diff --git a/.bzrignore b/.bzrignore new file mode 100644 index 000000000..64aa4c93e --- /dev/null +++ b/.bzrignore @@ -0,0 +1,171 @@ +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 deleted file mode 100644 index 33ffaa404..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -po/exclude.pot binary diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f6a1bd051..000000000 --- a/.gitignore +++ /dev/null @@ -1,277 +0,0 @@ -# -# 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 -*.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 -/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/modinfo.sh -/grub-core/rs_decoder.h -/grub-core/symlist.c -/grub-core/symlist.h -/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-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 -/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 deleted file mode 100644 index 4bd05a30a..000000000 --- a/.travis.yml +++ /dev/null @@ -1,109 +0,0 @@ -# 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 new file mode 100644 index 000000000..866b904ec --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,223 @@ +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-2015 b/ChangeLog similarity index 85% rename from ChangeLog-2015 rename to ChangeLog index 869f6bfb8..81bdae957 100644 --- a/ChangeLog-2015 +++ b/ChangeLog @@ -1,8996 +1,3 @@ -2015-01-23 Vladimir Serbinenko - - * tests/file_filter/file: Really add missing file. - -2015-01-23 Andrei Borzenkov - - * grub-core/disk/xen/xendisk.c: Accept hdX as disk names on Xen to - allow legacy menu.lst processing. - -2015-01-22 Felix Janda - - Remove direct _llseek code and require long filesystem libc. - -2015-01-20 Vladimir Serbinenko - - Remove potential division by 0 in gfxmenu. - -2015-01-20 Vladimir Serbinenko - - * grub-core/normal/menu_text.c (grub_menu_init_page): Avoid - returning 0 geometry to avoid divisions by 0. - -2015-01-20 Vladimir Serbinenko - - * grub-core/osdep/unix/cputime.c (grub_util_get_cpu_time_ms): Cache - sc_clk_tck and check it for sanity. - -2015-01-20 Vladimir Serbinenko - - * grub-core/kern/efi/mm.c (grub_efi_get_memory_map): Never return a - descriptor_size==0 to avoid potential divisions by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/osdep/haiku/getroot.c (grub_util_find_partition_start_os): - Avoid division by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/kern/generic/rtc_get_time_ms.c (grub_rtc_get_time_ms): Avoid - division by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (guessfsb): Avoid division by 0. - -2015-01-20 Vladimir Serbinenko - - * grub-core/kern/i386/tsc.c (calibrate_tsc): Ensure that - no division by 0 occurs. - -2015-01-20 Vladimir Serbinenko - - * include/grub/misc.h (grub_div_roundup): Remove as it's unused. - -2015-01-20 Vladimir Serbinenko - - * grub-core/term/gfxterm.c: Avoid division by zero. - -2015-01-20 Vladimir Serbinenko - - Avoid division by zero in serial. - - * grub-core/term/serial.c (grub_cmd_serial): Ensure speed is not 0. - * grub-core/term/ns8250.c (serial_get_divisor): Exit if speed is 0. - -2015-01-20 Vladimir Serbinenko - - * grub-core/video/readers/jpeg.c: Avoid sivision by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c: Validate volumes to avoid division - by zero. - -2015-01-20 Vladimir Serbinenko - - * include/grub/term.h: Avoid returining 0-sized terminal - as it may lead to division by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/zfs.c: Avoid divisions by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/btrfs.c: Avoid divisions by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/lib/pbkdf2.c (grub_crypto_pbkdf2): Check that hash len is not 0. - -2015-01-20 Vladimir Serbinenko - - * grub-core/osdep/linux/blocklist.c (grub_install_get_blocklist): Check - blocksize validity. - -2015-01-20 Vladimir Serbinenko - - * grub-core/disk/i386/pc/biosdisk.c: Check disk size sanity. - -2015-01-20 Vladimir Serbinenko - - * grub-core/disk/ieee1275/nand.c (grub_nand_open): Check block size - validity. - -2015-01-20 Vladimir Serbinenko - - * grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Do not - divide by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/hfs.c (grub_hfs_mount): Additional filesystem - sanity checks. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/minix.c: Additional filesystem - sanity checks. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext2_mount): Additional - checks for superblock validity. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_mount): Check - that sblock.ino_per_group is not 0. - -2015-01-20 Vladimir Serbinenko - - Reject NILFS2 superblocks with over 1GiB blocks. - - * grub-core/fs/nilfs2.c (grub_nilfs2_valid_sb): Check that - block size is <= 1GiB. - -2015-01-20 Vladimir Serbinenko - - * grub-core/disk/ata.c (grub_ata_setaddress): Check that geometry - is sane when using CHS addressing. - -2015-01-20 Vladimir Serbinenko - - * grub-core/disk/AFSplitter.c (AF_merge): Check that mdlen is not 0. - -2015-01-20 Vladimir Serbinenko - - * grub-core/commands/i386/pc/play.c (grub_cmd_play): Avoid - division by zero. - -2015-01-20 Vladimir Serbinenko - - * grub-core/bus/usb/usbtrans.c (grub_usb_bulk_maxpacket): Avoid - potentially returning 0. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/minix.c (grub_minix_read_file): Avoid reading past - the end of file. - -2015-01-20 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (grub_fshelp_read_file): Don't attempt to read - past the end of file. - -2015-01-20 Vladimir Serbinenko - - * grub-core/script/lexer.c (grub_script_lexer_yywrap): Update len - synchronously with line. - -2015-01-20 Vladimir Serbinenko - - Replace explicit sizeof divisions by ARRAY_SIZE. - -2015-01-19 Kris Moore - - * grub-core/disk/geli.c: Support GELI v6 and v7. - -2014-12-09 Andrei Borzenkov - - * grub-core/term/serial.c (grub_cmd_serial): Fix --rtscts - option processing. - -2014-12-07 David Kozub - - * grub-core/kern/arm/misc.S: fix unaligned 64bit local variable - in __aeabi_uidivmod - Fixes Savannah bug #43632. - -2014-12-07 Peter Nelson - - * grub-core/fs/ext2.c (grub_ext2_read_block): Support large sparse - chunks. - -2014-12-07 Andrei Borzenkov - - * util/grub-mkconfig_lib.in (version_test_gt): Remove redundant - non-portable '-n' echo option. - * util/grub.d/10_kfreebsd.in: Change how list is built to avoid - non-portable 'echo -n. - * util/grub.d/10_linux.in: Likewise (closes 43668). - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Print spaces directly to avoid - non-portable 'echo -n'. - -2014-12-07 Curtis Larsen - - * grub-core/net/tcp.c (grub_net_recv_tcp_packet): Fix double - free when multiple empty segments were received (closes 42765). - -2014-12-05 Andrei Borzenkov - - * tests/util/grub-shell.in: Support --files also for netboot. - * tests/file_filter_test.in: New file with file filters tests. - * Makefile.util.def: Add file_filter_test. - * conf/Makefile.extra-dist: ... and here. - * tests/file_filter/file.gz: Test file for file_filter_test. - * tests/file_filter/file.gz.sig: Likewise. - * tests/file_filter/file.lzop: Likewise. - * tests/file_filter/file.lzop.sig: Likewise. - * tests/file_filter/file.xz: Likewise. - * tests/file_filter/file.xz.sig: Likewise. - * tests/file_filter/keys: Likewise. - * tests/file_filter/keys.pub: Likewise. - * tests/file_filter/test.cfg: Likewise. - * grub-core/commands/verify.c: Fix memory corruption doing - signature check for network files (closes 43601). - -2014-12-01 Andrei Borzenkov - - * grub-core/loader/i386/xen_fileXX.c (grub_xen_get_infoXX): Fix - memory leak (CID 73645, 73782). - * grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Fix memory leak - (CID 73635). - -2014-11-30 Andrei Borzenkov - - * grub-core/lib/syslinux_parse.c (free_menu): Do not free - inline array (CID 73610). - -2014-11-28 Andrei Borzenkov - - * grub-core/io/lzopio.c (test_header): Fix double free (CID 73665) - * grub-core/disk/geli.c (configure_ciphers): Fix memory leaks - (Coverity CID 73813, 73710) - * grub-core/disk/luks.c (configure_ciphers): Fix memory leaks - and use after free (Coverity CID 73813, 73710, 73730) - * grub-core/disk/luks.c (luks_recover_key): Fix memory leak (Coverity - CID 73854) - * util/grub-install-common.c (grub_install_get_target): Check return - value of grub_util_fd_read (Coverity CID 73819). - * util/grub-mkstandalone.c (add_tar_file): Fix out of bound access - to hd.magic (Coverity CID 73587, 73888, bug 43690). - -2014-11-20 Andrei Borzenkov - - * tests/util/grub-fs-tester.in: Consistently print output - of grub ls if test fails. - -2014-11-07 Leif Lindholm - - * grub-core/kern/efi/init.c: check value of *path before - dereferencing. - -2014-11-03 Michael Chang - - * grub-core/net/icmp6.c (grub_net_recv_icmp6_packet): Fix size - of neighbor solicitation packet in grub_netbuff_pull. - -2014-10-14 Andrei Borzenkov - - * grub-core/loader/arm/linux.c: Use full initializer for initrd_ctx to - avoid fatal warnings with older gcc (probably before 4.7). - * grub-core/loader/arm64/linux.c: Likewise. - * grub-core/loader/i386/linux.c: Likewise. - * grub-core/loader/i386/pc/linux.c: Likewise. - * grub-core/loader/ia64/efi/linux.c: Likewise. - * grub-core/loader/mips/linux.c: Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c: Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c: Likewise. - -2014-09-25 Colin Watson - - Fix in-tree --platform=none - - * configure.ac: Only remove include/grub/cpu and - include/grub/machine in the --platform=none case, not all of - include/grub. - -2014-09-23 Colin Watson - - Add a new "none" platform that only builds utilities - - * configure.ac: Add "none" platform. Default to it for unsupported - CPUs rather than stopping with a fatal error. Don't downgrade - x86_64-none to i386. Define COND_real_platform Automake conditional - if the platform is anything other than "none". Don't do any include - directory linking for "none". - * Makefile.am: Skip building grub-core and all bootcheck targets if - !COND_real_platform. - * include/grub/time.h: Don't include if GRUB_UTIL - is defined. - -2014-09-22 Andrei Borzenkov - - Use grub_cpu_to_XXX_compile_time for constants. - -2014-09-21 Valentin Dornauer - - The AML parser implements only a small subset of possible AML - opcodes. On the Fujitsu Lifebook E744 this and another bug in - the parser (incorrect handling of TermArg data types) would lead - to the laptop not turning off (_S5 not found). - - * grub-core/commands/acpihalt.c: Support OpAlias in the AML parser; - in skip_ext_op(), handle some Type2Opcodes more correctly (TermArgs - aren't always simply strings!); Add function to skip TermArgs - * include/grub/acpi.h: Add new opcodes - -2014-09-21 Vladimir Serbinenko - - * grub-core/normal/main.c: Don't drop to rescue console in - case of password-protected prompt and no menu entries. - -2014-09-21 Vladimir Serbinenko - - * grub-core/commands/keylayouts.c: Ignore unknown keys. - -2014-09-21 Vladimir Serbinenko - - * grub-core/gmodule.pl.in: Accept newer binutils which output - empty column rather than 0x0. - -2014-09-21 Michael Chang - - * grub-core/osdep/unix/config.c: Remove extraneous comma. - -2014-09-21 Peter Jones - - * grub-core/loader/arm/linux.c: Initialized initrd_ctx so - we don't free a random pointer from the stack. - * grub-core/loader/arm64/linux.c: Likewise. - * grub-core/loader/i386/linux.c: Likewise. - * grub-core/loader/i386/pc/linux.c: Likewise. - * grub-core/loader/ia64/efi/linux.c: Likewise. - * grub-core/loader/mips/linux.c: Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c: Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c: Likewise. - -2014-09-15 Khem Raj - - * grub-core/kern/emu/hostfs.c: use _DEFAULT_SOURCE in addition to - _BSD_SOURCE to avoid warnings under glibc 2.20+. - -2014-09-08 Michael Chang - - * grub-core/fs/btrfs.c (grub_btrfs_extent_read): Fix extent size - check; comparing &data->extent against addresses in the region it - points to is unpredictable. - -2014-09-07 Colin Watson - - Support grub-emu on x32 (ILP32 but with x86-64 instruction set) - - * configure.ac: Remove -m64 from checks for -mcmodel=large and - -mno-red-zone. These are always either unnecessary (x86_64-emu) or - already in TARGET_CFLAGS at this point, and they produce incorrect - results when building for x32. - * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Cast - pointers to Elf64_Xword via grub_addr_t, in order to work on x32. - * include/grub/x86_64/types.h (GRUB_TARGET_SIZEOF_VOID_P, - GRUB_TARGET_SIZEOF_LONG): Define to 4 on x32. - -2014-09-07 Colin Watson - - * configure.ac: Remove several unnecessary semicolons. - -2014-08-25 Colin Watson - - * grub-core/kern/mips/arc/init.c (grub_machine_get_bootlocation): - Initialise pend to pacify GCC. - -2014-08-14 Andrey Borzenkov - - * util/grub-mkconfig.in: Fix typo (gettext_print instead of - gettext_printf). - -2014-08-13 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c: Retry probing keyboard if - scancode setup failed. - -2014-08-10 Vladimir Serbinenko - - * grub-core/kern/disk_common.c: Clump disk size to 1EiB. - -2014-08-10 Vladimir Serbinenko - - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_rw): Add - safety to avoid triggerring VirtualBox bug. - -2014-08-10 Vladimir Serbinenko - - * grub-core/fs/cbfs.c: Don't probe disks of unknow size. - - Fixes hang on virtualbox. - -2014-07-08 Colin Watson - - * util/grub.d/10_hurd.in: Make kernel list progression not fail on - kernels whose paths contain regex metacharacters. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - - Reported by: Heimo Stranner. - -2014-06-26 Colin Watson - - * docs/grub-dev.texi (Finding your way around): The build system no - longer uses AutoGen directly. - -2014-06-21 Роман Пехов - - * grub-core/commands/loadenv.c (check_blocklists): Fix overlap check. - -2014-06-21 Glenn Washburn - - * util/grub-install.c: Fix handling of --disk-module. - -2014-06-21 Stephane Rochoy - - * grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass pointer to - EFI system table. - -2014-06-21 Stephane Rochoy - - * grub-core/commands/efi/lsefisystab.c (grub_cmd_lsefisystab): Show - EFI system table physical address. - -2014-06-21 Trevor Woerner - - * util/grub-gen-asciih.c (add_glyph): Fix uninitialised variable. - -2014-06-21 Vladimir Serbinenko - - * grub-core/commands/verify.c (grub_pubkey_open): Trust procfs. - -2014-06-21 Vladimir Serbinenko - - * grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk - check. - -2014-04-20 Vladimir Serbinenko - - * grub-core/kern/misc.c (__bzero): Don't compile in GRUB_UTIL. - - Reported by: Yves Blusseau . - -2014-04-20 Piotr Krysiuk - - * grub-core/lib/i386/relocator.c: Allow loading old kernels by placing - GDT in conventional memory. - -2014-04-10 Colin Watson - - * util/grub.d/30_os-prober.in: Tolerate devices with no filesystem - UUID. Other parts of grub-mkconfig tolerate these, they were - previously allowed here up to commit - 55e706c918922def17f5012c23cfe88c4c645208, and they can arise in - practice when the system has active LVM snapshots. - Fixes Ubuntu bug #1287436. - -2014-04-10 Colin Watson - - * grub-core/disk/lvm.c (grub_lvm_detect): Search for - "logical_volumes" block a little more accurately. - -2014-04-06 Vladimir Serbinenko - - * grub-core/lib/syslinux_parse.c: Fix timeout quoting. - -2014-04-04 Vladimir Serbinenko - - * include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no longer - pulled from libgcc. - -2014-04-04 Vladimir Serbinenko - - Replace few instances of memcmp/memcpy in the code that should be - grub_memcmp/grub_memcpy. - -2014-04-03 Vladimir Serbinenko - - * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Support NVMe - device names. - -2014-03-31 Thomas Falcon - - btrfs: fix get_root key comparison failures due to endianness - - * grub-core/fs/btrfs.c (get_root): Convert - GRUB_BTRFS_ROOT_VOL_OBJECTID to little-endian. - -2014-03-31 Colin Watson - - Fix partmap, cryptodisk, and abstraction handling in grub-mkconfig. - - Commit 588744d0dc655177d5883bdcb8f72ff5160109ed caused grub-mkconfig - no longer to be forgiving of trailing spaces on grub-probe output - lines, which among other things means that util/grub.d/10_linux.in - no longer detects LVM. To fix this, make grub-probe's output - delimiting more consistent. As a bonus, this improves the coverage - of the -0 option. - - Fixes Debian bug #735935. - - * grub-core/disk/cryptodisk.c - (grub_util_cryptodisk_get_abstraction): Add a user-data argument. - * grub-core/disk/diskfilter.c (grub_diskfilter_get_partmap): - Likewise. - * include/grub/cryptodisk.h (grub_util_cryptodisk_get_abstraction): - Update prototype. - * include/grub/diskfilter.h (grub_diskfilter_get_partmap): Likewise. - * util/grub-install.c (push_partmap_module, push_cryptodisk_module, - probe_mods): Adjust for extra user-data arguments. - * util/grub-probe.c (do_print, probe_partmap, probe_cryptodisk_uuid, - probe_abstraction): Use configured delimiter. Update callers. - -2014-03-31 Colin Watson - - * util/grub-probe,c (options): Make -0 work again (broken by - conversion to argp). - (main): Simplify logic. - -2014-03-26 Vladimir Serbinenko - - * grub-core/lib/relocator.c: Fix the case when end of leftover is used. - -2014-03-26 Fu Wei - - * grub-core/loader/arm64/linux.c: Remove redundant "0x". - -2014-02-28 Vladimir Serbinenko - - * include/grub/i386/openbsd_bootarg.h: Add addr and frequency fields. - * grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Fill addr field. - - Suggested by: Markus Müller. - -2014-02-28 Vladimir Serbinenko - - * grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map - if E820 failed to return any regions. - -2014-02-28 Vladimir Serbinenko - - * grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]: Ignore low - tables for low memory calculations. - -2014-02-28 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): Limit - location to 640K. - -2014-02-28 Vladimir Serbinenko - - * grub-core/kern/i386/coreboot/mmap.c: Filter out 0xa0000-0x100000 - region. - -2014-02-20 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI - exclusively. - -2014-02-04 Paulo Flabiano Smorigo - - Add bootpath parser for open firmware. - - It enables net boot even when there is no bootp/dhcp server. - - * grub-core/net/drivers/ieee1275/ofnet.c: Add grub_ieee1275_parse_bootpath - and call it at grub_ieee1275_net_config_real. - * grub-core/kern/ieee1275/init.c: Add bootpath to - grub_ieee1275_net_config. - * include/grub/ieee1275/ieee1275.h: Likewise. - - -2014-02-04 Paulo Flabiano Smorigo - - Add grub_env_set_net_property function. - - * grub-core/net/bootp.c: Remove set_env_limn_ro. - * grub-core/net/net.c: Add grub_env_set_net_property. - * include/grub/net.h: Likewise. - -2014-02-03 Vladimir Serbinenko - - * util/grub-mkrescue.c: Build fix for argp.h with older gcc. - -2014-02-03 Vladimir Serbinenko - - * util/grub-mkfont.c: Build fix for argp.h with older gcc. - -2014-01-29 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Increase timeout. Some SSDs take up to - 7 seconds to recover if last poweroff was bad. - -2014-01-29 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Properly handle transactions with no - transferred data. - -2014-01-29 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Add safety cleanups. - -2014-01-29 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Allocate and clean space for all possible 32 - slots to avoid pointing to uninited area. - -2014-01-29 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Do not enable I/O decoding and keep - enabling busmaster for the end. - -2014-01-29 Vladimir Serbinenko - - * util/grub-mkfont.c: Downgrade warnings about unhandled features - to debug. - -2014-01-29 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c: Tolerate missing keyboard. - -2014-01-29 Paulo Flabiano Smorigo - - * .gitignore: add missing files and .exe variants. - -2014-01-26 Mike Gilbert - - grub-install: support for partitioned partx loop devices. - - * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Detect - /dev/loopX as being the parent of /dev/loopXpY. - -2014-01-26 Vladimir Serbinenko - - * grub-core/term/serial.c (grub_serial_register): Fix invalid free. - Ensure that pointers are inited to NULL and that pointers are not - accessed after free. - -2014-01-25 Andrey Borzenkov - - * include/grub/crypto.h: Replace __attribute__ ((format (printf)) with - __attribute__ ((format (__printf__)) to fix compilation under MinGW-w64. - * include/grub/emu/misc.h: ... and here. - * include/grub/err.h: ... and here. - * util/import_gcry.py: ... and here (in files g10lib.h). - -2014-01-25 Andrey Borzenkov - - * util/grub-mkimage.c: Make prefix argument mandatory. - -2014-01-24 Vladimir Serbinenko - - Fix several translatable strings. - - Suggested by: D. Prévot. - -2014-01-24 Vladimir Serbinenko - - * util/grub-install.c: List available targets. - -2014-01-23 Colin Watson - - * util/grub-install.c (write_to_disk): Add an info message. - -2014-01-21 Andrey Borzenkov - - * Makefile.am: Allow adding extra files to generated Windows ZIP - archive by setting GRUB_WINDOWS_EXTRA_DIST. - -2014-01-21 Andrey Borzenkov - - * configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype. - Show detected font path in summary. - -2014-01-21 Paulo Flabiano Smorigo - - * grub-core/net/arp.c (grub_net_arp_send_request): Increase network try - interval gradually. - * grub-core/net/icmp6.c (grub_net_icmp6_send_request): Likewise. - * grub-core/net/net.c (grub_net_fs_read_real): Likewise. - * grub-core/net/tftp.c (tftp_open): Likewise. - * include/grub/net.h (GRUB_NET_INTERVAL_ADDITION): New define. - -2014-01-21 Paulo Flabiano Smorigo - - * grub-core/net/net.c (receive_packets): Change stop condition to avoid - infinite loops. - - In net/net.c there is a while (1) that only exits if there is a stop - condition and more then 10 packages or if there is no package received. - - If GRUB is idle and enter in this loop, the only condition to leave is - if it doesn't have incoming packages. In a network with heavy traffic - this never happens. - -2014-01-19 Colin Watson - - * grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Ignore - EPERM when modifying kern.geom.debugflags. It is only a problem for - such things as installing GRUB to the MBR, in which case there'll be - an error later anyway, not for opening files during tests. - -2014-01-18 Andrey Borzenkov - - * grub-core/Makefile.am: Build grub_emu_init.[ch] from MODULE_FILES - instead of MOD_FILES. - * grub-core/genemuinit.sh: Simplify stripping of suffix so it works - both with and without .exe. - * grub-core/genemuinitheader.sh: Same. - -2014-01-18 Vladimir Serbinenko - - * util/grub-install.c: Fix a typo. - -2014-01-18 Vladimir Serbinenko - - * grub-core/normal/main.c (read_config_file): Buffer config file. - Reduces boot time. - -2014-01-18 Andrey Borzenkov - - * acinclude.m4 (grub_CHECK_LINK_DIR): Check that we can also remove - symbolic link to directory. It fails in Msys shell on Windows 2003. - -2014-01-18 Vladimir Serbinenko - - * Makefile.am (default_payload.elf): Add modules - multiboot cbmemc linux16 gzio echo help. - -2014-01-18 Mike Gilbert - - * Makefile.util.def: Link grub-ofpathname with zfs libs. - -2014-01-18 Vladimir Serbinenko - - * grub-core/commands/macbless.c: Rename FILE and DIR to avoid - conflicts. - - Reported by: Andrey Borzenkov. - -2014-01-18 Andrey Borzenkov - - * include/grub/misc.h: Move macros for compiler features to ... - * include/grub/compiler.h: ... new file. - * include/grub/list.h: Include instead of . - * grub-core/commands/fileXX.c: Include . - * grub-core/efiemu/prepare.c: Include . - * grub-core/loader/i386/xen_file.c: Include . - * grub-core/loader/i386/xen_fileXX.c: Include . - * grub-core/video/capture.c: Include . - * include/grub/command.h: Include . - * include/grub/dl.h: Include . - * include/grub/procfs.h: Include . - -2014-01-18 Andrey Borzenkov - - * configure.ac: Add support for BUILD_EXEEXT and use it ... - * Makefile.am: ... here. - * Makefile.util.def: ... and here. - * grub-core/Makefile.am: ... and here. - -2014-01-18 Andrey Borzenkov - - * include/grub/osdep/hostfile_windows.h: Use _W64 instead of - FILE_OFFSET_BITS to differentiate between native MinGW and Mingw W64. - -2014-01-18 Vladimir Serbinenko - - * grub-core/term/terminfo.c: Recognize keys F1-F12. - -2014-01-18 Andrey Borzenkov - - * configure.ac: Add support for BUILD_LDFLAGS. - * Makefile.am: Use BUILD_LDFLAGS for build time programs here ... - * grub-core/Makefile.am: ... and here. - * INSTALL: Mention BUILD_LDFLAGS. - -2014-01-18 Vladimir Serbinenko - - * util/grub-mount.c: Extend GCC warning workaround to grub-mount. - -2014-01-18 Vladimir Serbinenko - - * grub-core/kern/efi/efi.c: Ensure that the result starts with / - and has no //. - -2014-01-18 Vladimir Serbinenko - - * NEWS: Add few missing entries. - -2014-01-17 Colin Watson - - * util/grub.d/00_header.in (make_timeout): Use && rather than test - -a. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/10_netbsd.in (netbsd_load_fs_module): Use || rather - than test -o. - * util/grub.d/30_os-prober.in: Use && rather than test -a, and || - rather than test -o. - -2014-01-17 Colin Watson - - * grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove - redundant preprocessor conditional. - -2014-01-08 Colin Watson - - * Makefile.util.def (grub-macbless): Change mansection to 8. - -2014-01-07 Leif Lindholm - - * grub-core/loader/arm64/linux.c: correctly set device path end length. - -2014-01-07 Andrey Borzenkov - - * util/grub-install.c: Use bootaa64.efi instead of bootaarch64.efi on - arm64 to comply with EFI specification. Also use grubaa64.efi for - consistency. - * util/grub-mkrescue.c: Change to use bootaa64.efi too. - -2014-01-07 Andrey Borzenkov - - * include/grub/osdep/hostfile_windows.h: Do not redefine fseeko/ftello - on MinGW-64 when compiling for 32 bits. - -2013-12-30 Andrey Borzenkov - - * grub-core/Makefile.core.def: strip .eh_frame section for arm64-efi. - -2013-12-30 Vladimir Serbinenko - - * NEWS: Add few missing entries. Correct existing ones. - -2013-12-28 Vladimir Serbinenko - - Don't abort() on unavailable coreboot tables if not running on coreboot. - -2013-12-28 Andrey Borzenkov - - * grub-core/kern/emu/misc.c: Remove unused error.h; fixes compilation - on mingw. - -2013-12-28 Colin Watson - - * NEWS: The cmosclean command in fact dates back to 1.99. Remove - mention of it from 2.02. - -2013-12-27 Vladimir Serbinenko - - * grub-core/kern/arm/cache_armv6.S: Remove .arch directive. - - As these functions are used on pre-ARMv6 CPUs as well we don't want - to make assembler assume that architecture is higher than default one. - -2013-12-27 Colin Watson - - * NEWS: First draft of 2.02 entry. - -2013-12-27 Colin Watson - - * INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes. - * docs/grub.texi (Getting the source code): Likewise. - -2013-12-25 Andrey Borzenkov - - * grub-core/osdep/windows/platform.c (get_platform): Fix EFI - detection. - -2013-12-24 Vladimir Serbinenko - - * configure.ac: Set version to 2.02~beta2. - -2013-12-24 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c (name_devices): Skip Apple ghosts. - -2013-12-24 Andrey Borzenkov - - * util/grub-probe.c: Improve help message and simplify list handling. - -2013-12-24 Vladimir Serbinenko - - Fix buffer overflow in grub_efi_print_device_path. - -2013-12-24 Vladimir Serbinenko - - Show SATA device path. - -2013-12-24 Vladimir Serbinenko - - Revert grub-file usage in grub-mkconfig. - -2013-12-24 Vladimir Serbinenko - - Make newly-created files other than grub.cfg world-readable. - -2013-12-24 Andrey Borzenkov - - * util/grub.d/00_header.in: Improve compatibility with old config. - -2013-12-24 Vladimir Serbinenko - - Make rijndael.c respect aliasing rules. - - Trivial backport of dfb4673da8ee52d95e0a62c9f49ca8599943f22e. - -2013-12-24 Vladimir Serbinenko - - Make grub_util_device_is_mapped_stat available in grub-emu core. - -2013-12-24 Vladimir Serbinenko - - Add -Qn to TARGET_CFLAGS if it's supported. - Fixes compilation on cygwin. - - Reported by: Andrey Borzenkov. - Suggested by: Andrey Borzenkov. - -2013-12-24 Vladimir Serbinenko - - Save TARGET_CC version in modinfo.sh. - - Suggested by: Andrey Borzenkov. - -2013-12-24 Vladimir Serbinenko - - Make grub_util_devmapper_part_to_disk and grub_util_find_partition_start - follow the same algorithm to avoid method mismatch. Don't assume - DMRAID- UUID to mean full disk but instead check that mapping is linear. - -2013-12-24 Vladimir Serbinenko - - Declare GRUB_EFI_VENDOR_APPLE_GUID. - -2013-12-24 Vladimir Serbinenko - - Dump type and vendor specific data when printing device path. - -2013-12-23 Colin Watson - - Update some documentation to refer to Git rather than Bazaar. - - * docs/grub.texi (Obtaining and Building GRUB): Refer to Git rather - than Bazaar. - * po/README: Likewise. Fix spelling mistake. - -2013-12-23 Colin Watson - - Don't distribute config.h. - - * Makefile.am (platform_HEADERS): Move to ... - (nodist_platform_HEADERS): ... here. Fixes gettext_strings_test - failure when building from a distributed tarball. - -2013-12-23 Colin Watson - - * configure.ac: Fix spelling. - * grub-core/commands/parttool.c: Fix grammar. - * grub-core/disk/ldm.c: Use consistent capitalisation for "LDM - Embedding Partition". - -2013-12-23 Vladimir Serbinenko - - ARM64 support for grub-mkrescue. - -2013-12-23 Vladimir Serbinenko - - Install modinfo.sh to keep build information around. - -2013-12-23 Vladimir Serbinenko - - * grub-core/modinfo.sh.in: Add build config information. - -2013-12-23 Vladimir Serbinenko - - ARM64 grub-file and grub-mkconfig support. - -2013-12-23 Vladimir Serbinenko - - Remove leftover options defines. - -2013-12-23 Vladimir Serbinenko - - * include/grub/arm64/linux.h: Remove leftovers. Add missing prefixes. - -2013-12-23 Vladimir Serbinenko - - * grub-core/loader/arm64/linux.c: Add missing bracket. - -2013-12-23 Vladimir Serbinenko - - Add arm64-efi recognition to grub-file. - -2013-12-23 Vladimir Serbinenko - - Fix ia64-efi recognition in grub-file. - -2013-12-23 Vladimir Serbinenko - - Recognize raspberry pi kernel in grub-file. - -2013-12-23 Vladimir Serbinenko - - Enable cache on ARM U-Boot port. - - Without it the port is reidiculously slow. - -2013-12-23 Vladimir Serbinenko - - Fix ARM cache maintainance. - - More code was converted from ASM to C for easier handling. - -2013-12-22 Vladimir Serbinenko - - * grub-core/kern/arm/cache.c (grub_arm_disable_caches_mmu): Use v6 - algorithm on v5. - - Suggested by: Leif Lindholm. - -2013-12-22 Andrey Borzenkov - - * util/grub-mkconfig.in: Fix Xen platform conditions. - -2013-12-22 Andrey Borzenkov - - * util/grub-mkrescue.c: Split single help message string in several - strings used in previous shell version. - -2013-12-22 Leif Lindholm - - Add arm64 Linux loader. - -2013-12-22 Leif Lindholm - - Add grub_fdt_create_empty_tree() and grub_fdt_set_prop64(). - -2013-12-22 Vladimir Serbinenko - - Add module loading and parsing boot time checkpoints. - -2013-12-22 Vladimir Serbinenko - - * grub-core/loader/arm/linux.c: Pass arguments through on ATAG - platforms. - -2013-12-22 Lars Wendler - - * util/grub-mkconfig.in: Skip non-executable files. - -2013-12-22 Vladimir Serbinenko - - Workaround buggy timer in raspberry pie by using our own timer - implementation. - -2013-12-22 Vladimir Serbinenko - - * include/grub/arm/uboot/kernel.h (GRUB_KERNEL_MACHINE_HEAP_SIZE): - Increase to 16 MiB to allow loading the whole memdisk. - -2013-12-22 Vladimir Serbinenko - - Fix ARM Linux Loader on non-FDT platforms. - -2013-12-21 Vladimir Serbinenko - - * configure.ac: Choose link format based on host_os on emu. - -2013-12-21 Vladimir Serbinenko - - * grub-core/osdep/unix/getroot.c: Non-unix build fix. - -2013-12-21 Vladimir Serbinenko - - * grub-core/kern/emu/main.c: Build fix for emu. - -2013-12-21 Vladimir Serbinenko - - Build fixes for argp.h with older gcc. - -2013-12-21 Vladimir Serbinenko - - * util/grub-glue-efi.c: Use "universal binary" rather "fat binary" - in strings. - - Suggested by: David Prévot. - -2013-12-21 Vladimir Serbinenko - - * include/grub/crypto.h (grub_crypto_xor): Fix cast-align warning. - -2013-12-21 Vladimir Serbinenko - - Enable -Wformat=2 if it's supported. - -2013-12-21 Vladimir Serbinenko - - * configure.ac: Add -Wmissing-include-dirs -Wmissing-prototypes - -Wmissing-declarations if supported. - -2013-12-21 Vladimir Serbinenko - - * grub-core/commands/macbless.c (grub_mac_bless_inode): Pass inode as - u32 as both HFS and HFS+ have 32-bit inodes. - -2013-12-21 Vladimir Serbinenko - - * include/grub/misc.h (grub_strtol): Fix overflow. - -2013-12-21 Vladimir Serbinenko - - * include/grub/term.h (grub_unicode_estimate_width): Use grub_size_t - as return type in both conditionals. - -2013-12-21 Vladimir Serbinenko - - * include/grub/video.h (grub_video_rgba_color_rgb): Fix prototype - to use uint8_t for color. - -2013-12-21 Vladimir Serbinenko - - * util/misc.c (grub_util_get_image_size): Check for overflow. - -2013-12-21 Vladimir Serbinenko - - * grub-core/disk/raid6_recover.c (grub_raid_block_mulx): Use grub_size_t - for size. - -2013-12-21 Vladimir Serbinenko - - * grub-core/disk/lvm.c: Use grub_size_t for sizes and grub_ssize_t - for pointer difference. - -2013-12-21 Vladimir Serbinenko - - * util/import_gcry.py: Skip sample keys. - -2013-12-21 Vladimir Serbinenko - - * util/misc.c (grub_qsort_strcmp): Don't discard const attribute. - -2013-12-21 Vladimir Serbinenko - - * configure.ac: Remove duplicate warning arguments. - -2013-12-21 Vladimir Serbinenko - - Add missing static qualifiers. - -2013-12-21 Vladimir Serbinenko - - Add missing includes. - -2013-12-21 Vladimir Serbinenko - - Inline printf templates when possible to enable format checking. - -2013-12-21 Vladimir Serbinenko - - * include/grub/crypto.h: Don't discard const attribute. - -2013-12-21 Vladimir Serbinenko - - * grub-core/net/bootp.c (grub_cmd_dhcpopt): Use snprintf where it - was intended. - -2013-12-21 Vladimir Serbinenko - - * grub-core/lib/crypto.c: Don't discard const attribute. - -2013-12-21 Vladimir Serbinenko - - * grub-core/lib/disk.c: Fix potential overflow. - -2013-12-21 Vladimir Serbinenko - - * grub-core/lib/arg.c: Don't discard const attribute. - -2013-12-21 Vladimir Serbinenko - - * grub-core/kern/dl.c: Don't discard const attribute. - -2013-12-21 Vladimir Serbinenko - - * grub-core/kern/disk.c: Fix potential overflow. - -2013-12-21 Vladimir Serbinenko - - * conf/Makefile.common: Don't include non-existing directory - grub-core/lib/libgcrypt-grub/include. - -2013-12-21 Vladimir Serbinenko - - Clarify several translatable messages. - -2013-12-21 David Prévot - - Correct some translatable strings. - -2013-12-21 Colin Watson - - * util/grub-mkrescue.c: Rephrase mkrescue description. - -2013-12-21 Vladimir Serbinenko -2013-12-21 Colin Watson - - Clarify several translatable messages. - -2013-12-20 Colin Watson - - Be more verbose about some configure failures. - -2013-12-20 Colin Watson - - Fix various build problems on GNU/Hurd. - - * grub-core/osdep/unix/getroot.c (strip_extra_slashes): Move inside - !defined (__GNU__). - (xgetcwd): Likewise. - * include/grub/emu/hostdisk.h (grub_util_hurd_get_disk_info) - [__GNU__]: Add prototype. - * util/getroot.c (grub_util_biosdisk_get_grub_dev) [__GNU__]: Format - long int using %ld rather than %d. - -2013-12-18 Vladimir Serbinenko - - * util/grub-install.c: Inform user about install platform. - -2013-12-18 Vladimir Serbinenko - - * configure.ac: Set version to 2.02~beta1. - -2013-12-18 Allen Pais -2013-12-18 Bob Picco - - * grub-core/boot/sparc64/ieee1275/boot.S: Fix order of fields. - -2013-12-18 Vladimir Serbinenko - - Make grub_zlib_decompress handle incomplete chunks. - - Fixes squash4. - -2013-12-18 Vladimir Serbinenko - - * grub-core/Makefile.am: Don't attempt to export grub_bios_interrupt - on i386-multiboot. - -2013-12-18 Aleš Nesrsta - - * grub-core/disk/usbms.c: Retry on unknown errors. - Reuse the same tag on retries. - -2013-12-18 Aleš Nesrsta - - * grub-core/bus/usb/ehci.c: Fix handling of newborn transfers. - - Avoid confusing them with already completed transfers. - -2013-12-18 Vladimir Serbinenko - - Remove xen VFB. - - Due to XEN bug it prevents Linux boot. Remove it at least, until - workaround is found. - -2013-12-18 Vladimir Serbinenko - - * po/exclude.pot: Add 2 missing excludes. - -2013-12-18 Vladimir Serbinenko - - Add missing license section in macbless.mod and macho.mod. - -2013-12-18 Vladimir Serbinenko - - Allow compilation without thumb-interwork as long as no thumb is - involved or only thumb2 is used. - -2013-12-18 Vladimir Serbinenko - - * INSTALL: Update comment as to why sparc64 clang isn't usable. - -2013-12-18 Vladimir Serbinenko - - Add __attribute__ ((sysv_abi)) only if it's really needed. - - Some compilers don't support it. - -2013-12-18 Vladimir Serbinenko - - * grub-core/lib/syslinux_parse.c: Declare timeout unsigned. - -2013-12-18 Vladimir Serbinenko - - Remove -Wold-style-definition. - - Not very useful and interaction of it with regexp depends on GCC - version. - -2013-12-18 Vladimir Serbinenko - - Make grub_util_get_windows_path_real static. - -2013-12-18 Vladimir Serbinenko - - * grub-core/commands/fileXX.c: Silence cast-align. - * grub-core/loader/i386/xen_fileXX.c: Likewise. - -2013-12-18 Vladimir Serbinenko - - * include/grub/efi/api.h (GRUB_EFI_ERROR_CODE): Use explicit cast - rather than LL suffix. - -2013-12-18 Vladimir Serbinenko - - * include/grub/efi/api.h (PRIxGRUB_EFI_UINTN_T): Remove leftover. - -2013-12-18 Vladimir Serbinenko - - * grub-core/loader/arm/linux.c: Use common initrd functions. - -2013-12-18 Vladimir Serbinenko - - Decrease number of strings to translate. - -2013-12-18 Vladimir Serbinenko - - * grub-core/kern/arm/dl.c: Remove unnecessarry execution mode check. - -2013-12-18 Vladimir Serbinenko - - Mark strings for translation and add remaining ones to exclude list. - -2013-12-18 Vladimir Serbinenko - - * util/grub-file.c (main): Fix sizeof usage. - -2013-12-18 Vladimir Serbinenko - - Silence spurious warning. - -2013-12-18 Vladimir Serbinenko - - Remove check_nt_hiberfil as it's been superseeded by file command. - -2013-12-17 Vladimir Serbinenko - - * docs/osdetect.cfg: Add isolinux config to detected OSes. - -2013-12-17 Vladimir Serbinenko - - Implement syslinux parser. - -2013-12-17 Vladimir Serbinenko - - * grub-core/commands/legacycfg.c: Use 32-bit Linux protocol on non-BIOS. - -2013-12-17 Vladimir Serbinenko - - Support cpuid --pae. - -2013-12-17 Vladimir Serbinenko - - Use AT keyboard on Yeeloong 3A. - -2013-12-17 Vladimir Serbinenko - - Add Yeeloong 3A reboot and halt. - -2013-12-17 Vladimir Serbinenko - - Add Radeon Yeeloong 3A support. - -2013-12-17 Vladimir Serbinenko - - Add bonito 3A support. - -2013-12-17 Vladimir Serbinenko - - * grub-core/loader/machoXX.c: Fix compilation on non-i386. - -2013-12-17 Vladimir Serbinenko - - * grub-core/loader/i386/xen_fileXX.c: Silence cast-align. - -2013-12-17 Vladimir Serbinenko - - * grub-core/loader/macho.c: Fix compilation on non-i386. - -2013-12-17 Vladimir Serbinenko - - Add missing format_arg attribute to check that printf with translated - messages has proper arguments. - -2013-12-17 Vladimir Serbinenko - - Use grub_xasprintf to format translated error messages containing - 64-bit quantity. - -2013-12-17 Jon McCune - - Fix double-free introduced by commit 33d02a42d64cf06cada1c389 - -2013-12-17 Vladimir Serbinenko - - Unify message for unsupported relocation. - -2013-12-17 Vladimir Serbinenko - - Mark miscompile error for translation. - -2013-12-17 Vladimir Serbinenko - - Use %I64 and not %ll when using OS printf if compiling for windows. - -2013-12-17 Vladimir Serbinenko - - Update Mac code to match new register_efi prototype. - -2013-12-17 Vladimir Serbinenko - - Implement better integration with Mac firmware. - -2013-12-17 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c: Implement special value for - load_addr. - -2013-12-17 Vladimir Serbinenko - - Include serial module in default_payload.elf. - -2013-12-17 Vladimir Serbinenko - - Add explicit thumb interwork bx in asm files. - - Shouldn't matter for armv >= 5 but let's be safe. - -2013-12-17 Vladimir Serbinenko - - Implement Truecrypt ISO loader. - -2013-12-17 Vladimir Serbinenko - - * grub-core/lib/arg.c: Ensure at least a single space between commands. - -2013-12-17 Vladimir Serbinenko - - Implement grub_file tool and use it to implement generating of config - in separate root. - -2013-12-17 Vladimir Serbinenko - - Change to v1 xen grants. - -2013-12-17 Vladimir Serbinenko - - * grub-core/lib/i386/xen/relocator.S: Fix hypercall ABI violation. - - GRUB relied on %ebx being preserved across hypercall which isn't true. - -2013-12-17 Vladimir Serbinenko - - * grub-core/lib/x86_64/xen/relocator.S: Fix hypercall ABI violation. - - GRUB relied on %rdi being preserved across hypercall which isn't true. - -2013-12-17 Vladimir Serbinenko - - Implement XEN VFB support. - -2013-12-17 Vladimir Serbinenko - - Remove grub_bios_interrupt on coreboot. - - It's not used currently and cannot be used safely currently. - -2013-12-16 Vladimir Serbinenko - - Update exclude.pot and mark few strings for translation. - -2013-12-16 Vladimir Serbinenko - - * util/grub-mkrescue.c: Fix incorrect file usage in fallback code. - - Reported by: Jon McCune - -2013-12-16 Andrey Borzenkov - - * grub-core/osdep/linux/platform.c (grub_install_get_default_x86_platform): - Add verbose information which firmware directories were tried. - -2013-12-16 Andrey Borzenkov - - * grub-core/osdep/unix/exec.c (grub_util_exec_redirect_all): New - function to optionally redirect all three standard descriptors. - Redefine grub_util_exec, grub_util_exec_redirect and - grub_util_exec_redirect_null to use it. - * include/grub/emu/exec.h: Define it. - * include/grub/osdep/exec_unix.h: Delete, it is unused. - * grub-core/osdep/linux/platform.c (grub_install_get_default_x86_platform): - Use grub_util_exec_redirect_all to redirect error to NULL. - -2013-12-16 Vladimir Serbinenko - - * grub-core/tests/sleep_test.c: Silence spurious warning. - -2013-12-16 Vladimir Serbinenko - - Make grub_xen_hypercall on i386 cdecl rather than stdcall to avoid - linker trying to "fixup" the code. - -2013-12-16 Vladimir Serbinenko - - * grub-core/kern/x86_64/xen/startup.S: Align stack. - -2013-12-16 Vladimir Serbinenko - - Add support for converting PE+ to Elf64. - -2013-12-16 Vladimir Serbinenko - - * grub-core/commands/minicmd.c (grub_mini_cmd_dump): Handle LLP case. - -2013-12-16 Vladimir Serbinenko - - Remove practice of assigning random const pointers to device id. - - This is not required as cache code already checks driver id as well. - -2013-12-16 Vladimir Serbinenko - - * include/grub/x86_64/types.h: Define sizeof (long) as 4 when compiling - with mingw. - -2013-12-16 Vladimir Serbinenko - - * include/grub/efi/api.h: Don't use call wrappers when compiled with - mingw or cygwin as API already matches. - -2013-12-16 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/errno.h: Undefine errno before redefining. - -2013-12-16 Vladimir Serbinenko - - * include/grub/efi/api.h: Define (u)intn_t based on pointer size and - not on long. - -2013-12-16 Vladimir Serbinenko - - Handle X86_64_PC64 relocation. - - Those are generated by some cygwin compilers. - -2013-12-16 Vladimir Serbinenko - - Determine the need for mingw-related stubs at compile time rather than - using not very significant $target_os. - -2013-12-16 Vladimir Serbinenko - - * grub-core/genmod.sh.in: Strip before converting to ELF as strip - may not work with ELF. - -2013-12-16 Vladimir Serbinenko - - Use unix functions for temporary files and special files on cygwin. - -2013-12-16 Vladimir Serbinenko - - Define functions explicitly rather than using --defsym in tests - whenever possible. Respect locality in remaining cases. - -2013-12-16 Vladimir Serbinenko - - * grub-core/genmoddep.awk: Remove explicit getline < /dev/stdin. - -2013-12-15 Andrey Borzenkov - - * grub-core/osdep/windows/platform.c (grub_install_register_efi): Handle - unlikely errors when getting EFI variables and make exhaustive search - for all BootNNNN variables to find matching one. - -2013-12-15 Ian Campbell - - * grub-core/kern/uboot/init.c: Fix units of uboot timer. - -2013-12-15 Vladimir Serbinenko - - New functional test for sleep function. - - This test allows to check sleep without qemu. Keep qemu version as - well as functional test won't notice if all clocks are going too fast - or too slow. - -2013-12-15 Vladimir Serbinenko - - Add explicit sysv_abi on amd64 asm routines. - -2013-12-15 Vladimir Serbinenko - - * grub-core/commands/efi/lsefisystab.c: Use %lld to show - num_table_entries. - -2013-12-15 Vladimir Serbinenko - - * include/grub/test.h: Use gnu_printf rather than printf on GRUB - functions. - -2013-12-15 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c: Use grub_addr_t rather than long when - appropriate. - -2013-12-15 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c: Use %p rather than %lx for pointers. - -2013-12-15 Vladimir Serbinenko - - * grub-core/kern/elfXX.c: Use grub_addr_t rather than long when - appropriate. - -2013-12-15 Vladimir Serbinenko - - * grub-core/disk/loopback.c: Use sequential IDs rather than pointer. - - In case of quick removal of loopback and adding another one it may - get same ID, confusing the cache system. - -2013-12-15 Vladimir Serbinenko - - * grub-core/commands/acpi.c: Use grub_addr_t rather than long when - appropriate. - -2013-12-15 Vladimir Serbinenko - - * grub-core/kern/i386/coreboot/cbtable.c: Use char * arithmetic rather - than converting to long. - -2013-12-15 Vladimir Serbinenko - - * grub-core/disk/cryptodisk.c: Rename "n" to "last_cryptodisk_id". - -2013-12-15 Vladimir Serbinenko - - * util/grub-mkimagexx.c (relocate_addresses): Display offset rather - than almost useless pointer. - -2013-12-15 Vladimir Serbinenko - - Add gcc_struct to all packed structures when compiling with mingw. - - Just "packed" doesn't always pack the way we expect. - -2013-12-14 Vladimir Serbinenko - - * include/grub/i386/coreboot/lbio.h: Add missing attribute (packed). - -2013-12-14 Vladimir Serbinenko - - * util/grub-pe2elf.c: Fix handling of .bss. - -2013-12-14 Vladimir Serbinenko - - Implement windows flavour of EFI install routines. - -2013-12-14 Vladimir Serbinenko - - * conf/Makefile.extra-dist: Adjust path to conf/i386-cygwin-img-ld.sc. - -2013-12-14 Vladimir Serbinenko - - Change grub_install_register_efi interface to pass GRUB device. - - This allows grub_install_register_efi to request partition info - directly. - -2013-12-14 Vladimir Serbinenko - - Workaround cygwin bug when using \\?\Volume{GUID} syntax. - -2013-12-14 Vladimir Serbinenko - - Do not use TCHAR string functions as they are not available on cygwin. - -2013-12-14 Vladimir Serbinenko - - Workaround windows bug when querying EFI system partition parameters. - -2013-12-14 Vladimir Serbinenko - - * grub-core/kern/i386/qemu/init.c (resource): Decrease struct size - by using bitfields. - -2013-12-14 Vladimir Serbinenko - - * grub-core/boot/i386/qemu/boot.S: Add missing EXT_C. - -2013-12-14 Vladimir Serbinenko - - Make i386-* other than i386-pc compileable under cygwin. - -2013-12-14 Vladimir Serbinenko - - Fix definition of grub_efi_hard_drive_device_path. Take care that - existing code would work even if by some reason bogus definition is - used by EFI implementations. - -2013-12-14 Vladimir Serbinenko - - * grub-core/osdep/windows/hostdisk.c: Fix cygwin compilation. - -2013-12-14 Vladimir Serbinenko - - * grub-core/osdep/windows/blocklist.c: Add missing cast in printf - invocation. - -2013-12-14 Vladimir Serbinenko - - * util/config.c: Remove trailing newline from distributor in simple - parsing. - -2013-12-14 Vladimir Serbinenko - - * include/grub/efi/api.h: Rename protocol and interface to avoid - conflict. - -2013-12-14 Vladimir Serbinenko - - * .gitignore: add .exe variants. add missing files. remove few outdated - entries. - -2013-12-14 Vladimir Serbinenko - - * grub-core/osdep/exec.c: Use unix version on cygwin. - -2013-12-13 Vladimir Serbinenko - - Implement multiboot2 EFI BS specification. - -2013-12-11 Vladimir Serbinenko - - * grub-core/normal/charset.c: Fix premature line wrap and crash. - Crash happened only in some cases like a string starting at the - half of the screen of same length. - -2013-12-11 Vladimir Serbinenko - - * include/grub/efiemu/efiemu.h: Sync configuration table declaration - with EFI counterpart. - -2013-12-11 Vladimir Serbinenko - - Propagate the EFI commits to x86-efi specific parts. - -2013-12-11 Vladimir Serbinenko - - * grub-core/commands/efi/lssal.c: Fix terminating condition. - -2013-12-11 Vladimir Serbinenko - - Introduce grub_efi_packed_guid and use it where alignment is not - guaranteed. - -2013-12-11 Vladimir Serbinenko - - * include/grub/efi/api.h (grub_efi_device_path): Define length as - unaligned u16 rather than u8[2]. - -2013-12-11 Vladimir Serbinenko - - * grub-core/kern/ia64/dl.c (grub_arch_dl_relocate_symbols): Add checks - for relocation range. - -2013-12-11 Vladimir Serbinenko - - * grub-core/kern/ia64/dl.c (grub_arch_dl_relocate_symbols): Handle - non-function pcrel21b relocation. It happens with .text.unlikely - section. - -2013-12-10 Leif Lindholm - - * make MAX_USABLE_ADDRESS platform-specific - * grub-core/kern/efi/mm.c: add Vladimir's new BYTES_TO_PAGES_DOWN macro. - -2013-12-10 Leif Lindholm - - * grub-core/lib/fdt.c: change memcpy => grub_memcpy - -2013-12-09 Jon McCune - - * Add --no-rs-codes flag to optionally disable reed-solomon codes - in grub-install and grub-bios-setup for x86 BIOS targets. - -2013-12-09 Vladimir Serbinenko - - Add missing compile and link options for sparc64-emu. - -2013-12-09 Vladimir Serbinenko - - Implement sparc64 trampolines (needed for sparc64-emu). - -2013-12-09 Vladimir Serbinenko - - * grub-core/kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Check - range of R_SPARC_HI22. - Implement R_SPARC_LM22. - -2013-12-09 Vladimir Serbinenko - - * grub-core/kern/powerpc/dl_helper.c (grub_arch_dl_get_tramp_got_size): - Do not explicitly check for symbol table as it's already checked in - platform-independent layer. - -2013-12-09 Vladimir Serbinenko - - * grub-core/kern/emu/cache.c [__ia64__]: Use our cache cleaning routine - on ia64 as __clear_cache is a dummy on ia64. - -2013-12-09 Vladimir Serbinenko - - * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): - Do not explicitly check for symbol table as it's already checked in - platform-independent layer. - -2013-12-09 Colin Watson - - * util/grub-mkconfig.in: Add missing newline to output. - -2013-12-08 Vladimir Serbinenko - - * grub-core/kern/ia64/efi/init.c (grub_arch_sync_caches): Move to ... - * grub-core/kern/ia64/cache.c (grub_arch_sync_caches): ... here. - -2013-12-08 Vladimir Serbinenko - - * grub-core/kern/emu/main.c: Silence missing prototypes to allow emu - compilation with GCC <= 4.2. - * grub-core/kern/emu/argp_common.c: Likewise. - -2013-12-08 Vladimir Serbinenko - - * include/grub/kernel.h [__sparc__]: Restrict sparc64-ieee1275 to - right platform rather than leaking to sparc64-emu. - -2013-12-08 Vladimir Serbinenko - - * grub-core/osdep/windows/emuconsole.c: Remove unsigned comparison >= 0. - But ensure that the variables in question are indeed unsigned. - -2013-12-08 Vladimir Serbinenko - - * grub-core/kern/emu/lite.c: Add missing include of ../ia64/dl_helper.c. - -2013-12-08 Vladimir Serbinenko - - Remove grub_memalign on emu. - -2013-12-08 Vladimir Serbinenko - - * grub-core/kern/ia64/efi/init.c: Fix alignment code so it doesn't - truncate incomplete lines but instead flushes them. - -2013-12-08 Vladimir Serbinenko - - Move OS-dependent mprotect for module loading to grub-core/osdep/*/dl.c - and implement windows variant. - -2013-12-08 Vladimir Serbinenko - - Fix mips-emu compilation. - -2013-12-08 Vladimir Serbinenko - - * configure.ac: Check for freetype library usability. - -2013-12-08 Vladimir Serbinenko - - Make arm-emu work. - -2013-12-07 Vladimir Serbinenko - - * util/grub-mkfont.c: Replace stpcpy with grub_stpcpy. - -2013-12-07 Andrey Borzenkov - - * docs/grub.texi (Environment): Update color_normal and color_highlight - defaults (light-gray instead of white). - -2013-12-07 Andrey Borzenkov - - * grub-core/normal/main.c (INIT): Set default color to light-gray - to match GRUB_TERM_DEFAULT_NORMAL_COLOR (i.e. rescue mode), Linux - and apparently BIOS defaults. - -2013-12-07 Vladimir Serbinenko - - Transform -C option to grub-mkstandalone to --core-compress available - in all grub-install flavours. - -2013-12-07 Vladimir Serbinenko - - Merge GRUBFS and GRUB_FS variables. - -2013-12-07 Andrey Borzenkov - - Revert commit 69ca97c820, it caused failures when using OS device name - in grub-install. Instead just strip off parenthesis in grub-install - if (hdX) was passed. - -2013-12-07 Andrey Borzenkov - - * util/grub-install.c (push_partmap_module): Add helper to convert - partmap names to module names and use it in probe_mods(). Fixes - failure to find partmap modules in diskfilter case. - -2013-12-07 Vladimir Serbinenko - - * configure.ac: Make unifont mandatory on coreboot. - -2013-12-07 Vladimir Serbinenko - - * configure.ac: Skip unifont 6.3 pcf and bdf. - -2013-12-07 Vladimir Serbinenko - - * Makefile.am: Remove partial font files if generation failed. - -2013-12-07 Andrey Borzenkov - - * util/misc.c (grub_qsort_strcmp): Add qsort helper function to sort - strings. - * include/grub/util/misc.h: Define it ... - * util/grub-install.c (device_map_check_duplicates): ... and use it. - -2013-12-07 Andrey Borzenkov - - * util/grub.d/30_os-prober.in: Fix use of grub-probe instead of - ${grub_probe}. - -2013-12-06 Vladimir Serbinenko - - Don't add -mlong-calls when compiling with clang. - -2013-12-06 Vladimir Serbinenko - - * configure.ac: Fix a typo. - -2013-12-06 Vladimir Serbinenko - - Revamp relocation handling. - - Move more code to common dl.c. Add missing veneers for arm and arm64. - Decreases kernel size by 70 bytes on i386-pc (40-50 compressed) - -2013-12-05 Vladimir Serbinenko - - * util/grub-mkimagexx.c: Fix reloc section generation for ia64. - -2013-12-05 Mike Gilbert - - * INSTALL: Raise minimum python version to 2.6. - * gentpl.py: Use python3-style print function. - -2013-12-05 Vladimir Serbinenko - - * util/grub-install.c: Mention Boot* variable. - -2013-12-05 Colin Watson - - * grub-core/osdep/linux/hostdisk.c - (grub_util_find_partition_start_os): Initialise start to avoid - spurious compiler warning. - -2013-12-05 Colin Watson - - On Linux, read partition start offsets from sysfs if possible, to - cope with block device drivers that don't implement HDIO_GETGEO. - Fixes Ubuntu bug #1237519. - - * grub-core/osdep/linux/hostdisk.c (sysfs_partition_path): New - function. - (sysfs_partition_start): Likewise. - (grub_util_find_partition_start_os): Try sysfs_partition_start - before HDIO_GETGEO. - -2013-12-05 Leif Lindholm - - * grub-core/kern/fdt.c: Update struct size when adding node. - -2013-12-05 Vladimir Serbinenko - - Handle unaligned .bss on sparc64. - - Current code improperly assumes that both __bss_start and _end are - aligned to 8-bytes. Eliminating this assumption and explicitly align - modules. - -2013-12-04 Vladimir Serbinenko - - * grub-core/boot/sparc64/ieee1275/boot.S [CDBOOT]: Move scratchpad - so it doesn't land in the middle of loaded image. - -2013-12-04 Vladimir Serbinenko - - * configure.ac: Move all warning options that may be absent in - gcc >= 3.1 to optional. - - Note: while this allows to compile with older GCC, official requirements - remain the same and no support for older GCC. - -2013-12-04 Colin Watson - - Copying the themes directory in grub-shell isn't - parallel-test-friendly and breaks on the second test when the source - directory is read-only (as in "make distcheck"). Instead, add a - hidden --themes-directory option to grub-mkrescue et al, and use it - in grub-shell. - -2013-12-04 Vladimir Serbinenko - - * conf/Makefile.common (CFLAGS_GNULIB): Remove -Wno-old-style-definition - as it's no longer necessarry. - -2013-12-04 Vladimir Serbinenko - - * configure.ac: Allow compilation with older GCC for ARM. - -2013-12-04 Vladimir Serbinenko - - * configure.ac: Add -no-integrated-as if {addme|ame} isn't supported. - * INSTALL: Note that GRUBwas successfully compiled with clang 3.2 for - ppc. - -2013-12-04 Vladimir Serbinenko - - * grub-core/kern/emu/main.c: Ignore missing prototype for main. - -2013-12-04 Vladimir Serbinenko - - Pass font config to config.h and not by TARGET_CFLAGS as adding - arguments doesn't work if TARGET_CFLAGS is specified on command - line. - -2013-12-04 Vladimir Serbinenko - - * configure.ac: Add -Wvla if compiler supports it. - -2013-12-04 Vladimir Serbinenko - - * grub-core/osdep/windows/emuconsole.c (grub_console_putchar): - Remove variable length arrays. - * grub-core/term/efi/console.c (grub_console_putchar): Likewise. - -2013-12-04 Vladimir Serbinenko - - * grub-core/kern/i386/qemu/init.c: Remove variable length arrays. - -2013-12-04 Vladimir Serbinenko - - * include/grub/types.h: Declare all byteswaps as inline functions - except compile-time ones. - - Solves variable shadowing in constructions like - cpu_to_le (le_to_cpu(x) + 1). - -2013-12-04 Vladimir Serbinenko - - * grub-core/kern/efi/efi.c: Remove variable length arrays. - -2013-12-04 Vladimir Serbinenko - - * grub-core/kern/uboot/init.c (uboot_timer_ms): Fix overflow after 71 - minutes. - -2013-12-04 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c: Remove variable length arrays. - * grub-core/net/drivers/ieee1275/ofnet.c: Likewise. - -2013-12-03 Colin Watson - - * grub-core/Makefile.core.def (setjmp): Distribute - lib/arm64/setjmp.S. - -2013-12-03 Colin Watson - - Add a new timeout_style environment variable and a corresponding - GRUB_TIMEOUT_STYLE configuration key for grub-mkconfig. This - controls hidden-timeout handling more simply than the previous - arrangements, and pressing any hotkeys associated with menu entries - during the hidden timeout will now boot the corresponding menu entry - immediately. - - GRUB_HIDDEN_TIMEOUT= + GRUB_TIMEOUT= now - generates a warning, and if it shows the menu it will do so as if - the second timeout were not present. Other combinations are - translated into reasonable equivalents. - - Based loosely on work by Franz Hsieh. Fixes Ubuntu bug #1178618. - -2013-12-02 Vladimir Serbinenko - - * util/config.c: Add missing pointer adjustment. - Reported by: qwertial - -2013-11-30 Andrey Borzenkov - - * grub-core/kern/arm64/dl_helper.c: Include grub/arm64/reloc.h - directly, not via `cpu' link, to fix libgrub.pp generation. - -2013-11-30 Leif Lindholm - - New port arm64-efi. - -2013-11-30 Andrey Borzenkov - - * docs/grub.texi (sleep): Document exit codes. - -2013-11-30 Vladimir Serbinenko - - Ensure that -mno-unaligned-access or some equivalent option is used. - -2013-11-30 Vladimir Serbinenko - - * grub-core/lib/libgcrypt/mpi/longlong.h: Fix compilation error with - -march=armv3. - -2013-11-30 Vladimir Serbinenko - - Remove leftover GRUB_IA64_DL_TRAMP_SIZE. - -2013-11-29 Colin Watson - - * docs/grub-dev.texi (Font Metrics): Exclude @image command from DVI - builds, since we don't have an EPS version of font_char_metrics.png. - Add leading dot to image extension per the Texinfo documentation. - -2013-11-29 Colin Watson - - * util/grub-gen-asciih.c: Include FT_SYNTHESIS_H rather than - , fixing build with FreeType 2.5.1. - * util/grub-gen-widthspec.c: Likewise. - * util/grub-mkfont.c: Likewise. - -2013-11-29 Andrey Borzenkov - - * util/grub-setup.c (main): Move parsing of (hdX) syntax to ... - * util/setup.c (SETUP): ... here. Fixes regression: grub-install - failed to install on (hdX). - * util/grub-setup.c (get_device_name): Remove, not needed after - above change. - -2013-11-29 Vladimir Serbinenko - - * grub-core/kern/emu/hostfs.c (is_dir): Remove variable length arrays. - -2013-11-29 Vladimir Serbinenko - - * util/grub-fstest.c: Remove variable length arrays. - -2013-11-29 Vladimir Serbinenko - - * grub-core/osdep/linux/ofpath.c: Check return value of read. - -2013-11-29 Vladimir Serbinenko - - * util/mkimage.c (grub_install_generate_image): Use grub_crypto_hash for - computing crc32 rather than handling with md fundtions directly. - -2013-11-29 Vladimir Serbinenko - - * util/mkimage.c (grub_install_generate_image): Use grub_crypto_hash for - checking fwstart.img rather than md fundtions directly. - -2013-11-29 Vladimir Serbinenko - - * util/grub-mkrescue.c (main): Check that fread succeeded. - -2013-11-29 Vladimir Serbinenko - - * conf/Makefile.common: Remove -mexplicit-relocs and - -DUSE_ASCII_FALLBACK on yeeloong. - - -DUSE_ASCII_FALLBACK is already added by font snippets. - -mexplicit-relocs isn't needed is compiler/assemblera are - configured properly. - If they're not we shouldn't attempt to fix it by ourselves. - Binary compare between before and after shows no difference. - -2013-11-29 Vladimir Serbinenko - - * grub-core/Makefile.core.def: Remove libgnulib.a and use its - sources in dependencies directly. - - This was the only instance of "library" in core config. A bug was - reported that -fno-stack-protector wasn't passed to it. Instead of - figuring out why it failed just remove this construction used - needlessly. - -2013-11-29 Vladimir Serbinenko - - * grub-core/osdep/unix/password.c (grub_password_get): Check that - fgets succeeded. - -2013-11-27 Francesco Lavra - - * docs/grub.texi (ls): Fix command description in case of a device name - passed as argument. - -2013-11-27 Vladimir Serbinenko - - Eliminate variable length arrays in grub_vsnprintf_real. - - A bit tricky because this function has to continue to work without - heap for short strings. Fixing prealloc to 32 arguments is reasonable - but make all stack references use 32-bit offset rather than 8-bit one. - So split va_args preparsing to separate function and put the prealloc - into the caller. - -2013-11-27 Vladimir Serbinenko - - Introduce grub_util_file_sync and use it instead of fsync(fileno(f)). - Fixes build for windows. - -2013-11-27 Vladimir Serbinenko - - * gentpl.py: Don't generate platform-dependent conditionals for - platform-independent targets. - -2013-11-27 Colin Watson - - * grub-core/osdep/unix/exec.c (grub_util_exec_redirect): Remove - references to mdadm from otherwise generic code. - (grub_util_exec_pipe): Likewise. - (grub_util_exec_pipe_stderr): Likewise. - * grub-core/osdep/unix/getroot.c (grub_util_pull_lvm_by_command): - This function calls vgs, not mdadm; adjust variable names - accordingly. - -2013-11-27 Colin Watson - - Generate Makefile.*.am directly from gentpl.py, eliminating the use - of Autogen. The Autogen definitions files remain intact as they - offer a useful abstraction. - -2013-11-27 Colin Watson - - Add grub_util_disable_fd_syncs call to turn grub_util_fd_sync calls - into no-ops, and use it in programs that copy files but do not need - to take special care to sync writes (grub-mknetdir, grub-rescue, - grub-mkstandalone). - -2013-11-26 Colin Watson - - * tests/util/grub-fs-tester.in: Execute xorriso from $PATH rather - than hardcoding /usr/local/bin/xorriso. - -2013-11-26 Vladimir Serbinenko - - Add PCI command activation to all PCI drivers as required for coreboot - and maybe some other firmwares. - -2013-11-26 Vladimir Serbinenko - - * grub-core/Makefile.am: Reduce gratuituous differences between Apple - and non-Apple variants of efiemu compile. - -2013-11-25 Andrey Borzenkov - - * configure.ac: Add explicit check for linking format of - efiemu64; save it as EFIEMU64_LINK_FORMAT. - * grub-core/Makefile.am: Use EFIEMU64_LINK_FORMAT instead of - hardcoding linking format. - -2013-11-25 Vladimir Serbinenko - - * util/grub-mknetdir.c: Look for platform directories under pkglibdir - and not pkgdatadir. - -2013-11-25 Colin Watson -2013-11-25 Vladimir Serbinenko - - Add a --locale-directory option to grub-install and related tools. - - * include/grub/util/install.h (GRUB_INSTALL_OPTIONS): Add - --locale-directory option. - (enum grub_install_options): Add - GRUB_INSTALL_OPTIONS_LOCALE_DIRECTORY. - * util/grub-install-common.c (grub_install_help_filter): Handle - GRUB_INSTALL_OPTIONS_LOCALE_DIRECTORY. - (grub_install_parse): Likewise. - (get_localedir): New function to check for a user-provided option - before trying grub_util_get_localedir. - (copy_locales): Use get_localedir rather than - grub_util_get_localedir. Handle differing locale directory layouts. - (grub_install_copy_files): Likewise. - -2013-11-25 Vladimir Serbinenko - - * grub-core/osdep/unix/platform.c (get_ofpathname): Trim ending newline. - Don't rely on PATH_MAX. - -2013-11-25 Vladimir Serbinenko - - * grub-core/genmoddep.awk: Use more portable && rather than and. - -2013-11-24 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S [__APPLE__]: Create _edata by placing - an object after data. While it doesn't seem right solution, it - works well enough and OSX isn't main compilation platform. - -2013-11-24 Vladimir Serbinenko - - * gentpl.py: Add -ed2016 in order to make objconv accept our binary. - While it doesn't seem right solution, it works well enough and - OSX isn't main compilation platform. - -2013-11-24 Vladimir Serbinenko - - * configure.ac: Add -static to LDFLAGS when using apple linker to - prevent it from pulling in dynamic linker. - -2013-11-24 Vladimir Serbinenko - - Apple assembly doesn't handle symbol arithmetic well. So define an - offset symbol in boot.S and use it. - -2013-11-24 Vladimir Serbinenko - - Apple assembly doesn't handle symbol arithmetic well. So instead - of getting addres of kernel_sector + 4 define kernel_sector_high. - It also makes code more readable. - -2013-11-24 Vladimir Serbinenko - - With Apple assembly in .macro environvemnt you have to use $$ instead - of $. So introduce new preprocessor macro MACRO_DOLLAR(x) which expands - to $$x on Apple and to $x on everything else. - -2013-11-24 Vladimir Serbinenko - - * grub-core/Makefile.am: Use correct TARGET_OBJCONV rather than - OBJCONV. - -2013-11-24 Vladimir Serbinenko - - * grub-core/gdb/i386/machdep.S: Use xorl %eax, %eax on both Apple - and non-Apple. This instruction is shorter and faster, - so no reason not to use it on both. - -2013-11-24 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c: Use section _text, _text rather than - .text when compiling for Apple. - -2013-11-24 Vladimir Serbinenko - - * grub-core/term/arc/console.c: Add missing cast to silence warning. - -2013-11-24 Vladimir Serbinenko - - * grub-core/boot/i386/pc/boot.S: Fix floppy probe. Due to missing - %dx restore the probe worked on non-existant drive. Reorganize the - code a little bit to free 2 bytes necessary for push/pop. - -2013-11-23 Vladimir Serbinenko - - * grub-core/kern/mips/arc/init.c (grub_machine_get_bootlocation): - Add missing cast to silence warning. - -2013-11-23 Keshav Padram Amburay - - * util/grub-install.c (update_nvram): Support --no-nvram flag - for EFI targets. - -2013-11-23 Vladimir Serbinenko - - * INSTALL: Add note about sparc64/ia64 with clang (unsupported). - -2013-11-23 Vladimir Serbinenko - - * util/garbage-gen.c: Add missing include of sys/time.h. - -2013-11-23 Vladimir Serbinenko - - Don't add -mflush-func if it's not supported by compiler. - -2013-11-23 Vladimir Serbinenko - - Move common BIOS/coreboot memory map declarations to - include/grub/i386/memory_raw.h and eliminate duplicate declarations. - -2013-11-22 Andrey Borzenkov - - * Makefile.am: Add util/garbage-gen.c to EXTRA_DIST. - -2013-11-22 Vladimir Serbinenko - - * INSTALL: Document why older clang versions aren't appropriate. - -2013-11-22 Vladimir Serbinenko - - * INSTALL: Document about clang for mips. - -2013-11-22 Vladimir Serbinenko - - * grub-core/lib/libgcrypt/mpi/longlong.h: Use C version with mips - clang. - -2013-11-22 Vladimir Serbinenko - - Add *-xen to the list of grub-install-common platforms. - -2013-11-22 Vladimir Serbinenko - - * configure.ac: Do not enforce -mcmodel=large. It's not necessarry with - 3 last commits. - -2013-11-22 Vladimir Serbinenko - - * grub-core/kern/xen/init.c: Do not map more pages than we can address. - -2013-11-22 Vladimir Serbinenko - - * grub-core/kern/efi/mm.c: Limit allocations to 2GiB when not compiling - with -mcmodel=large. - -2013-11-22 Vladimir Serbinenko - - * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Add - range-checking for 32-bit quantities. - -2013-11-22 Vladimir Serbinenko - - * configure.ac: Compile with -fPIC when compiling with clang on - mips. - -2013-11-22 Vladimir Serbinenko - - * configure.ac: Add -no-integrated-as on mips(el) to TARGET_CCASFLAGS - when compiling with clang. - -2013-11-22 Vladimir Serbinenko - - clang emits calls to abort () under some unknown conditions. - Export abort () when compiling with clang. - -2013-11-22 Vladimir Serbinenko - - * docs/grub-dev.texi: Document stack and heap sizes. - -2013-11-22 Vladimir Serbinenko - - * include/grub/i386/pc/memory.h: Decrease - GRUB_MEMORY_MACHINE_SCRATCH_SIZE and increase - GRUB_MEMORY_MACHINE_PROT_STACK_SIZE. - The binary doesn't change (checked). It's more to better reflect actual - usage. - -2013-11-22 Vladimir Serbinenko - - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_open): Ensure - at compile time that enough of scratch size is available. - -2013-11-22 Vladimir Serbinenko - - * grub-core/kern/x86_64/efi/callwrap.S: Fix stack alignment. - Previously we misaligned stack by 8 in startup.S and compensated - for it in callwrap.S. According to ABI docs (EFI and sysv amd64) - right behaviour is to align stack in startup.S and keep it aligned - in callwrap.S. startup.S part was committed few commits before. This - takes care of callwrap.S. - Reported by: Gary Lin. - -2013-11-22 Vladimir Serbinenko - - * grub-core/boot/mips/startup_raw.S: Handle the case of gap between - .data and .bss. May happen if compiler and assembly use different - alignment. - -2013-11-22 Vladimir Serbinenko - - On MIPS handle got16 relocations to local symbols in an ABI-compliant - way. - -2013-11-22 Vladimir Serbinenko - - Add support for a new magic symbol _gp_disp on mips to handle PIC - binaries. - -2013-11-22 Vladimir Serbinenko - - Use $t9 for indirect calls from asm to C as PIC ABI requires. - -2013-11-22 Vladimir Serbinenko - - Remove -march=mips3 from TARGET_CCASFLAGS as it creates linking problem - when rest of GRUB is compiled for hisher stepping. Instead use - .set mips3/.set mips1 around cache and sync opcodes. - -2013-11-21 Vladimir Serbinenko - - Unify GOT/trampoline handling between PPC, MIPS and IA64 as they - do essentially the same thing, do it in similar way. - -2013-11-21 Colin Watson - - * util/grub-mkrescue.c (main): If a source directory is not - specified, read platform-specific files from subdirectories of - pkglibdir, not pkgdatadir. - -2013-11-21 Colin Watson - - * grub-core/normal/progress.c: Remove unused file. - -2013-11-20 Vladimir Serbinenko - - * grub-core/lib/crypto.c (grub_crypto_hash): Remove variable length - array. - -2013-11-20 Vladimir Serbinenko - - * util/grub-mkconfig.in: Say explicit "grub configuration" rather - than grub.cfg. - -2013-11-20 Vladimir Serbinenko - - * coreboot.cfg: Add missing file. - -2013-11-19 Vladimir Serbinenko - - * Makefile.am: Allow STRIP to be empty when creating windowszip. - -2013-11-19 Axel Kellermann - - * util/grub.d/30_os-prober.in: Add GRUB_OS_PROBER_SKIP_LIST to - selectively skipping systems. - -2013-11-19 Colin Watson - - * Makefile.util.def (grub-mkimage): Add - grub-core/osdep/aros/config.c to extra_dist. - * conf/Makefile.extra-dist (EXTRA_DIST): Add docs/autoiso.cfg, - docs/osdetect.cfg, grub-core/gnulib-fix-null-deref.diff, - grub-core/gnulib-fix-width.diff, grub-core/gnulib-no-abort.diff, and - grub-core/gnulib-no-gets.diff. - -2013-11-19 Vladimir Serbinenko - - Add automated filesystem checking based on scripts I've used now for - quite some time locally. Most of the test require root so they are - skipped when run without necessarry privelegies. - -2013-11-19 Colin Watson - - * util/grub-install.c (main): Adjust info messages to match - installed paths of grub-bios-setup and grub-sparc64-setup. - -2013-11-19 Colin Watson - - * util/grub-install-common.c (copy_locales): Consistently use - grub_util_get_localedir () rather than LOCALEDIR. - (grub_install_copy_files): Likewise. - -2013-11-19 Josh Triplett - - * grub-core/kern/x86_64/efi/startup.S (_start): Align the stack to a - 16-byte boundary, as required by the x86-64 ABI, before calling - grub_main. In some cases, GCC emits code that assumes this - alignment, which crashes if not aligned. The EFI firmware is also - entitled to assume that stack alignment without checking. - -2013-11-18 Josh Triplett - - * grub-core/mmap/efi/mmap.c (grub_mmap_register): Round up/down to - 4k page boundaries as expected by firmware rather than 1k - boundaries. - (grub_mmap_malign_and_register): Likewise. - -2013-11-18 Vladimir Serbinenko - - * tests/grub_func_test.in: Decrease RAM size to 512M. With less - fragmentation 512M is enough. - -2013-11-18 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the - pointer to 32K. This is the size of cache element which is the most - common allocation >1K. This way the pointer is always around blocks - of 32K and so we keep performance while decreasing fragmentation. - -2013-11-18 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_real_malloc): Don't update the pointer to - current memory when allocating large chunks. This significantly - decreases memory fragmentation. - -2013-11-18 Colin Watson - - * tests/gzcompress_test.in: Skip if gzip is not installed (unlikely, - but for symmetry). - * tests/lzocompress_test.in: Skip if lzop is not installed. - * tests/xzcompress_test.in: Skip if xz is not installed. - -2013-11-18 Colin Watson - - * util/grub-mkrescue.c (main): Fix typo. - -2013-11-18 Vladimir Serbinenko - - * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Update - clock frequency to 200 MHz, - -2013-11-18 Vladimir Serbinenko - - * tests/util/grub-shell.in: Increase console size to 1024x1024. - -2013-11-18 Vladimir Serbinenko - - * Makefile.am (default_payload.elf): Add pata to loaded modules. - Load config file from (cbfsdisk)/etc/grub.cfg. - -2013-11-18 Vladimir Serbinenko - - * util/grub-install-common.c (grub_install_copy_files): Fix module - destination directory. - -2013-11-18 Colin Watson - - * tests/util/grub-shell.in: Don't fail on emu platform if po/*.gmo - files have not been built. - -2013-11-18 Colin Watson - - * grub-core/osdep/unix/hostdisk.c (grub_util_make_temporary_file): - Handle errors from mkstemp. - (grub_util_make_temporary_dir): Handle errors from mkdtemp. - -2013-11-18 Vladimir Serbinenko - - * tests/util/grub-shell.in: Use -cdrom and don't force cdrom - on primary master on pseries. - -2013-11-18 Vladimir Serbinenko - - * grub-core/tests/videotest_checksum.c: Don't reload unifont if it's - already loaded. This saves memory needed for tests, - -2013-11-18 Vladimir Serbinenko - - * util/grub-mkrescue.c (main): Fix a typo to make yeeloong part - work again. - -2013-11-18 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_cmd_terminfo): Fix a typo to make -g - work again. - -2013-11-18 Vladimir Serbinenko - - * tests/util/grub-shell.in: For powerpc tests put the CD-ROM as primary - master since with some combinations of qemu and firmware only primary - IDE channel is available. - -2013-11-18 Vladimir Serbinenko - - * grub-core/tests/gfxterm_menu.c: Skip high-resolution tests on - low-memory platforms where we don't have enough memory for them. - * grub-core/tests/videotest_checksum.c: Likewise. - -2013-11-18 Vladimir Serbinenko - - * grub-core/tests/cmdline_cat_test.c: Don't reload unifont if it's - already loaded. This saves memory needed for tests, - -2013-11-18 Vladimir Serbinenko - - Fix handling of install lists. - -2013-11-18 Vladimir Serbinenko - - * grub-core/lib/sparc64/setjmp.S: Force spilling of current window. - -2013-11-18 Vladimir Serbinenko - - On i386-ieee1275 we run in paged mode. So we need to explicitly map - the devices before accessing them. - -2013-11-18 Vladimir Serbinenko - - * grub-core/lib/relocator.c (grub_mm_check_real): Accept const char * - as file argument. - -2013-11-18 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (grub_cmdline_get): Plug memory leak. - -2013-11-18 Vladimir Serbinenko - - * grub-core/kern/file.c (grub_file_open): Free file->name on failure. - (grub_file_close): Free file->name. - -2013-11-18 Vladimir Serbinenko - - * grub-core/commands/verify.c (free_pk): Plug memory leak. - (grub_load_public_key): Likewise. - (grub_verify_signature_real): Likewise. - (grub_cmd_verify_signature): Likewise. - -2013-11-18 Vladimir Serbinenko - - * grub-core/commands/legacycfg.c (grub_legacy_check_md5_password): Plug - memory leak. - -2013-11-18 Vladimir Serbinenko - - * grub-core/lib/powerpc/setjmp.S (grub_setjmp): Save r31. - (grub_longjmp): Restore r31. - * include/grub/powerpc/setjmp.h (grub_jmp_buf): Reserve space for r31. - -2013-11-18 Vladimir Serbinenko - - * util/grub-mkrescue.c (make_image_fwdisk_abs): Insert all partmap - modules to be in line with make_image_abs. - -2013-11-18 Vladimir Serbinenko - - * include/grub/mips/setjmp.h (grub_jmp_buf): Fix buffer size. - - setjmp.S uses 12 entries but buffer is declared with only 11 entries. - -2013-11-17 Ian Campbell - - * grub-core/disk/uboot/ubootdisk.c: Include SCSI disks. - -2013-11-17 Vladimir Serbinenko - - * tests/grub_func_test.in: Increase memory reservation as on EFI we need - to leave some memory to firmware. - -2013-11-17 Vladimir Serbinenko - - * grub-core/tests/cmdline_cat_test.c (cmdline_cat_test): Ignore errors - of loading gfxterm as gfxterm is embed in kernel on some platforms. - * grub-core/tests/gfxterm_menu.c (gfxterm_menu): Likewise. - Load gfxmenu. - -2013-11-17 Vladimir Serbinenko - - * tests/core_compress_test.in: Use full arguments as grub-mkimage-extra - now needs full arguments. - -2013-11-17 Vladimir Serbinenko - - * util/grub-mkrescue.c (main): Add trailing \n in - .disk_label.contentDetails to be in line with previous shell script. - -2013-11-17 Vladimir Serbinenko - - * util/grub-mkrescue.c (main): Use right source file for bootinfo.txt. - -2013-11-17 Vladimir Serbinenko - - * util/grub-install-common.c (grub_install_parse): Recognize - --compress=none like shell script did. - -2013-11-17 Vladimir Serbinenko - - * include/grub/misc.h: Replace check for __sparc64__ with one for - __sparc__ as __sparc64__ isn't actually defined. - -2013-11-17 Vladimir Serbinenko - - * tests/util/grub-shell.in: Use escc-ch-b on powerpc. This is missing - counterpart of fixing the naming of escc ports. - -2013-11-17 Vladimir Serbinenko - - * util/grub-install-common.c (platforms): Fix the order of entries and - remove useless field val. - -2013-11-16 Vladimir Serbinenko - - * util/grub-install.c: Add new option --no-bootsector to skip - installing of bootsector. Accept --grub-setup=/bin/true as - backwards-compatible synonym. - -2013-11-16 Andrey Borzenkov - - * util/grub-install.c (device_map_check_duplicates): Fix incorrect - order of qsort arguments (number of elements vs. element size). - -2013-11-16 Vladimir Serbinenko - - Rewrite grub-install, grub-mkrescue, grub-mkstandalone and grub-mknetdir - the function of these files exceeds what can be sanely handled in shell - in posix-comaptible way. Also writing it in C extends the functionality - to non-UNIX-like OS and minimal environments. - -2013-11-16 Vladimir Serbinenko - - * grub-core/kern/arm/cache.S: Don't switch back to ARM mode when - compiling to thumb2. - * grub-core/kern/arm/cache_armv7.S: Likewise. - * grub-core/lib/arm/setjmp.S: Likewise. - -2013-11-16 Leif Lindholm - - * grub-core/kern/arm/uboot/startup.S: delete superflouous save of r8 - in grub_uboot_syscall - -2013-11-16 Vladimir Serbinenko - - Decrease stack usage in lexer. - - We have only 92K of stack and using over 4K per frame is wasteful - - * grub-core/script/yylex.l (yyalloc), (yyfree), (yyrealloc): Declare - as macros so that compiler would remove useless structure on stack. - Better solution would be to fix flex not to put this structure on - the stack but flex is external program. - -2013-11-16 Vladimir Serbinenko - - Decrease stack usage in signature verification. - - We have only 92K of stack and using over 4K per frame is wasteful - - * grub-core/commands/verify.c (grub_load_public_key): Allocate on heap - rather than stack. - (grub_verify_signature_real): Likewise. - -2013-11-16 Vladimir Serbinenko - - Decrease stack usage in mdraid 0.9x. - - We have only 92K of stack and using over 4K per frame is wasteful - - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Allocate on heap - rather than stack. - -2013-11-16 Vladimir Serbinenko - - Decrease stack usage in BtrFS. - - We have only 92K of stack and using over 4K per frame is wasteful - - * grub-core/fs/btrfs.c (grub_btrfs_lzo_decompress): Allocate on heap - rather than stack. - -2013-11-16 Vladimir Serbinenko - - Decrease stack usage in JFS. - - We have only 92K of stack and using over 4K per frame is wasteful - - * grub-core/fs/jfs.c (getblk): Allocate on heap rather than on - stack. Note: this function is recursive. - (grub_jfs_read_inode): Read only part we care about. - -2013-11-16 Leif Lindholm - - * grub-core/kern/arm/uboot/startup.S: fix grub_uboot_syscall va_arg - handling - -2013-11-16 Andrey Borzenkov - - * configure.ac: Restore -nostdlib for libgcc symbols tests. - -2013-11-16 Andrey Borzenkov - - * docs/grub.texi (Environment): Document cmdpath. - -2013-11-16 Andrey Borzenkov - - * grub-core/kern/mips/arc/init.c (grub_machine_get_bootlocation): - Remove "unused" attribute from arguments, they are used. - -2013-11-15 Colin Watson - - * .gitignore: Only ignore grub-mk* at the top level. - -2013-11-15 Colin Watson - - * util/grub-reboot.in (usage): Fix a typo. - -2013-11-15 Vladimir Serbinenko - - Replace libgcc version of ctz with our own. - - On upcoming arm64 port libgcc ctz* are not usable in standalone - environment. Since we need ctz* for this case and implementation is - in C we may as well use it on all concerned platforms. - -2013-11-14 Vladimir Serbinenko - - * configure.ac: Probe for linking format rather than guessing it based - on target_os. - -2013-11-14 Vladimir Serbinenko - - * grub-core/disk/xen/xendisk.c (grub_xendisk_fini): Set state to - "1" prior to handoff. - - Reported by: M A Young. - -2013-11-14 Vladimir Serbinenko - - * grub-core/kern/xen/init.c (grub_xenstore_write_file): Don't add - \0 to all files. - - Reported by: M A Young. - -2013-11-14 Vladimir Serbinenko - - * grub-core/osdep/bsd/hostdisk.c (grub_util_get_fd_size_os): Fix - compilation on NetBSD. - -2013-11-14 Vladimir Serbinenko - - * acinclude.m4: Don't add -P on initial nm test. - - Note: even though this patch postdates Andrey's it bears 14 Nov as - date due to timezone difference. - -2013-11-15 Andrey Borzenkov - - * grub-core/Makefile.core.def (signature_test): Add missing - tests/signatures.h. - -2013-11-14 Colin Watson - - * util/grub-install_header: Set localedir here, since this file is - where it's used. - * util/grub-install.in: Remove setting of localedir. - * util/grub-mkrescue.in: Likewise. - -2013-11-14 Vladimir Serbinenko - - * Makefile.am (default_payload.elf): Add uhci, ohci and usb_keyboard. - -2013-11-14 Vladimir Serbinenko - - * configure.ac: Move nm checks to the end. - Call grub_PROG_NM_WORKS. - * acinclude.m4: New check grub_PROG_NM_WORKS. - Use $TARGET_CFLAGS -c when compiling test binary. - -2013-11-14 Colin Watson - - * util/getroot.c (grub_util_biosdisk_get_grub_dev) [__GNU__]: Remove - unused variables. - -2013-11-14 Matthew Garrett - - * grub-core/kern/main.c (grub_set_prefix_and_root): Set variable - cmdpath to firmware directory. - -2013-11-14 Vladimir Serbinenko - - * grub-core/kern/efi/efi.c (grub_efi_get_filename): Reset the pointer - at the start of second iteration. - -2013-11-14 Vladimir Serbinenko - - * grub-core/Makefile.am (efiemu64.o): Explicitly set link format. - -2013-11-14 Vladimir Serbinenko - - * Makefile.am (default_payload.elf): New target for easier coreboot - build. - -2013-11-14 Vladimir Serbinenko - - * grub-core/kern/arm/cache_armv6.S: Remove special handling for - clang (not necessarry with -no-integrated-as). - * include/grub/symbol.h [__arm__]: Likewise. - -2013-11-14 Vladimir Serbinenko - - * configure.ac: Use -no-integrated-as on arm with clang. - * INSTALL: Mention ARM compilation with clang. - -2013-11-14 Vladimir Serbinenko - - * conf/Makefile.common (CCASFLAGS_PLATFORM) [COND_arm]: Add - -mthumb-interwork. - -2013-11-14 Colin Watson - - * grub-core/fs/ext2.c (grub_ext2_read_block): Factor out common - code for indirect block handling. - - Saves 185 bytes on compressed image. - -2013-11-13 Paulo Flabiano Smorigo - - Fix make clean. - - * Makefile.am: Remove build-grub-* in make clean. - -2013-11-13 Paulo Flabiano Smorigo - - New files to gitignore. - - * .gitignore: Add build-grub-gen-asciih, build-grub-gen-widthspec, - build-grub-mkfont, and grub-emu-lite. Remove .bzrignore. - -2013-11-13 Leif Lindholm - - * grub-core/kern/arm/misc.S: Make thumb2-compatible. - -2013-11-13 Leif Lindholm - - * .gitignore: fix rules for .dep* and add *.a post git migration - -2013-11-13 Colin Watson - - * configure.ac (AM_INIT_AUTOMAKE): Require at least version 1.10.1, - to match INSTALL. - -2013-11-13 Colin Watson - - * grub-core/kern/misc.c: Don't redirect divisions in the - GRUB_UTIL case. - * include/grub/misc.h: Likewise. - -2013-11-13 Colin Watson - - * grub-core/osdep/unix/emuconsole.c (put): Pacify the compiler on - systems that require checking the return value of write. - -2013-11-13 Colin Watson - - * util/grub-install.in (efi_quiet): Fix inverted logic: make - efibootmgr quiet when --debug is not used, rather than when it is. - -2013-11-13 Colin Watson - - * gentpl.py (define_macro_for_platform_dependencies): Remove - first (and thus unused) of two definitions for this function. - (platform_dependencies): Likewise. - -2013-11-13 Colin Watson - - * acinclude.m4 (grub_apple_cc): Remove; since the removal of nested - functions, we only need to check this for the target, not the host. - * configure.ac (grub_apple_cc): Likewise. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/arm/cache.c (probe_caches): Move asm part to ... - * grub-core/kern/arm/cache_armv6.S: ... here. This allows this - asm to stay in arm even if surrounding is thumb. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/arm/misc.S: Add __muldi3 and __aeabi_lmul. Those - helper functions are needed for thumb. - -2013-11-13 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_make_raid): Make - level / 3 division explicitly unsigned. Saves few bytes. - -2013-11-13 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (ZAP_LEAF_NUMCHUNKS): Use unsigned arithmetics. - -2013-11-13 Vladimir Serbinenko - - * grub-core/normal/datetime.c (grub_get_weekday): Use if rather than - division. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/uboot/init.c: Move grub_uboot_machine_type and - grub_uboot_boot_data to asm part. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/arm/uboot/startup.S: Remove = by replacing with - literal load. - (grub_uboot_syscall): Save/restore r9 and align stack. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/arm/cache.S: Replace = with explicit litteral load. - -2013-11-13 Vladimir Serbinenko - - * include/grub/symbol.h (END) [__arm__]: New macros. Replace all .end - occurencies with END. - -2013-11-13 Colin Watson - - * util/grub-editenv.c (help_filter, argp): Document how to delete - the whole environment block. - Reported by Dan Jacobson. Fixes Debian bug #726265. - -2013-11-13 Colin Watson - - * docs/grub.texi (Internationalisation, Supported kernels): Fix - sectioning. - -2013-11-13 Josh Triplett - - * grub-core/normal/term.c (grub_set_more): Use bool logic rather than - increment/decrement. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/arm/cache_armv6.S [__clang__]: Don't add .armv6 when - compiling with clang. - -2013-11-13 Vladimir Serbinenko - - * grub-core/kern/arm/uboot/startup.S: Use .org rather than assigning - ".". - -2013-11-13 Vladimir Serbinenko - - Redirect all divisions to grub_divmod64. - -2013-11-12 Vladimir Serbinenko - - * grub-core/term/tparm.c (tparam_internal): Use unsigned divisions. - -2013-11-12 Vladimir Serbinenko - - Add missing includes of loader.h. - -2013-11-12 Vladimir Serbinenko - - * configure.ac: Allow disabling themes. - -2013-11-12 Lukas Schwaighofer - - * util/grub.d/20_linux_xen.in: Don't decompress initrd. - -2013-11-12 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c: Don't poll non-functional AT controller - until it becomes operational. - -2013-11-12 Vladimir Serbinenko - - * grub-core/Makefile.core.def (legacy_password_test): Disable - on platforms where no legacycfg is compiled. - * grub-core/tests/lib/functional_test.c: Tolerate failure to - load legacy_password_test. - -2013-11-12 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/efiemu/prepare.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/osdep/windows/hostdisk.c (grub_util_fd_strerror): Silence - strict-aliasing warning. - (fsync): Silence cast warning. - -2013-11-12 Vladimir Serbinenko - - * grub-core/commands/verify.c: Remove variable length arrays. - Load gcry_dsa/gcry_rsa automatically. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/signature_test.c: New test. - -2013-11-12 Vladimir Serbinenko - - * grub-core/disk/cryptodisk.c (luks_script_get): Adapt to new procfs - API. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/legacy_password_test.c (vectors): Make static. - * grub-core/tests/pbkdf2_test.c (vectors): Likewise. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/setjmp_test.c: Reset counter to 0 before starting. - -2013-11-12 Vladimir Serbinenko - - * grub-core/fs/proc.c: Allow \0 in proc files. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/xnu_uuid_test.c: Fix assert message. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/xnu_uuid_test.c: Fix copyright year. - -2013-11-12 Vladimir Serbinenko - - * grub-core/fs/ext2.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/lib/crypto.c (grub_crypto_cbc_decrypt): Remove variable - length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/disk/AFSplitter.c: Remove variable length arrays. - * grub-core/disk/cryptodisk.c: Likewise. - * grub-core/disk/geli.c: Likewise. - * grub-core/disk/luks.c: Likewise. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/legacy_password_test.c: New test. - * grub-core/commands/legacycfg.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/lib/pbkdf2.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/pbkdf2_test.c: New test. - -2013-11-12 Vladimir Serbinenko - - * grub-core/lib/xzembed/xz_dec_stream.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/io/lzopio.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * include/grub/crypto.h: Add maximums on hash size and cipher block - size. - -2013-11-12 Vladimir Serbinenko - - * grub-core/commands/xnu_uuid.c: Remove variable length arrays. - -2013-11-12 Vladimir Serbinenko - - * grub-core/tests/xnu_uuid_test.c: New test. - -2013-11-12 Vladimir Serbinenko - - * grub-core/commands/hashsum.c: Remove unneeded memset (zalloc already - covers it). - -2013-11-12 Vladimir Serbinenko - - * grub-core/commands/hashsum.c: Remove variable length arrays. - -2013-11-11 Vladimir Serbinenko - - * grub-core/tests/gfxterm_menu.c (gfxterm_menu): Handle out-of-memory - condition. - * tests/grub_func_test.in: Increase memory allocation. - -2013-11-11 Vladimir Serbinenko - - * grub-core/osdep/unix/getroot.c [HAVE_STRUCT_STATFS_F_FSTYPENAME - && HAVE_STRUCT_STATFS_F_MNTFROMNAME]: Include sys/param.h and - sys/mount.h. - -2013-11-11 Vladimir Serbinenko - - * grub-core/osdep/apple/hostdisk.c (grub_util_get_fd_size): Rename to .. - (grub_util_get_fd_size_os): ...this. - (grub_hostdisk_flush_initial_buffer): New empty function. - -2013-11-11 Vladimir Serbinenko - - * grub-core/gensyminfo.sh.in: Handle the case of portable output - without --defined-only. - -2013-11-11 Vladimir Serbinenko - - * grub-core/lib/i386/relocator_common.S [__APPLE__ && __x86_64__]: Use - rip-relative addressing in prologue. - -2013-11-11 Vladimir Serbinenko - - * include/grub/misc.h [__APPLE__]: Do not add regparm(0) on x86_64. - * grub-core/kern/misc.c (__bzero) [__APPLE__]: New function. - -2013-11-11 Vladimir Serbinenko - - * util/getroot.c (grub_util_biosdisk_get_grub_dev) [__APPLE__]: - Add missing semicolon. - -2013-11-11 Vladimir Serbinenko - - * util/grub-macho2img.c: Use plain fopen rather than grub_util_fopen. - -2013-11-11 Vladimir Serbinenko - - * configure.ac: Check for lzma.h for enabling liblzma and allow - manual disabling. - -2013-11-11 Vladimir Serbinenko - - Add missing includes of loader.h. - -2013-11-11 Fam Zheng - - * util/grub.d/30_os-prober.in: Add minix entry. - -2013-11-10 Vladimir Serbinenko - - * grub-core/loader/i386/coreboot/chainloader.c (load_segment): Use - right buffer for temporary load. - -2013-11-10 Vladimir Serbinenko - - * grub-core/loader/i386/coreboot/chainloader.c: Support tianocore. - -2013-11-10 Vladimir Serbinenko - - * grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed - payload. - -2013-11-10 Vladimir Serbinenko - - * include/grub/lib/LzmaDec.h: Fix to include LzmaTypes.h and - not Types.h. - * grub-core/lib/LzmaDec.c: Fix prologue to make it compileable in GRUB - environment. - (LzmaDec_InitDicAndState): Make static. - -2013-11-10 Vladimir Serbinenko - - * util/grub-mkimagexx.c (generate_elf): Fix module address on coreboot. - -2013-11-10 Vladimir Serbinenko - - * grub-core/term/ieee1275/escc.c (GRUB_MOD_INIT): Fix order of channels. - - Reported by: Aaro Koskinen - -2013-11-10 Vladimir Serbinenko - - * docs/grub-dev.texi: Replace bzr references with git ones. - -2013-11-10 Andrey Borzenkov - - * docs/grub.texi (Simple configuration): Remove reference to - grub-reboot from saved default entry description - grub-default - does not use it anymore. - -2013-11-10 Vladimir Serbinenko - - * configure.ac: Make efiemu test cflags match the cflags efiemu is - compiled with. - -2013-11-10 Andrey Borzenkov - - * docs/grub.texi (Simple configuration): Document GRUB_DISABLE_SUBMENU. - -2013-11-10 Vladimir Serbinenko - - Fix grub_machine_fini bitrot. - - Reported by: Glenn Washburn. - -2013-11-10 Vladimir Serbinenko - - * configure.ac: Remove leftover -fnested-funcions -Wl,-allow_execute. - -2013-11-10 Vladimir Serbinenko - - * grub-core/Makefile.am (efiemu): Remove leftover -DAPPLE_CC and - -DELF. - * grub-core/efiemu/runtime/config.h: Use __i386__ and __x86_64__ - instead of ELF*. - -2013-11-10 Vladimir Serbinenko - - * configure.ac: Restore CFLAGS to TARGET_CFLAGS before external tests. - Add -march=core2 when testing compile of efiemu64. - - Thanks Andrey Borzenkov for spotting this. - -2013-11-09 Vladimir Serbinenko - - Add new ports: i386-xen and x86_64-xen. This allows running GRUB in - XEN PV environment and load kernels. - -2013-11-09 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c: Handle space in command line. - * grub-core/loader/multiboot_mbi2.c: Likewise. - -2013-11-09 Vladimir Serbinenko - - * grub-core/lib/cmdline.c (grub_loader_cmdline_size): Fix empty cmdline - handling. - -2013-11-09 Vladimir Serbinenko - - * grub-core/commands/i386/cmostest.c: Add new command "cmosset". - - Tested by: Denis 'GNUtoo' Carikli. - -2013-11-08 Vladimir Serbinenko - - * grub-core/normal/datetime.c (grub_get_weekday): Use unsigned types. - -2013-11-08 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_circular_progress.c (parse_angle): - Use to get rounded angle rather than truncated. - -2013-11-08 Vladimir Serbinenko - - * grub-core/term/serial.c: Add option for enabling/disabling - RTS/CTS flow control. - -2013-11-08 Vladimir Serbinenko - - * grub-core/lib/libgcrypt/cipher/idea.c (mul_inv): Remove signed - divisions. - -2013-11-08 Vladimir Serbinenko - - * grub-core/lib/libgcrypt/mpi/mpih-div.c (_gcry_mpih_divrem): - Use grub_fatal rather than divide by zero. - * grub-core/lib/libgcrypt/mpi/mpi-pow.c (gcry_mpi_powm): Likewise. - -2013-11-08 Vladimir Serbinenko - - * include/grub/gui.h (grub_fixed_sfs_divide): Round rather than - truncate. - (grub_fixed_fsf_divide): Likewise. - -2013-11-08 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_list.c (draw_scrollbar): Avoid - division by-zero and senseless negative divisions. - -2013-11-08 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_circular_progress.c (circprog_paint): Avoid - division by-zero and senseless negative divisions. - (circprog_set_property): Don't accept negative num_ticks. - -2013-11-08 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_progress_bar.c (draw_pixmap_bar): Avoid - division by-zero and senseless negative divisions. - -2013-11-08 Vladimir Serbinenko - - * configure.ac: Use elf_*_fbsd on kfreebsd. - -2013-11-08 Vladimir Serbinenko - - * grub-core/tests/div_test.c: New test. - -2013-11-08 Vladimir Testov - - * grub-core/gfxmenu/gui_box.c: Updated to work with area status. - * grub-core/gfxmenu/gui_canvas.c: Likewise. - * grub-core/gfxmenu/view.c: Likewise. - * grub-core/video/fb/video_fb.c: Introduce new functions: - grub_video_set_area_status, grub_video_get_area_status, - grub_video_set_region, grub_video_get_region. - * grub-core/video/bochs.c: Likewise. - * grub-core/video/capture.c: Likewise. - * grub-core/video/video.c: Likewise. - * grub-core/video/cirrus.c: Likewise. - * grub-core/video/efi_gop.c: Likewise. - * grub-core/video/efi_uga.c: Likewise. - * grub-core/video/emu/sdl.c: Likewise. - * grub-core/video/radeon_fuloong2e.c: Likewise. - * grub-core/video/sis315pro.c: Likewise. - * grub-core/video/sm712.c: Likewise. - * grub-core/video/i386/pc/vbe.c: Likewise. - * grub-core/video/i386/pc/vga.c: Likewise. - * grub-core/video/ieee1275.c: Likewise. - * grub-core/video/i386/coreboot/cbfb.c: Likewise. - * include/grub/video.h: Likewise. - * include/grub/video_fb.h: Likewise. - * include/grub/fbfill.h: Updated render_target structure. - grub_video_rect_t viewport, region, area - int area_offset_x, area_offset_y, area_enabled - * include/grub/gui.h: New helper function - grub_video_bounds_inside_region. - * docs/grub-dev.texi: Added information about new functions. - -2013-11-08 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_real_malloc): Use AND rather than MOD - for alignment. - -2013-11-08 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (grub_reed_solomon_recover): Add - missing attribute. - * grub-core/gdb/cstub.c (grub_gdb_trap): Likewise. - -2013-11-08 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_divmod64): Don't fallback to - simple division on arm and ia64. - -2013-11-08 Vladimir Serbinenko - - * grub-core/kern/arm/misc.S (__aeabi_unwind_cpp_pr0): Add dummy to - link with libgcc. - -2013-11-08 Vladimir Serbinenko - - * include/grub/symbol.h (FUNCTION), (VARIABLE): Fix precedence logic. - -2013-11-08 Vladimir Serbinenko - - * include/grub/symbol.h (FUNCTION), (VARIABLE) [__arm__]: Use % as - prefix symbol, not @. - -2013-11-08 Vladimir Serbinenko - - * INSTALL: Add note about older gcc and clang. - -2013-11-08 Vladimir Serbinenko - - * tests/util/grub-shell.in: Boot as hdd on ppc by default. - -2013-11-08 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_module): Fix - NULL pointer dereference. - -2013-11-07 Vladimir Serbinenko - - * grub-core/Makefile.am: Do not include libgcc.h when compiling with - clang. - -2013-11-07 Vladimir Serbinenko - - * grub-core/kern/powerpc/dl.c: Add missing pragma to silence cast-align - warnings. - -2013-11-07 Vladimir Serbinenko - - * grub-core/net/net.c (grub_net_route_unregister): Remove unused - function. - * grub-core/loader/i386/xnu.c (hextoval): Likewise. - * grub-core/disk/geli.c (ascii2hex): Likewise. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Run linker tests without -Werror. - Define TARGET_LDFLAGS_STATIC_LIBGCC and TARGET_LIBGCC. - Change all occurences of -static-libgcc resp -lgcc to - TARGET_LDFLAGS_STATIC_LIBGCC resp TARGET_LIBGCC. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Don't add -no-itegrated-as on clang on non-x86. - -2013-11-07 Vladimir Serbinenko - - Allow compiling with clang (not really supported though). - - * conf/Makefile.common (CFLAGS_PLATFORM): Don't add -mrtd -mregparm=3 - unconditionally. - * configure.ac: Add -no-integrated-as when using clangfor asm files. - Add -mrtd -mregparm=3 on i386 when not using clang. - * grub-core/kern/misc.c (grub_memset): Add volatile when on clang. - -2013-11-07 Vladimir Serbinenko - - * grub-core/kern/ieee1275/cmain.c: Add explicit attribute on asm - bindings. - * grub-core/lib/reed_solomon.c: Likewise. - * include/grub/i386/gdb.h: Likewise. - * include/grub/i386/pc/int.h: Likewise. - * include/grub/i386/pc/pxe.h: Likewise. - * include/grub/ieee1275/ieee1275.h: Likewise. - -2013-11-07 Vladimir Serbinenko - - Import libgcrypt 1.5.3. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Don't add -Wcast-align on x86. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Add -freg-struct-return on all platforms that - support it. - -2013-11-07 Vladimir Serbinenko - - * acinclude.m4: Use -Werror on parameter tests. - * configure.ac: Likewise. - -2013-11-07 Vladimir Serbinenko - - * acinclude.m4: Add missing TARGET_CCASFLAGS on asm tests. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Check that -malign-loops works rather than assuming that - either -falign-loops or -malign-loops work. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Remove -fnested-functions. We don't need it anymore. - -2013-11-07 Vladimir Serbinenko - - * configure.ac: Prevent cflags leaking to subsequent tests by always - resetting cflags to target_cflags in target tests. - -2013-11-07 Vladimir Serbinenko - - * grub-core/kern/parser.c (grub_parser_split_cmdline): Remove nested - function. - -2013-11-07 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Remove nested functions. - -2013-11-07 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_parse): Remove nested function. - -2013-11-07 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (grub_cmdline_get): - Remove nested functions. - -2013-11-07 Vladimir Serbinenko - - * tests/test_sha512sum.in: Make it work on emu. - -2013-11-07 Vladimir Serbinenko - - * grub-core/normal/charset.c (bidi_line_wrap): Eliminate nested - functions. - (grub_bidi_line_logical_to_visual): Likewise. - -2013-11-07 Vladimir Serbinenko - - Remove vestiges of -Wunsafe-loop-optimisations. - - * conf/Makefile.common (CFLAGS_GNULIB): Remove - -Wno-unsafe-loop-optimisations. - * grub-core/commands/legacycfg.c: Remove -Wunsafe-loop-optimisations - pragma. - * grub-core/io/gzio.c: Likewise. - * grub-core/script/parser.y: Likewise. - * grub-core/script/yylex.l: Likewise. - * util/grub-mkfont.c: Likewise. - -2013-11-07 Vladimir Serbinenko - - * util/grub-mkfont.c (process_cursive): Remove nested function. - -2013-11-07 Vladimir Serbinenko - - * include/grub/misc.h (grub_dprintf): Use unnamed vararg. - (grub_boot_time): Likewise. - -2013-11-07 Vladimir Serbinenko - - * include/grub/symbol.h (FUNCTION): Use @function rather than - "function". - (VARIABLE): Likewise. - -2013-11-07 Vladimir Serbinenko - - * grub-core/net/bootp.c (OFFSET_OF): Explicitly cast to grub_size_t. - -2013-11-07 Vladimir Serbinenko - - * grub-core/net/bootp.c (set_env_limn_ro): Make pointer const. - (parse_dhcp_vendor): Likewise. - -2013-11-07 Vladimir Serbinenko - - * util/grub-mkimagexx.c (relocate_symbols): Remove unneeded brackets. - -2013-11-07 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (main_context), (secondary_context): - Define after defining type and not before. - -2013-11-07 Vladimir Serbinenko - - * grub-core/fs/zfs/zfscrypt.c (grub_ccm_decrypt): Return right error - type. - (grub_gcm_decrypt): Likewise. - (algo_decrypt): Likewise. - (grub_zfs_decrypt_real): Transform error type. - -2013-11-07 Vladimir Serbinenko - - * grub-core/disk/geli.c (geli_rekey): Fix error return type. - -2013-11-07 Vladimir Serbinenko - - * grub-core/disk/usbms.c (grub_usbms_cbi_cmd): Fix error type. - (grub_usbms_cbi_reset): Likewise. - (grub_usbms_bo_reset): Likewise. - (grub_usbms_reset): Likewise. - (grub_usbms_attach): Likewise. - (grub_usbms_transfer_cbi): Likewise. - -2013-11-07 Vladimir Serbinenko - - * grub-core/io/lzopio.c (test_header): Simplify code and remove useless - "checksum = checksum;". - -2013-11-07 Vladimir Serbinenko - - * grub-core/fs/reiserfs.c (grub_reiserfs_iterate_dir): Fix type of - entry_type. - -2013-11-07 Vladimir Serbinenko - - * grub-core/commands/legacycfg.c (grub_cmd_legacy_kernel): Fix - BIOS disk check. - -2013-11-07 Vladimir Serbinenko - - * grub-core/bus/usb/ehci.c (grub_ehci_restore_hw): Return right enum - type. - (grub_ehci_fini_hw): Likewise. - * grub-core/bus/usb/usbhub.c (grub_usb_add_hub): Likewise. - -2013-11-07 Vladimir Serbinenko - - * include/grub/usb.h (grub_usb_controller_dev): Make portstatus - return grub_usb_err_t for cosistency. All users updated. - -2013-11-07 Vladimir Serbinenko - - * util/mkimage.c (SzAlloc): Use attribute unused rather than dubious - assigning to itself. - -2013-11-05 Gustavo Luiz Duarte -2013-11-05 Paulo Flabiano Smorigo - - Issue separate DNS queries for ipv4 and ipv6 - - Adding multiple questions on a single DNS query is not supportted by - most DNS servers. This patch issues two separate DNS queries - sequentially for ipv4 and then for ipv6. - - Fixes: https://savannah.gnu.org/bugs/?39710 - - * grub-core/net/bootp.c (parse_dhcp_vendor): Add DNS option. - * grub-core/net/dns.c (grub_dns_qtype_id): New enum. - * (grub_net_dns_lookup): Now using separated dns packages. - * (grub_cmd_nslookup): Add error condition. - * (grub_cmd_list_dns): Print DNS option. - * (grub_cmd_add_dns): Add four parameters: --only-ipv4, --only-ipv6, - --prefer-ipv4, and --prefer-ipv6. - * include/grub/net.h (grub_dns_option_t): New enum. - * (grub_net_network_level_address): option added. - -2013-11-05 Vladimir Testov - - * grub-core/video/fb/video_fb.c: Merge two blit functions - into one. - -2013-11-05 Vladimir Serbinenko - - * grub-core/term/terminfo.c: Add sequences for home and end. - -2013-11-05 Vladimir Serbinenko - - * grub-core/lib/legacy_parse.c: Fix handling of hercules and add - graphics console. - -2013-11-05 Vladimir Serbinenko - - * grub-core/video/i386/pc/vga.c: Fix double bufferring and - add mode 0x12. - -2013-11-04 Vladimir Serbinenko - - * docs/grub.texi (Vendor power-on keys): Add XPS M1330M based on old - e-mail by Per Öberg. - -2013-11-04 Vladimir Serbinenko - - * grub-core/commands/i386/nthibr.c (GRUB_MOD_INIT): Fix typo in command - name. - -2013-11-04 Andrey Borzenkov - - * configure.ac: Explicitly disable emusdl, emuusb and emupci on non- - emu platforms. - * grub-core/Makefile.core.def: Enable emupci and emuucb only for emu. - -2013-11-04 Vladimir Serbinenko - - * docs/grub.texi: Document usage of menuentry id. - -2013-11-04 Vladimir Serbinenko - - * docs/grub.texi: Add few mentions about EFI, debug and videoinfo. - -2013-11-04 Peter Lustig - - * grub-core/commands/i386/nthibr.c: New command. - -2013-11-04 Vladimir Serbinenko - - * grub-core/tests/video_checksum.c: Add 2560x1440 mode to testing. - -2013-11-04 Vladimir Serbinenko - - * include/grub/term.h (grub_term_coordinate): Extend to 16-bit per - coordinate. - -2013-11-04 Vladimir Serbinenko - - Support GRUB_DISABLE_SUBMENU config. - - Inspired by patch from Prarit Bhargava. - -2013-11-03 Vladimir Serbinenko - - * docs/grub.texi: Mention RSA support. - -2013-11-03 Vladimir Serbinenko - - * grub-core/commands/verify.c: Add RSA support. - -2013-11-03 Vladimir Serbinenko - - * grub-core/disk/ahci.c (grub_ahci_pciinit): Detect ATAPI devices. - * grub-core/disk/ata.c (grub_ata_identify): Use atapi_identify if - device is known to be ATAPI. - -2013-11-03 Mike Frysinger - - * configure.ac: Don't add target-prefix. - -2013-11-03 Vladimir Serbinenko - - * grub-core/commands/loadenv.c (grub_cmd_save_env): Remove unset - variables. - -2013-11-03 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (grub_gettext_init_ext): Ignore errors - if language is English. - -2013-11-03 Vladimir Serbinenko - - * grub-core/osdep/linux/getroot.c: Fix cast-align problems. - -2013-11-02 Vladimir Serbinenko - - * configure.ac: Don't add -m32/-m64 on emu. - -2013-11-02 neil - - * grub-core/osdep/linux/blocklist.c: Include linux/types.h for some - broken linux headers. - -2013-11-02 Vladimir Serbinenko - - * util/grub.d/30_os-prober.in: Add unhiding of partition if on msdos. - -2013-11-02 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (grub_reed_solomon_recover): Don't do - Reed-Solomon recovery if more than half of redundancy info is 0. - -2013-11-02 Vladimir Serbinenko - - * util/grub-mount.c: Handle symlinks to directories. - -2013-11-02 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (find_file): Save ctx->next when calling - find_file recursively for symlink. - -2013-11-02 Vladimir Serbinenko - - * tests/util/grub-shell.in: Copy themes. - -2013-11-02 Vladimir Serbinenko - - * util/grub-mkimagexx.c (locate_sections): Reject mislinked images. - -2013-11-02 Vladimir Serbinenko - - * configure.ac: Use 0x8000 for address instead of 8000. - -2013-11-02 Vladimir Serbinenko - - * grub-core/loader/sparc64/ieee1275/linux.c (get_physbase): Fix - signature. - -2013-11-02 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c (grub_efidisk_readwrite): Remove unused - variable. - -2013-11-02 Vladimir Serbinenko - - * configure.ac (TARGET_CFLAGS): Add -march=i386 on i386. - -2013-11-02 Vladimir Serbinenko - - * grub-core/fs/hfspluscomp.c (hfsplus_read_compressed_real): Call - file_progress_read_hook. - * grub-core/fs/ntfscomp.c (hfsplus_read_compressed_real): Likewise. - -2013-11-02 Vladimir Serbinenko - - * conf/Makefile.common (CFLAGS_PLATFORM): Remove poisoning of float - and double. - -2013-11-01 Vladimir Serbinenko - - * grub-core/fs/tar.c (grub_cpio_read): Add read_hook. - -2013-11-01 Vladimir Serbinenko - - Rewrite blocklist functions in order to get progress when - reading large extents and decrease amount of blocklist hook calls. - -2013-11-01 Vladimir Serbinenko - - * grub-core/term/serial.c (options), (grub_cmd_serial): Fix handling - of SI suffixes. - -2013-11-01 Vladimir Serbinenko - - Support --base-clock for serial command to handle weird cards with - non-standard base clock. - -2013-11-01 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext2_read_symlink): Use memcpy rather - strncpy. - * grub-core/fs/jfs.c (grub_jfs_lookup_symlink): Likewise. - * grub-core/kern/misc.c (grub_strncpy): Move from here ... - * include/grub/misc.h (grub_strncpy): ... to here. Make inline. - * grub-core/net/net.c (grub_net_addr_to_str): Use COMPILE_TIME_ASSERT - + strcpy rather than strncpy. - -2013-11-01 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (nvpair_name): Use correct type for size. - (check_pool_label): Likewise. Fixes overflow. - (nvlist_find_value): Fix comparison. - -2013-11-01 Vladimir Serbinenko - - * include/grub/misc.h (grub_strcat): Removed. All users changed to - more appropriate functions. - -2013-11-01 Vladimir Serbinenko - - * grub-core/kern/efi/efi.c (grub_efi_get_filename): Avoid inefficient - realloc. - -2013-11-01 Vladimir Serbinenko - - * util/grub-mkrescue.in: Do not use UUID search on EFI. - -2013-11-01 Vladimir Serbinenko - - * grub-core/kern/dl.c: Unify section-finding algorithm. Saves 30 bytes - on core size. - -2013-10-30 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_realloc): Don't copy more data than we have. - -2013-10-30 Vladimir Serbinenko - - * grub-core/io/gzio.c (huft_build): Use zalloc for safety. - (initialize_tables): reset tl and td to NULL after freeing. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c: Implement network tag. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c: Add EFI memory map to the list - of supported tags. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c: Implement EFI memory map. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/multiboot.c: Add support for multiboot kernels - quirks. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (allocate_pages): Allocate at least - a page in protected space. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/multiboot.c (grub_cmd_module): Don't attempt to - allocate space for zero-sized modules. - -2013-10-28 Vladimir Serbinenko - - * grub-core/loader/xnu_resume.c (grub_xnu_resume): Reject empty images. - -2013-10-28 Francesco Lavra - - * grub-core/lib/fdt.c: Fix miscellaneous bugs. - -2013-10-28 Vladimir Serbinenko - - * grub-core/lib/progress.c (grub_file_progress_hook_real): Add missing - safeguards. Fixes a crash with i386/pc/console.c. - -2013-10-28 Vladimir Serbinenko - - * include/grub/emu/hostdisk.h: Add proper declaration for grub_host_init - and grub_hostfs_init. - -2013-10-28 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_check_file_presence): Use - windows method on other platforms without good stat as well. - -2013-10-28 Vladimir Serbinenko - - * grub-core/osdep/linux/getroot.c: Add new btrfs defines. - -2013-10-28 Vladimir Serbinenko - - Make / in btrfs refer to real root, not the default volume. - Modify mkrelpath to work even if device is mounted with subvolid option. - -2013-10-28 Andrey Borzenkov - - * Makefile.util.def: Add grub-core/kern/disk_common.c to library - extra_dist. - * grub-core/Makefile.core.def: Add kern/disk_common.c to disk module - extra_dist. - -2013-10-27 Vladimir Serbinenko - - * util/grub-mkfont.c (main): Show error message when FT_Set_Pixel_Sizes - fails. - -2013-10-27 BVK Chaitanya - - * docs/autoiso.cfg: New file. - -2013-10-27 Vladimir Serbinenko - - * configure.ac: Remove leftover COND_BUILD_GRUB_MKFONT and - COND_GRUB_PE2ELF conditions. - -2013-10-27 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Accept "sd", "cd", - "vnd", "rd" and "fd" disks. - -2013-10-27 Vladimir Serbinenko - - Move grub_disk_write out of kernel into disk.mod. - -2013-10-27 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Unify int and wchar - handling. - -2013-10-27 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_abort): Make static - -2013-10-27 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Don't attempt to - transform invalid unicode codepoints. - -2013-10-27 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Remove needless explicit - \0 checking. - -2013-10-27 Vladimir Serbinenko - - * grub-core/lib/legacy_parse.c: Add support for "nd" disk. - -2013-10-26 Vladimir Serbinenko - - Consolidate cpuid code. - -2013-10-26 Vladimir Serbinenko - - Move cpuid code to cpuid.h and TSC code to tsc.c. - -2013-10-26 Grégoire Sutre - - * util/grub.d/00_header.in: Don't use LANG if it's not set. - -2013-10-26 Grégoire Sutre - - * util/grub-mkconfig.in: Replace $0 with $self. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - -2013-10-26 BVK Chaitanya - - * docs/osdetect.cfg: New file. - -2013-10-26 BVK Chaitanya - - * tests/util/grub-shell.in: Add new --debug option. - -2013-10-26 BVK Chaitanya - - * tests/test_unset.in: New test. - -2013-10-26 BVK Chaitanya - - * tests/test_sha512sum.in: New test. - -2013-10-26 Vladimir Serbinenko - - * grub-core/fs/iso9660.c: Replace strncat with memcpy. - * include/grub/misc.h: Remove strncat. - * grub-core/lib/posix_wrap/string.h: Likewise. - -2013-10-26 Vladimir Serbinenko - - * grub-core/net/tftp.c: Retransmit ack when rereceiving old packet. - Try to handle more than 0xFFFF packets. - Reported by: Bernhard Übelacker . - He also spotted few overflows in first version of this patch. - -2013-10-26 Vladimir Serbinenko - - * tests/date_unit_test.c: New test. - -2013-10-26 Vladimir Serbinenko - - * grub-core/normal/datetime.c (grub_unixtime2datetime): Fix mishandling - of first three years after start of validity of unixtime. - -2013-10-26 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (get_logical_num_lines): Use unsigned - division as the one making more sense. - (update_screen): Likewise. - (complete): Likewise. - -2013-10-25 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (complete): Make sure that width is >0. - -2013-10-25 Vladimir Serbinenko - - Make char and string width grub_size_t rather than grub_ssize_t. - -2013-10-25 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (grub_history_get): Make argument into - unsigned. - (grub_history_replace): Likewise. - -2013-10-25 Vladimir Serbinenko - - * grub-core/disk/raid6_recover.c: Use unsigned arithmetics when - appropriate. - -2013-10-25 Vladimir Serbinenko - - * grub-core/video/bitmap_scale.c: Use unsigned arithmetics when - appropriate. - -2013-10-25 Vladimir Serbinenko - - * grub-core/video/fb/fbblit.c: Use (255 ^ x) rather than (255 - x). - Use unsigned divisions rather than signed variants. - -2013-10-25 Vladimir Serbinenko - - * grub-core/video/readers/png.c (grub_png_convert_image): Use - unsigned arithmetics. - Add missing break. - -2013-10-25 Vladimir Serbinenko - - * grub-core/video/readers/jpeg.c: Use unsigned where appropriate. - -2013-10-25 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (xor_out): Use unsigned modular arithmetics - rather than signed one. - (recovery): Likewise. - -2013-10-25 Vladimir Serbinenko - - * grub-core/net/dns.c (hash): Use unsigned arithmetic. - -2013-10-25 Vladimir Serbinenko - - * grub-core/io/gzio.c (test_zlib_header): Use undigned modulo rather - than signed. - -2013-10-25 Jon McCune - - * docs/grub.texi: Cleanup security documentation around signatures. - -2013-10-25 Vladimir Serbinenko - - * grub-core/fs/ext2.c (EXT2_BLOCK_SIZE): Make unsigned. - -2013-10-25 Vladimir Serbinenko - - * grub-core/commands/gptsync.c (lba_to_chs): Use proper types rather - than int. - -2013-10-25 Vladimir Serbinenko - - * conf/Makefile.common (CPPFLAGS_KERNEL): Add -DGRUB_KERNEL=1. - * include/grub/dl.h (GRUB_MOD_INIT), (GRUB_MOD_FINI): Define - functions when compiling for kernel. - -2013-10-25 Vladimir Serbinenko - - * grub-core/lib/progress.c (grub_file_progress_hook_real): Cast to - unsigned long long when using %llu. - -2013-10-25 Vladimir Serbinenko - - * grub-core/lib/progress.c (grub_file_progress_hook_real): Refresh - terminal after updating progress. - -2013-10-25 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S (grub_gate_a20): Remove - argument. We don't disable Gate A20 in this code. - -2013-10-25 Vladimir Serbinenko - - * grub-core/boot/i386/qemu/boot.S: Ensure that A20 is enabled. - Conceptually based on change in branch "vbe-on-coreboot". - -2013-10-24 Robert Millan - - * grub-core/video/i386/pc/vbe.c (grub_video_vbe_setup): Replace - numeric constants with their symbolic equivalent. - Taken from branch "vbe-on-coreboot". - -2013-10-22 Vladimir Serbinenko - - * docs/grub.texi: Fix ordering and use pxref rather than xref. - -2013-10-22 Vladimir Serbinenko - - * grub-core/lib/progress.c (grub_file_progress_hook_real): Use - divmod64 for offset division. - -2013-10-22 Paulo Flabiano Smorigo - - Rename .bzrignore to .gitignore. Add "*.o" rule. - - * .bzrignore: Renamed to... - * .gitignore: ...this. - -2013-10-22 Paulo Flabiano Smorigo - - Add new progress module that displays the load progress of files. - - * grub-core/lib/progress.c: New file. - * grub-core/Makefile.core.def (progress): New module. - * grub-core/kern/file.c (grub_file_open): File name added. - * (grub_file_read): Progress hook added. - * grub-core/fs/cbfs.c (grub_cbfs_read): Likewise. - * grub-core/fs/cpio_common.c (grub_cpio_read): Likewise. - * grub-core/net/net.c (grub_net_fs_read_real): Likewise. - * include/grub/file.h (struct grub_file): Add progress module members. - * include/grub/term.h (struct grub_term_output): Likewise. - * grub-core/osdep/unix/emuconsole.c (grub_console_term_output): - Terminal velocity added. - * grub-core/osdep/windows/emuconsole.c (grub_console_term_output): Likewise. - * grub-core/term/arc/console.c (grub_console_term_output): Likewise. - * grub-core/term/efi/console.c (grub_console_term_output): Likewise. - * grub-core/term/gfxterm.c (grub_video_term): Likewise. - * grub-core/term/i386/coreboot/cbmemc.c (grub_cbmemc_term_output): Likewise. - * grub-core/term/i386/pc/console.c (grub_console_term_output): Likewise. - * grub-core/term/i386/pc/vga_text.c (grub_vga_text_term): Likewise. - * grub-core/term/ieee1275/console.c (grub_console_term_output): Likewise. - * grub-core/term/morse.c (grub_audio_term_output): Likewise. - * grub-core/term/serial.c (grub_serial_term_output): Likewise. - * grub-core/term/spkmodem.c (grub_spkmodem_term_output): Likewise. - * grub-core/term/uboot/console.c (uboot_console_term_output): Likewise. - -2013-10-22 Vladimir Serbinenko - - Verify signatures of signatures unless --skip-sig is specified. - -2013-10-21 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Remove needless explicit - \0 checking. - - Saves 70 bytes on compressed image. - -2013-10-21 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_strtoull): Remove needless *ptr != 0 - check. - - Saves 10 bytes on compressed image. - -2013-10-21 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_isprint): Move to ... - * include/grub/misc.h (grub_isprint): ... here. Make inline. - - Saves 20 bytes on compressed image due to remving exporting. - -2013-10-21 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (grub_ntfs_mount): Remove redundant check. - - Saves 5 bytes on compressed image. - -2013-10-21 Vladimir Serbinenko - - * grub-core/fs/ntfs.c: Move common UTF-16 handling to a separate - function get_utf8. - - Saves 379 bytes on compressed image. - -2013-10-21 Vladimir Serbinenko - - * grub-core/fs/ntfs.c: Handle 48-bit MFT no. - -2013-10-21 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (read_run_data): Rewrite using bitfields. - - Saves 40 bytes on compressed image. - -2013-10-21 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (grub_ntfs_iterate_dir): Use grub_uint8_t for - mask rather than 64-bit type. - - Saves 20 bytes on compressed image. - -2013-10-21 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (read_data): Move code for compressed data to ... - * grub-core/fs/ntfscomp.c (ntfscomp): ... here. - - Saves 273 bytes on compressed image. - -2013-10-20 Vladimir Serbinenko - - * grub-core/kern/disk.c (grub_disk_write): Use malloc/free instead of - variable length arrays. - - Saves 50 bytes on compressed image. - -2013-10-20 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c: Remove variable length arrays. - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/ufs.c: Remove variable length arrays. - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/ntfs.c: Add comment about fixed allocation size. - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/zfs.c: Remove variable length arrays. - Reduces zfs.mod by 160 bytes (208 compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (check_pool_label): Fix memory leak. - -2013-10-20 Vladimir Serbinenko - - * grub-core/net/arp.c: Remove variable length arrays. - * grub-core/net/bootp.c: Likewise. - * grub-core/net/dns.c: Likewise. - * grub-core/net/icmp6.c: Likewise. - * grub-core/net/net.c: Likewise. - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/ntfs.c: Remove variable length arrays. - Increases ntfs.mod by 64 bytes (but decreases by 3 when - compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/hfs.c: Remove variable length arrays. - Reduces hfs.mod by 8 bytes (52 compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/udf.c: Remove variable length arrays. - Increases udf.mod by 128 bytes (but decreases by 13 when - compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/iso9660.c: Remove variable length arrays. - Increases iso9660.mod by 200 bytes (but decreases by 79 when - compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c: Remove variable length arrays. - Increases nilfs2.mod by 24 bytes (but decreases by 115 when - compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/xfs.c: Remove variable length arrays. - Reduces xfs.mod by 40 bytes (43 compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/fshelp.c: Remove variable length arrays. - Reduces fshelp.mod by 116 bytes (23 compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/normal/completion.c: Remove variable length arrays. - * grub-core/normal/menu_entry.c: Likewise. - - Reduces normal.mod by 496 bytes. - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/minix.c: Remove variable length arrays. Reduces jfs.mod - by 356 bytes (158 compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/jfs.c: Remove variable length arrays. Reduces jfs.mod - by 364 bytes (169 compressed). - -2013-10-20 Vladimir Serbinenko - - * grub-core/fs/bfs.c: Remove variable length arrays. Reduces afs.mod and - bfs.mod size by 556 resp 740 bytes (288 resp 334 compressed). - * include/grub/types.h (grub_unaligned_uint64_t): New type. - -2013-10-19 Vladimir Serbinenko - - Lift 255x255 erminal sie restriction to 65535x65535. Also change from - bitmasks to small structures of size chosen to fit in registers. - -2013-10-19 Vladimir Serbinenko - - * conf/Makefile.common: Use -freg-struct-return on i386. This - decreases code size and improves performance. - -2013-10-19 Vladimir Serbinenko - - * grub-core/osdep/unix/exec.c: Fix compilation error on emu. - -2013-10-19 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Fix formatting of - "(null)" string. - Simplify expressions to save around 256 bytes in kernel.img. - * tests/printf_unit_test.c (printf_test): Add "(null)" tests. - -2013-10-19 Vladimir Serbinenko - - * grub-core/tests/video_checksum.c (grub_video_capture_write_bmp): - Use GRUB_UTIL_FD_O_* rather than O_*. - -2013-10-19 Vladimir Serbinenko - - Add haiku-specific functions. - -2013-10-19 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c: Remove few leftover includes. - -2013-10-19 Vladimir Serbinenko - - Move stat () and device mode checking into OS-dependent files as - long as performance doesn't suffer. - -2013-10-19 Vladimir Serbinenko - - Split make_system_path_relative_to_its_root into separate file - relpath.c from getroot.c as it's common between unix and haiku - but otherwise haiku doesn't use any functions from unix getroot.c. - -2013-10-19 Vladimir Serbinenko - - * grub-core/osdep/aros/hostdisk.c (grub_util_is_directory): - New function. - (grub_util_is_special_file): Likewise. - -2013-10-19 Vladimir Serbinenko - - * grub-core/osdep/unix/getroot.c: Move exec functions to ... - * osdep/unix/exec.c: ... here. Add few additional exec_* variants. - -2013-10-19 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Define size_t to - grub_size_t. This fixes the case when size_t mismatches grub_size_t. - -2013-10-19 Vladimir Serbinenko - - * util/grub-mkimagexx.c (make_reloc_section): Fix memory leak. - (load_image): Likewise. - -2013-10-19 Vladimir Serbinenko - - * util/grub-render-label.c: Move backend part to ... - * util/render-label.c: ... here. - -2013-10-18 Vladimir Serbinenko - - * grub-core/osdep/random.c: Use unix/random.c on haiku. Haiku uses - yarrow (by B. Schneier et al) for its /dev/urandom (similar to FreeBSD). - -2013-10-18 Vladimir Serbinenko - - * grub-core/osdep/generic/blocklist.c: Add missing include to string.h. - -2013-10-18 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Handle - CD-ROM in case when it's declared as having subpartitions. - -2013-10-18 Vladimir Serbinenko - - Don't add -lm on haiku. - - * configure.ac: Define BUILD_LIBM to -lm on most platforms - and empty on haiku. - * grub-core/Makefile.am (gentrigtables): Use $(BUILD_LIBM) rather than - -lm. - -2013-10-18 Vladimir Serbinenko - - * configure.ac: Use -melf_*_haiku as target on haiku. - -2013-10-18 Vladimir Serbinenko - - * Makefile.util.def: Add util/setup.c to extra_dist. - -2013-10-18 Vladimir Serbinenko - - * grub-core/kern/i386/pc/mmap.c (grub_machine_mmap_iterate): Pass - unknown types through. - -2013-10-18 Vladimir Serbinenko - - * grub-core/osdep/unix/getroot.c (grub_util_check_block_device): Remove. - (grub_util_check_char_device): Likewise. - * include/grub/emu/getroot.h: Likewise. - -2013-10-18 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Use define for defining - memset rather than inline static function. - -2013-10-18 Vladimir Serbinenko - - * grub-core/lib/xzembed/xz_config.h: Enable all bcj filters when - not doing embedded decompressor. - -2013-10-18 Vladimir Serbinenko - - * grub-core/disk/ldm.c: Rename variables and arguments to prevent - shadowing. - * grub-core/kern/disk.c: Likewise. - * grub-core/kern/misc.c: Likewise. - * include/grub/parser.h: Likewise. - * include/grub/script_sh.h: Likewise. - * include/grub/zfs/zfs.h: Likewise. - -2013-10-18 Vladimir Serbinenko - - * grub-core/disk/luks.c (configure_ciphers): Fix spurious warning. - -2013-10-18 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs_lz4.c: Check that __INTEL_COMPILER is - defined before trying to use it. - -2013-10-18 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_create_node): Fix uninited value - warning. - -2013-10-18 Vladimir Serbinenko - - * include/grub/dl.h: Remove double declaration of GRUB_MOD_DEP. - Use __unused__ rather than __used__ on gcc < 3.2. - -2013-10-18 Vladimir Serbinenko - - * include/grub/setjmp.h: Define RETURNS_TWICE. Keep it empty for - gcc < 4.0. - * include/grub/*/setjmp.h: USe RETURNS_TWICE. - -2013-10-18 Vladimir Serbinenko - - * grub-core/disk/dmraid_nvidia.c: Fix potentially uninited "layout". - -2013-10-18 Vladimir Serbinenko - - * include/grub/misc.h: Don't use warn_unused_result on gcc < 3.4. - * include/grub/emu/misc.h: Likewise. - -2013-10-18 Vladimir Serbinenko - - * grub-core/term/i386/pc/vga_text.c: Remove extra declaration of - cur_color. - -2013-10-18 Vladimir Testov - - * grub-core/tests/checksums.h: Regenerated due to progress bar - get_minimal_size changes. - -2013-10-17 BVK Chaitanya - - Added `tr' command support. - - * grub-core/commands/tr.c: New file. - * grub-core/Makefile.core.def: Build rules for new module. - - * tests/grub_cmd_tr.in: New test. - * Makefile.util.def: Build rules for new test. - -2013-10-17 Vladimir Testov - - * grub-core/gfxmenu/gui_progress_bar.c: Sanity checks added. - -2013-10-17 Vladimir Testov - - * grub-core/gfxmenu/gui_progress_bar.c: New option ``highlight_overlay`` - * docs/gurb.texi: Likewise. - -2013-10-17 Vladimir Testov - - * grub-core/gfxmenu/gui_progress_bar.c (draw_pixmap_bar): Fixed bug. - Pixmap highlighted section with east and west slices was displayed - incorrectly due to negative width of the central slice. - -2013-10-17 Vladimir Testov - - * docs/grub.texi: Graphical options information update. - Removed outdated. Updated current. Inserted missed. - -2013-10-17 Vladimir Serbinenko - - * docs/grub.texi: Mention few new platform-specific commands. - -2013-10-17 Vladimir Serbinenko - - * grub-core/script/yylex.l: Fix LSQBR2 and RSQBR2. It's not - currently used so this doesn't really have any effect. - Reported by: Douglas Ray - -2013-10-17 Vladimir Serbinenko - - * autogen.sh: Don't set LC_CTYPE as it doesn't create problem for - compilation but prevents gcc from displaying messages in non-Latin - alphabets. - * conf/Makefile.common: Likewise. - -2013-10-16 Hiroyuki YAMAMORI - - Handle Japanese special keys. - Reported by: Hiroyuki YAMAMORI. - Codes supplied by: Hiroyuki YAMAMORI. - -2013-10-16 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: Scrollbar sanity checks added. - -2013-10-16 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: New option `item_pixmap_style`. - * docs/grub.texi: Likewise. - -2013-10-16 Vladimir Serbinenko - - * grub-core/osdep/unix/hostdisk.c (grub_util_fd_read): Return correct - value in case of incomplete read. - (grub_util_fd_write): Likewise. - -2013-10-15 Vladimir Serbinenko - - * util/editenv.c (grub_util_create_envblk_file): Use grub_util_rename. - -2013-10-15 Vladimir Serbinenko - - * util/grub-editenv.c (create_envblk_file): More from here ... - * util/editenv.c (grub_util_create_envblk_file): ... to here. - -2013-10-15 Vladimir Serbinenko - - * grub-core/osdep/unix/getroot.c (grub_guess_root_devices): - canonicalize file name before doing the rest. - -2013-10-15 Vladimir Serbinenko - - * include/grub/osdep/hostfile_windows.h: Add missing ftello for - mingw32. - -2013-10-15 Vladimir Serbinenko - - Define grub_util_is_directory/regular/special_file and - use OS-dependent versions rather than to rely on stat(). - -2013-10-15 Vladimir Serbinenko - - * util/grub-mkimage.c: Move backend part to ... - * util/mkimage.c: ... here. - -2013-10-15 Vladimir Serbinenko - - Allow compilation with mingw64 albeit with warnings due to lack of - %llx/%llu. - - * grub-core/gnulib/msvc-inval.c: Use __cdecl rather than cdecl. - * grub-core/lib/posix_wrap/wchar.h: Define wint_t. - * grub-core/lib/posix_wrap/wctype.h: Define wctype_t. - * include/grub/osdep/hostfile_windows.h: Don't define fseeko/ftello - on mingw64. - * include/grub/types.h: Allow sizeof (long) != sizeof (void *). - -2013-10-15 Vladimir Serbinenko - - Remove leftover references to some of the system headers. - -2013-10-15 Vladimir Serbinenko - - * grub-core/disk/geli.c (grub_util_get_geli_uuid): Close handle after - read. - -2013-10-15 Vladimir Serbinenko - - * grub-core/disk/cryptodisk.c: Use grub_util_fd_strerror instead - of strerror. - -2013-10-15 Vladimir Serbinenko - - Split out blocklist retrieving from setup.c to - grub-core/osdep/blocklist.c and add windows implementation since - generic version doesn't work on NTFS on Windows due to aggressive - unflushable cache. - -2013-10-15 Vladimir Serbinenko - - Split grub-setup.c into frontend (grub-setup.c) and backend (setup.c) - files. - -2013-10-15 Vladimir Serbinenko - - * grub-core/osdep/windows/hostdisk.c (grub_util_fd_strerror): - Cut tailing newline. Remove arbitrary limitation. Always use - grub_util_tchar_to_utf8. - -2013-10-15 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Handle %% properly. - * tests/printf_unit_test.c (printf_test): Add %% tests. - Reported by: Paulo Flabiano Smorigo. - -2013-10-15 Vladimir Serbinenko - - * grub-core/osdep/windows/hostdisk.c (fsync) [__MINGW32__]: Really - implement fsync. - -2013-10-15 Vladimir Serbinenko - - * configure.ac: Check for nvlist_lookup_string in nvpair since we - use nvlist_lookup_string and don't use nvlist_print. - -2013-10-15 Vladimir Serbinenko - - Add wrappers around rename, unlink, mkdir, opendir, readdir and - closedir to handle filename charset translation. - -2013-10-15 Vladimir Serbinenko - - * include/grub/emu/hostdisk.h: Move file operations to - * include/grub/emu/hostfile.h: ... here. - -2013-10-15 Vladimir Serbinenko - - * grub-core/osdep/windows/hostdisk.c (canonicalize_file_name): Handle - unicode path. - -2013-10-15 Vladimir Serbinenko - - * grub-core/tests/checksums.h: Regenerate due to swiss.sed change. - -2013-10-15 Vladimir Serbinenko - - Move cpu time retrieval to separate grub_util_get_cpu_time_ms - and remove export.h. - -2013-10-15 Vladimir Serbinenko - - * grub-core/kern/emu/error.c: Removed. - * grub-core/Makefile.core.def (kernel): Don't add error.c and progname.c - explicitly as it's already in libgnu.a. - -2013-10-15 Vladimir Serbinenko - - * grub-core/osdep/windows/emuconsole.c: Add missing config.h and - config-util.h include. - -2013-10-15 Vladimir Serbinenko - - Split emunet into platform-dependent and GRUB-binding parts. Keep - platform-dependent part in kernel for easy access to OS functions. - -2013-10-15 Vladimir Serbinenko - - * grub-core/tests/video_checksum.c: Use grub_util_fd_* rather than - open/read/write. - -2013-10-14 Vladimir Serbinenko - - * grub-core/osdep/windows/emuconsole.c: New file. - -2013-10-14 Andrey Borzenkov - - * conf/Makefile.extra-dist: Add osdep/*/init.c - -2013-10-14 Vladimir Serbinenko - - * Makefile.am: Use TARGET_OBJCOPY when doing objcopy for target. - -2013-10-14 Vladimir Serbinenko - - * util/grub-probe.c (probe): Separate different drives in hint-str - by spaces and not newlines. - * util/grub-mkconfig_lib.in: Handle multidevice filesystem. - -2013-10-14 Andrey Borzenkov - - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): - Handle CD-ROMs. - -2013-10-14 Vladimir Serbinenko - - Pass-through unknown E820 types. It required reorganisation of mmap - module. - -2013-10-14 Andrey Borzenkov - - * Makefile.util.def: Add osdep/init.c to grub-mount files. - -2013-10-14 Vladimir Serbinenko - - Make grub_util_fd_seek match behaviour of other grub_util_fd_* and - fseeko. - -2013-10-14 qwertial - - * grub-core/gdb_grub.in: Fix overflow and wrong field. - -2013-10-14 Jon McCune - - * docs/grub.texi: Document new signatures possibility. - -2013-10-14 Vladimir Serbinenko - - Define GRUB_UTIL_FD_O_* and always use them with grub_util_fd_open. - -2013-10-14 Vladimir Serbinenko - - * include/grub/osdep/hostfile_windows.h (grub_util_utf8_to_tchar): Add - missing prototype. - (grub_util_tchar_to_utf8): Likewise. - -2013-10-14 Vladimir Serbinenko - - * grub-core/Makefile.core.def: Add osdep/init.c on emu. - * grub-core/kern/emu/main.c: Add missing include. - * grub-core/osdep/basic/init.c (grub_util_host_init) [!GRUB_UTIL]: - Don't call grub_util_init_nls. - * grub-core/osdep/windows/init.c (grub_util_host_init) [!GRUB_UTIL]: - Likewise. - -2013-10-13 Vladimir Serbinenko - - * util/misc.c (grub_util_get_image_size): Use FILE functions rather than - stat. - -2013-10-13 Vladimir Serbinenko - - * util/grub-editenv.c: Remove leftover set_program_name and init_nls. - -2013-10-13 Vladimir Serbinenko - - * include/grub/misc.h: Use gnu_printf only on gcc 4.4 or later. - -2013-10-13 Vladimir Serbinenko - - Add a wrapper for fopen. On unix-like systems just pass-through. On - windows use unicode version. - -2013-10-13 Vladimir Serbinenko - - Move set_program_name and init_nls to host_init. On windows - fix in this fuction console and argument charset as well. - -2013-10-12 Andrey Borzenkov - - Fix inconsistent use of GRUB_CRYPTODISK_ENABLE and - GRUB_ENABLE_CRYPTODISK. - - * util/grub-install.in: Rename all GRUB_CRYPTODISK_ENABLE to - GRUB_ENABLE_CRYPTODISK. - * util/grub-mkconfig_lib.in: Likewise. - -2013-10-12 Christian Cier-Zniewski - - * docs/grub.texi (Vendor power-on keys): Add Dell Latitude E4300. - -2013-10-12 Melki Christian - - * grub-core/term/at_keyboard.c [DEBUG_AT_KEYBOARD]: Fix compilation - error when enabling debug. - -2013-10-12 Ilya Bakulin - - * configure.ac: Use -melf_*_obsd on openbsd. - -2013-10-12 Vladimir Serbinenko - - * grub-core/kern/arm/dl_helper.c: Use more proper %p for pointer. - -2013-10-12 Vladimir Serbinenko - - * include/grub/misc.h: Use gnu_printf rather than printf as format - template since our functions are independent of libc. - -2013-10-11 Vladimir Serbinenko - - * util/grub-setup.c (setup): Move copying of partition table as - futher up as possible to avoid possible overwrite by floppy routines. - -2013-10-11 Vladimir Serbinenko - - * grub-core/fs/fat.c: Fix handling of exfat contiguous files. - -2013-10-10 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: New option `scrollbar_thumb_overlay`. - * docs/grub.texi: Likewise. - -2013-10-10 Vladimir Serbinenko - - * util/getroot.c (make_device_name): Remove dos_part and bsd_part as - it's mostly unused. Move vestiges to the callers. - -2013-10-10 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c: Remove temporary buffers for hex - version of salt and hash. Use grub_snprintf rather than snprintf. - -2013-10-10 Vladimir Serbinenko - - * docs/grub.texi: Fix problem with braces. - -2013-10-10 Vladimir Serbinenko - - * conf/Makefile.extra-dist: Fix extra-dist list. - * grub-core/Makefile.core.def: Likewise. - -2013-10-10 Vladimir Serbinenko - - * docs/grub.texi: Document disk names used on Windows and AROS. - -2013-10-10 Vladimir Serbinenko - - * grub-core/osdep/aros/getroot.c: Change to //: prefix as discussed - with AROS devs. - * grub-core/osdep/aros/hostdisk.c: Likewise. - -2013-10-10 Vladimir Serbinenko - - Avoid including hostfile.h when not necessarry as it pulls - in OS-specific headers which may redefine generic names - like "far". - -2013-10-09 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: New options for scrollbar padding: - scrollbar_left_pad, scrollbar_right_pad, scrollbar_top_pad, - scrollbar_bottom_pad - * docs/grub.texi: Likewise. - -2013-10-09 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c (list_destroy): Fixed memory leak. - -2013-10-09 Vladimir Serbinenko - - Move OS-dependent file definitions to include/grub/osdep/hostfile*.h. - -2013-10-09 Vladimir Serbinenko - - * include/grub/emu/hostdisk.h (grub_hostdisk_linux_find_partition): - Removed. - * grub-core/osdep/linux/hostdisk.c (grub_hostdisk_linux_find_partition): - Made static. - -2013-10-09 Vladimir Serbinenko - - * include/grub/emu/getroot.h (grub_util_find_hurd_root_device): Remove - leftover. - -2013-10-09 Vladimir Serbinenko - - Move OS-specific driver configuration to grub_util_fd_open. This - moves OS-dependent parts from kern/emu/hostdisk.c to - grub-core/osdep/*/hostdisk.c. - -2013-10-09 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Use size_t instead of - grub_size_t. - * util/grub-mkimagexx.c (locate_sections): Likewise. - (load_image): Likewise. - -2013-10-09 Vladimir Serbinenko - - * util/misc.c (grub_util_write_image_at): Don't use PRIxGRUB_SIZE for - size_t. - (grub_util_write_image): Likewise. - -2013-10-08 Vladimir Serbinenko - - * grub-core/osdep/basic/random.c: New file. Abort on an attempt to - get random when no RNG is available. - * grub-core/osdep/random.c: Use basic/random.c on OS out of whitelist. - -2013-10-08 Vladimir Serbinenko - - * include/grub/util/lvm.h: Removed. - -2013-10-08 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c (fsync) [__MINGW32__]: Move to ... - * grub-core/osdep/windows/hostdisk.c (fsync) [__MINGW32__]: ... here. - -2013-10-08 Vladimir Serbinenko - - * grub-core/osdep/windows/sleep.c: Add missing config.h. - -2013-10-08 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c (grub_get_rtc): Remove (it's a leftover). - -2013-10-08 Vladimir Serbinenko - - * grub-core/net/drivers/emu/emunet.c: Move to .. - * grub-core/osdep/linux/emunet.c: ..here. - -2013-10-08 Vladimir Serbinenko - - * util/ieee1275/ofpath.c: Move to ... - * grub-core/osdep/linux/ofpath.c: ..here, split stub into ... - * grub-core/osdep/basic/ofpath.c: ..here. - -2013-10-08 Vladimir Serbinenko - - Move password-querying (util-version) routines to grub-core/osdep. - -2013-10-08 Vladimir Serbinenko - - Move sleep routines to grub-core/osdep. - -2013-10-08 Vladimir Serbinenko - - Move OS-dependent files to grub-core/osdep and document it. - -2013-10-08 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c (canonicalize_file_name): Move to ... - * grub-core/kern/emu/hostdisk_*.c (canonicalize_file_name): ... here. - -2013-10-08 Vladimir Serbinenko - - * grub-core/kern/arm/misc.S: Remove leftover ARM and THUMB. - -2013-10-08 Vladimir Serbinenko - - * util/misc.c: Remove leftover inclusion of malloc.h. - -2013-10-08 Vladimir Serbinenko - - * include/grub/setjmp.h: Remove leftover GRUBOF. - -2013-10-08 Vladimir Serbinenko - - * util/raid.c: Fold into ... - * util/getroot_linux.c: ... here. Make all functions static. - -2013-10-08 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs_lz4.c: Switch from ad-hoc endiannes and width - macros to GRUB ones. - -2013-10-08 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c (draw_scrollbar): Fixed rare - occasional bug. If there are too many boot entries or too low - scrollbar height then we need to use another formula to calculate - the position and size of the scrollbar thumb. - -2013-10-08 Vladimir Serbinenko - - * util/random_unix.c: Add NetBSD, Solaris and Mac OS X to verified list. - -2013-10-08 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: New option `scrollbar-slice`. - * docs/grub.texi: Likewise. - -2013-10-08 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: Draw the scrollbar in a separate - viewport. - -2013-10-08 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c (list_get_minimal_size): Corrected - minimal width calculations. - -2013-10-07 Vladimir Serbinenko - - * docs/grub.texi: Update note on colors on emu console. - -2013-10-07 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_get_file_block): Give GRUB_ERR_BAD_FS - for quadruple indirect rather than GRUB_ERR_NOT_IMPLEMENTED_YET as - it's FS and not GRUB limitation. - -2013-10-07 Vladimir Serbinenko - - * grub-core/kern/arm/efi/startup.S: Remove thumb leftover. - -2013-10-07 Vladimir Serbinenko - - * grub-core/kern/arm/efi/init.c: Rewrite timer fucntion. - -2013-10-04 Samuel Thibault - - * util/grub.d/10_hurd.in: Use `version_find_latest` to sort gnumach - kernels by version order. - -2013-10-04 Vladimir Serbinenko - - * util/random_unix.c: Add kFreeBSD to the list of secure RNG. - -2013-10-04 Vladimir Serbinenko - - Add AROS hostdisk and getroot routines. - -2013-10-04 Vladimir Serbinenko - - Make cryptodisk and diskfilter probe data retrievable programmatically - and not just printable. - -2013-10-04 Vladimir Serbinenko - - Split random retrieving code into separate files. - -2013-10-03 Vladimir Serbinenko - - * grub-core/kern/arm/dl.c (do_relocations): Accept and ignore - R_ARM_V4BX. - -2013-10-03 Vladimir Serbinenko - - * grub-core/tests/video_checksum.c: Increase robustness to out of memory - condition. - * grub-core/tests/fake_input.c: Likewise. - * grub-core/tests/cmdline_cat_test.c: Likewise. - -2013-10-03 Vladimir Serbinenko - - * grub-core/video/capture.c: Do not do finalization when .fini - is called as there is explicit capture_end. - -2013-10-03 Vladimir Serbinenko - - * grub-core/term/gfxterm.c: Add flag "functional" to skip input when - changing windows to avoid crash. - -2013-10-03 Vladimir Serbinenko - - * grub-core/kern/arm/cache.c: Add v5 write-through cache support. - -2013-10-03 Vladimir Serbinenko - - * po/exclude.pot: Add several strings to exclude. - -2013-10-03 Vladimir Serbinenko - - * tests/gettext_strings_test.in: Add getroot_*.c to exclude list. - -2013-10-03 Vladimir Serbinenko - - * autogen.sh: Add ./util/grub-gen-widthspec.c and - ./util/grub-gen-asciih.c to exclude list. - -2013-10-03 Vladimir Serbinenko - - * grub-core/gfxmenu/theme_loader.c (theme_set_string): Fix memory leak - and don't mark error strings for translation. - -2013-10-03 Vladimir Serbinenko - - * grub-core/disk/uboot/ubootdisk.c (uboot_disk_open): Use grub_error - properly in case of missing block size. - -2013-10-03 Vladimir Serbinenko - - * grub-core/lib/arm/setjmp.S: Add missing license section. - -2013-10-03 Vladimir Serbinenko - - * po/swiss.sed: Add replacement for key names and for term computer. - -2013-10-02 Vladimir Testov - - * grub-core/gfxmenu/theme_loader.c: New global options for the - theme background image handling. desktop-image-scale-method, - desktop-image-h-align, desktop-image-v-align. - * grub-core/gfxmenu/view.c: Likewise. - * include/gfxmenu_view.h: Likewise. - * include/bitmap_scale.h: Proportional scale functions introduced. - * grub-core/video/bitmap_scale.c: Likewise. Verification checks are - put in a separate functions. GRUB_ERR_BUG is set for grub_error in - cases of unexpected input variables for scale functions. - * docs/grub.texi: Updated documentation for new options. - -2013-10-02 Vladimir Serbinenko - - * grub-core/video/readers/png.c: Support narrow (4-/2-/1-bpp) PNG. - -2013-10-01 Vladimir Testov - - * grub-core/tests/checksums.h: Corrected due to changes in - bilinear interpolation function. - -2013-10-01 Vladimir Testov - - * grub-core/video/bitmap_scale.c (scale_bilinear): Increased precision - to eliminate artefacts in bilinear interpolation. - -2013-09-28 Vladimir Serbinenko - - * grub-core/video/readers/tga.c: Support paletted tga. - -2013-09-28 Vladimir Serbinenko - - * grub-core/video/readers/jpeg.c (grub_jpeg_decode_data): Remove - incorrect cbcr setting when in color mode. - -2013-09-28 Vladimir Serbinenko - - * grub-core/video/readers/png.c: Support paletted images and clean up - greyscale support. - -2013-09-28 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_terminfo_readkey): Fix - usage of wrong table which resulted in mishandling of 4-byte - sequences. - -2013-09-28 Vladimir Serbinenko - - * grub-core/term/terminfo.c: Add Home and End key sequences. - -2013-09-27 Vladimir Serbinenko - - * grub-core/video/readers/png.c (grub_png_decode_image_header): - Fix formula for computing total number of bytes. - -2013-09-27 Vladimir Serbinenko - - * grub-core/video/readers/tga.c: Reorganize to separate RLE and - image processing, fix big-endian and support grayscale. - -2013-09-27 Vladimir Serbinenko - - * grub-core/video/fb/video_fb.c (grub_video_fb_create_render_target): - Correctly will with maximum transparency when using index color. - -2013-09-27 Vladimir Serbinenko - - * grub-core/video/readers/png.c: Support grayscale - -2013-09-27 Vladimir Serbinenko - - * grub-core/video/readers/jpeg.c: Support grayscale. - -2013-09-26 Jon McCune - - * grub-core/commands/loadenv.c: Support skipping signature check - and variable names filtering. - -2013-09-24 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk_unix.c: Declare AROS as non-unix. - * grub-core/kern/emu/hostfs.c: Likewise. - * util/getroot_unix.c: Likewise. - -2013-09-24 Vladimir Serbinenko - - * include/grub/emu/hostdisk.h (GRUB_FD_STAT_IS_FUNTIONAL): New define. - Migrate all explicit defines to this new one. - -2013-09-24 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Use - grub_util_fd_strerror when using grub_util_fd_*. - (grub_util_fd_open_device): Likewise. - (grub_util_biosdisk_read): Likewise. - (grub_util_biosdisk_write): Likewise. - * grub-core/kern/emu/hostdisk_unix.c (grub_util_fd_open): New function. - (grub_util_fd_strerror): Likewise. - (grub_util_fd_sync): Likewise. - (grub_util_fd_close): Likewise. - * grub-core/kern/emu/hostdisk_windows.c (grub_util_fd_sync): Likewise. - (grub_util_fd_close): Likewise. - (grub_util_fd_strerror): Likewise. - * include/grub/emu/hostdisk.h (grub_util_fd_close): Make into real - function proto rather than macro. - (grub_util_fd_sync): Likewise. - (grub_util_fd_open): Likewise. - (grub_util_fd_strerror): New proto. - -2013-09-24 Vladimir Serbinenko - - * util/getroot.c (grub_util_biosdisk_is_present): Don't do stat on - platforms on which it doesn't work. - -2013-09-24 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Move struct - stat immediately to where it's used. - -2013-09-24 Vladimir Serbinenko - - * util/getroot.c (grub_util_check_block_device): Move to ... - * util/getroot_unix.c (grub_util_check_block_device): ... here. - * util/getroot.c (grub_util_check_char_device): Move to ... - * util/getroot_unix.c (grub_util_check_char_device): ... here. - -2013-09-24 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_close): Fix - disk closing logic. - -2013-09-24 Andrey Borzenkov - - * docs/grub.texi (Simple configuration): Document GRUB_ENABLE_CRYPTODISK. - -2013-09-24 Andrey Borzenkov - - * docs/grub.texi (File name syntax): Document ZFS filenames - (/volume@snapshot/...). - -2013-09-23 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk_windows.c (grub_util_get_windows_path): - Always return full path. Fixes a problem with mkrelpath. - -2013-09-23 Paulo Flabiano Smorigo - - * util/grub-install.in: Add GPT PReP support. - * util/grub-probe.c (probe): Support GPT partition type. - (main): Support -t gpt_parttype. - -2013-09-23 Aleš Nesrsta - - * grub-core/bus/usb/ehci.c: SMI disabled in all cases - -2013-09-23 Massimo Maggi - - * grub-core/fs/zfs/zfs.c (check_pool_label): Check nvlist. - -2013-09-23 Tim Hardeck - - * util/grub.d/10_hurd.in: Filter out character for the class. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - -2013-09-23 Melki Christian - - * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Fix the type of - "changed". - -2013-09-23 Josh Triplett - - * grub-core/boot/i386/pc/lnxboot.S: Re-add support for recording the - boot partition. - -2013-09-23 Vladimir Serbinenko - - * Makefile.util.def (libgrubmods.a): Remove CFLAGS_POSIX as this lib - doesn't use posix_wrap. Keep literal -fno-builtin however. - -2013-09-23 Vladimir Serbinenko - - * conf/Makefile.common (CPPFLAGS_LIBFDT): Remove leftover. - -2013-09-23 Vladimir Serbinenko -2013-09-23 neil - - * configure.ac: Do not enable -Wmissing-noreturn as its - usefulness is limited and creates problems on some OS notably with - code generated by bison. - -2013-09-23 Vladimir Serbinenko -2013-09-23 neil - - * configure.ac: Do not explicitly enable -Waddress as it's not - supported by all gcc and when it is, it's already enabled by -Wall. - -2013-09-23 Vladimir Serbinenko - - * grub-core/video/efi_gop.c (grub_video_gop_setup): Fix a typo which - desactivated use of EDID at all. - -2013-09-23 Vladimir Serbinenko -2013-09-23 neil - - * grub-core/loader/multiboot.c (grub_multiboot_set_console): Always use - video if no text is available. - -2013-09-23 Vladimir Serbinenko -2013-09-23 neil - - * configure.ac: Substitute TARGET_RANLIB. - -2013-09-23 Vladimir Serbinenko -2013-09-23 neil - - * grub-core/genmod.sh.in: Remove ./ from TARGET_OBJ2ELF. Add quotes. - - Based on patches from AROS. - -2013-09-23 Vladimir Serbinenko -2013-09-23 neil - - * grub-core/Makefile.am: Override STRIP and RANLIB. - * configure.ac: compute TARGET_RANLIB. - * INSTALL: Document TARGET_RANLIB - - Based on patches from AROS. - -2013-09-23 Vladimir Serbinenko - - * util/getroot.c (grub_util_biosdisk_get_grub_dev): Do not assume - that floppies are unpartitioned. - -2013-09-23 Vladimir Serbinenko - - * util/getroot_unix.c [__MINGW32__ || __CYGWIN__]: - Define dummy grub_util_pull_lvm_by_command to decrease number of #if's. - -2013-09-23 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/sys/types.h: Use OpenBSD approach: it's - less nice but more portable. - * grub-core/lib/posix_wrap/wchar.h: Likewise. - -2013-09-23 Vladimir Serbinenko - - * include/grub/cryptodisk.h (grub_cryptodisk): Use grub_util_fd_t - for cheat_fd. - * grub-core/disk/cryptodisk.c (grub_cryptodisk_open): Use grub_util_* - functions. - (grub_cryptodisk_cheat_insert): Likewise. - (grub_cryptodisk_close): Likewise. - -2013-09-23 Vladimir Serbinenko - - * include/grub/emu/misc.h: Remove leftover cygwin definitions. - Use windows path for DEFAULT_DIRECTORY. - -2013-09-23 Vladimir Serbinenko - - * include/grub/i386/setjmp.h: Remove useless #if MINGW where original - difference was likely just gcc version, not anything mingw-related. - -2013-09-23 Vladimir Serbinenko - - Use Winapi on both cygwin and mingw32 to share more code between both. - -2013-09-22 Andrey Borzenkov - - * util/grub-install.in: Add --grub-editenv option. - * util/grub-install_header (grub_compress_file): Explicitly check for - plain file to avoid cp error. - -2013-09-22 Andrey Borzenkov - - * docs/grub.texi (Device syntax): Document new LVM UUID based device - names; fix LVM driver name (lvm, not lv). - * util/grub-probe.c (probe_abstraction): Support lvmid/xxx device - names. - -2013-09-22 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c: Disentagle into a series of OS-specific - files rather than one file with loads of #if's. - * util/getroot.c: Likewise. - -2013-09-22 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/sys/types.h: Use stddef on *BSD. - -2013-09-22 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c (grub_get_random): Add windows and - GNU/Hurd to the list of checked PRNG. - -2013-09-22 Vladimir Serbinenko - - * configure.ac: On FreeBSD use -melf_*_fbsd format. - -2013-09-21 Ales Nesrsta - - * grub-core/bus/usb/ehci.c: Corrected EHCI QH handling (async./sync.) - -2013-09-20 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c: Handle non-md UUIDs. - * grub-core/disk/lvm.c: Add LVM UUIDs. - * util/getroot.c: Use LVM UUIDs whenever possible. - -2013-09-19 Andrey Borzenkov - - * docs/grub.texi (Networking commands): Add documentation for - network related commands. - -2013-09-19 Vladimir Serbinenko - - * util/getroot.c (grub_util_open_dm): Check major rather than the name - to determine if device is handled by devmapper. - (convert_system_partition_to_system_disk): Likewise. - (get_dm_uuid): Don't check explicitly if device is mapped, it's - already done in grub_util_open_dm. - -2013-09-19 Leif Lindholm - - * kern/arm/cache.S: Correct access to ilinesz/dlinesz variables. - Clean up stack manipulation (sync_caches_armv*) - -2013-09-19 Vladimir Serbinenko - - * util/lvm.c: Remove since unused. Remove remaining references. - -2013-09-19 Vladimir Serbinenko - - Handle the case of partitioned LVM properly. - - * grub-core/kern/emu/hostdisk.c (grub_util_get_dm_node_linear_info): - Stop on meeting LVM, mpath or DMRAID. - (grub_hostdisk_os_dev_to_grub_drive): Canonicalize os device. - (read_device_map): Likewise. - * util/getroot.c (convert_system_partition_to_system_disk): Assume that - device is full disk rather than erroring out on LVM and similar cases. - -2013-09-18 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in: Keep supplied pkgdatadir if any. - -2013-09-18 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_mm_init_region): Skip regions less than - 4K before the end. - Reported by: Leif Lindholm - -2013-09-18 Pawel Wojtalczyk -2013-09-18 Vladimir Serbinenko - - * grub-core/term/efi/console.c (grub_console_getkey): Accept VT100-style - codes. - -2013-09-18 Colin Watson - - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name_iter): - Remove no-longer-true __attribute__ ((unused)) on disk parameter. - -2013-09-18 Douglas Ray - - * util/grub-mkpasswd-pbkdf2.c (grub_get_random): Declare OpenBSD PRNG - as secure. - -2013-09-18 Aleš Nesrsta - - * docs/grub.texi: Fix broken link. - -2013-09-18 Melki Christian - - * grub-core/bus/usb/usb.c (grub_usb_device_initialize): Add condition - to break endless loop. - -2013-08-23 Vladimir Serbinenko - - * util/grub-fstest.c: Fix several printf formats. - * util/grub-mkimage.c: Likewise. - * util/grub-mkimagexx.c: Likewise. - * util/grub-script-check.c: Likewise. - -2013-08-23 Vladimir Serbinenko - - * grub-core/lib/xzembed/xz_dec_lzma2.c: Make -Wattributes not cause - error. - -2013-08-23 Vladimir Serbinenko - - * config.h.in [GRUB_BUILD]: Explicitly undefine ENABLE_NLS. - -2013-08-23 Vladimir Serbinenko - - * util/getroot.c (grub_find_device): Use cygwin_conv_path ratherthan - removed in current versions cygwin_conv_*. - -2013-08-23 Vladimir Serbinenko - - * configure.ac: Disable efiemu runtime on cygwin. - -2013-08-23 Vladimir Serbinenko - - * conf/Makefile.extra-dist: Add missing util/grub-gen-asciih.c, - util/grub-gen-widthspec.c and util/grub-pe2elf.c. - -2013-08-22 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c (grub_password_get): Remove extraneous - error message. - -2013-08-22 Vladimir Serbinenko - - * grub-core/lib/crypto.c (grub_password_get) [GRUB_UTIL]: Add - windows variant. - * util/grub-mkpasswd-pbkdf2.c: Add windows flavour for retrieving random - data. - -2013-08-22 Vladimir Serbinenko - - * configure.ac: Add -Wl,-melf_i386 and -Wl,-melf_x86_64 systematically - when on x86 and not cygwin. - * conf/Makefile.common: Remove unsystematic -Wl,-melf_i386 and - -Wl,-melf_x86_64. - -2013-08-22 Vladimir Serbinenko - - * configure.ac: Set CPP to build one when checkoing for freetype for - build. - -2013-08-22 Vladimir Serbinenko - - * util/grub-mkfont.c [!GRUB_BUILD]: Define my_argp_state. - [!GRUB_BUILD]: Remove has_argument. - -2013-08-22 Vladimir Serbinenko - - * util/ieee1275/ofpath.c (grub_util_devname_to_ofpath) [_WIN32]: - Replace with a dummy. - -2013-08-22 Vladimir Serbinenko - - * configure.ac: Don't change host_os from mingw to cygwin. - -2013-08-22 Vladimir Serbinenko - - * configure.ac: Change target_os from windows to cygwin. - -2013-08-22 Vladimir Serbinenko - - Handle grub-pe2elf and grub-mkfont for cases when build != host. - - * Makefile.am (build-grub-mkfont): Don't include gnulib. - (build-grub-gen-asciih): Likewise. - (build-grub-gen-widthspec): Likewise. - * Makefile.util.def (grub-pe2elf): Remove. - * config.h.in [GRUB_BUILD]: Use build rather than host constants. - * configure.ac: Separate tests for build. - Move ./build-grub-pe2elf to grub-core. - Fix typo. - * grub-core/Makefile.am (build-grub-pe2elf): New target. - * grub-core/kern/emu/misc.c (xasprintf): Don't compile if GRUB_BUILD is - defined. - * include/grub/types.h [GRUB_BUILD]: Use build rather than host - constants. - * util/grub-mkfont.c [GRUB_BUILD]: Simplify not to rely on argp. - * util/grub-pe2elf.c: Simplify not to rely on getopt. - * util/misc.c (program_name) [GRUB_BUILD]: Define to static string. - -2013-08-22 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_size): Adapt for - mingw32 as well based on grub_util_get_disk_size. - * util/misc.c (grub_util_get_disk_size): Removed. all users switched to - grub_util_get_fd_size. - (sync): Removed. - (fsync): Moved to ... - * grub-core/kern/emu/misc.c (fsync): ... here. - -2013-08-22 Vladimir Serbinenko - - * include/grub/mm.h (grub_extend_alloc): Remove. - * grub-core/loader/i386/pc/plan9.c: Use own version of - grub_extend_alloc with appropriate types. - -2013-08-22 Vladimir Serbinenko - - * conf/Makefile.common (CFLAGS_GCRY): Add -Wno-redundant-decls. - -2013-08-22 Vladimir Serbinenko - - * util/getroot.c: Include sys/wait.h only when we need waitpid. - -2013-08-22 Vladimir Serbinenko - - Fix dependencies on cygwin. - - * gentpl.py: Support variable dependencies. Add $TARGET_OBJ2ELF to - dependencies when used and defined. - * grub-core/Makefile.core.def (regexp): Add dependency on libgnulib.a. - -2013-08-22 Vladimir Serbinenko - - * include/grub/zfs/spa.h (zio_cksum): Add explicit members for mac. - * grub-core/fs/zfs/zfs.c (zio_read): Don't use casts to retrieve mac. - -2013-08-22 Vladimir Serbinenko - - * grub-core/kern/emu/mm.c (grub_memalign): Don't define if there is no - implementation available to cause compile-time rather than runtime - error. - -2013-08-22 Vladimir Serbinenko - - * util/grub-fstest.c: Don't check for symlinks on windows. - -2013-08-22 Vladimir Serbinenko - - * INSTALL: Mention unavailability of man pages when cross-compiling. - -2013-08-22 Vladimir Serbinenko - - * include/grub/crypto.h: Don't declare gcry_log_bug, gcry_log_printf - and gcry_log_bug. - * grub-core/lib/libgcrypt_wrap/mem.c: Include g10lib.h - -2013-08-21 Vladimir Serbinenko - - * INSTALL: Document cross-compilation. - * acinclude.m4: Determine whether nm support -P and --defined-only. - * configure.ac: Add TARGET_ to all variables pertaining to target - that don't have it yet. - * gentpl.py: Likewise. - * grub-core/Makefile.am: Likewise. - * grub-core/genmod.sh.in: Likewise. - * grub-core/gensyminfo.sh.in: Handle OpenBSD and other non-GNU nm - as well. - -2013-08-21 Ilya Bakulin - - * configure.ac: Remove -Wempty-body. It's not essential and needs - recent gcc. - -2013-08-21 Ilya Bakulin - - * grub-core/kern/emu/hostdisk.c: Add conditionals for OpenBSD. - * util/getroot.c: Likewise. - -2013-08-21 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Add needed explicit cast. - * grub-core/lib/backtrace.c: Likewise. - * grub-core/net/ip.c: Likewise. - * grub-core/net/tcp.c: Likewise. - * grub-core/net/udp.c: Likewise. - -2013-08-21 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/wchar.h: Fix typo. - -2013-08-21 Vladimir Serbinenko - - * util/import_gcry.py: Add final newline in visibility.h. - -2013-08-21 Vladimir Serbinenko - - * conf/Makefile.common: Fix typo. - -2013-08-21 Vladimir Serbinenko - - * Makefile.util.def (grub-mkfont): Add missing libgnu.a. - -2013-08-21 Vladimir Serbinenko - - * Makefile.am (widthspec.h): Fix typo. - * util/grub-gen-widthspec.c: Likewise. - -2013-08-21 Vladimir Serbinenko - - Move ascii.h and widthspec.h generation to a separate build-time-only - tool. - -2013-08-16 Grégoire Sutre - - * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): - Always fill bootdisk info and improve check for NetBSD disklabel. - -2013-08-16 Vladimir Serbinenko - - * conf/Makefile.extra-dist: Add util/bin2h.c. - Reported by: floppym. - -2013-08-16 Vladimir Serbinenko - - * configure.ac: Make unifont mandatory for powerpc-ieee1275. - -2013-08-16 Vladimir Serbinenko - - * configure.ac: Disable unifont and starfield if no freetype was found. - -2013-08-16 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/wchar.h: Fix wchar_t and mbstate_t conflict - on NetBSD and OpenBSD. - -2013-08-15 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: Baseline misplacement fixed. - -2013-08-15 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: The number of color mappings is - reduced. Inheritant options are processed during the theme loading. - -2013-08-15 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: Minimal width fixed. - -2013-08-14 Avik Sil - - * grub-core/net/tftp.c: Send tftp ack packet before closing the socket. - -2013-08-14 Avik Sil - - * grub-core/net/drivers/ieee1275/ofnet.c: Get proper mac address when - using qemu. - -2013-08-14 Paulo Flabiano Smorigo - - * .bzrignore: Add bootinfo.txt, grub.chrp, gnulib/float.h, and - remove-potcdate.sed. - -2013-08-14 Andrey Borzenkov - - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_iterate): Remove - unused attribute from pull argument. - -2013-08-14 Andrey Borzenkov - - * util/getroot.c (grub_util_is_imsm): Fix descriptor and - memory leak. - -2013-08-14 Andrey Borzenkov - - * util/getroot.c (pull_lvm_by_command): add --separator option - to vgs call to disable padding of output to 10 characters. - -2013-08-14 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c (grub_device_mapper_supported): Move from - here ... - * grub-core/kern/emu/hostdisk.c (grub_device_mapper_supported): ... to - here. - -2013-08-14 Vladimir Serbinenko - - * include/grub/i386/pc/biosdisk.h (grub_biosdisk_drp): Fix device_path - length. - -2013-08-14 Vladimir Serbinenko - - Fix handling of build-time grub-bin2h and grub-mkfont when doing - full Canadian cross. Tested with build=x86_64, host=arm, - target=ppc-ieee1275. - -2013-08-14 Vladimir Serbinenko - - * configure.ac: Error if no $BUILD_CC could be found. - Reported by: DevHC. - -2013-08-14 Vladimir Serbinenko - - * grub-core/kern/i386/coreboot/init.c: Fix compilation on - i386-multiboot. - -2013-08-14 Vladimir Serbinenko - - * grub-core/kern/vga_init.c: Fix compilation on qemu-mips. - * grub-core/kern/mips/qemu_mips/init.c: Likewise. - -2013-08-13 Colin Watson - - * util/getroot.c (grub_util_biosdisk_get_grub_dev): Zero out - grub_errno in the case where we handle GRUB_ERR_UNKNOWN_DEVICE by - falling back to the partition device, otherwise a later call to this - function may fail spuriously. - Reported by Axel Beckert. Fixes Debian bug #708614. - -2013-08-12 Grégoire Sutre - - * autogen.sh: Replace find -not by the POSIX-compliant find !. - -2013-08-12 Grégoire Sutre - - Prevent shadowing of stdlib's devname(3) on BSD. - - * grub-core/disk/cryptodisk.c (grub_cmd_cryptomount): Rename devname - and devlast to diskname and disklast, respectively. - -2013-08-11 Colin Watson - - * util/grub-mkconfig.in: Fix detection of Emacs autosave files. - -2013-08-08 Vladimir Testov - - * docs/grub.texi: Introduce terminal window position options: - terminal-left: terminal window's left position - terminal-top: terminal window's top position - terminal-width: terminal window's width - terminal-height: terminal window's height - terminal-border: terminal window's border width - * grub-core/gfxmenu/theme-loader.c: Likewise. - * include/grub/gfxmenu_view.h: Likewise. - * po/exlude.pot: Likewise. - * grub-core/gfxmenu/view.c: Likewise. - Also updated minimal window size. - Also terminal_sanity_check function has been introduced. - * grub-core/tests/checksums.h: Update (terminal window height - is adjusted now for low resolution screen) - -2013-08-02 Vladimir Serbinenko - - * grub-core/tests/checksums.h: Update (1-pixel difference in marker - position). - -2013-08-02 Vladimir Serbinenko - - * po/exclude.pot: Add few recent exceptions. - -2013-08-02 Vladimir Serbinenko - - * tests/grub_func_test.in: Add unicode.pf2. - -2013-08-02 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Start with - standard rather than noral color, in line with other terminals. - -2013-08-02 Vladimir Serbinenko - - * grub-core/partmap/dfly.c: Simplify dprintfs for easier gettext - analysis. - -2013-08-02 Vladimir Serbinenko - - * grub-core/loader/arm/linux.c: Change printf to dprintf. - -2013-08-02 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (check_feature): Cleanup and remove - inappropriate printf. - -2013-07-25 Andrey Borzenkov - - * .bzrignore: Remove grub-core/lib/dtc-grub, - grub-core/Makefile.libfdt.def - * conf/Makefile.extra-dist: Remove grub-core/Makefile.libfdt.def. - -2013-07-25 Vladimir Serbinenko - - * include/grub/video.h (grub_video_register): Keep double-linked as - well as single-linked invariants. - Reported by: qwertial. - -2013-07-25 Vladimir Serbinenko - - * grub-core/commands/nativedisk.c (get_uuid): Handle - GRUB_DISK_DEVICE_UBOOTDISK_ID. - -2013-07-25 Vladimir Testov - - * grub-core/gfxmenu/widget-box.c: Fixed draw function. Now it takes - maximum of NW, N, NE heights instead of N's height and maximum of - NW, W, SW widths instead of W's width. (So the box will be always - correctly drawn) - -2013-07-20 Grégoire Sutre - - * grub-core/partmap/bsdlabel.c (netopenbsdlabel_partition_map_iterate): - Fix misuse of variable count. - -2013-07-18 Leif Lindholm -2013-07-18 Francesco Lavra -2013-07-18 Vladimir Serbinenko - - New ports to arm-uboot and arm-efi. - Mostly by Leif Lindholm with some additions from - Francesco Lavra and cleanup by Vladimir Serbinenko. - -2013-07-16 Vladimir Serbinenko - - * grub-core/loader/multiboot_elfxx.c: Check eip after v2p translation - and not before. - Reported by: Leon Drugi. - -2013-07-16 Vladimir Serbinenko - - * grub-core/kern/powerpc/ieee1275/startup.S: Handle unaligned bss. - Reported by: Paulo Flabiano Smorigo. - -2013-07-14 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: USe viewport when drawing strings. - -2013-07-14 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: Fix height calculation. - -2013-07-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c: Stylistic fixes. - -2013-07-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c: Run emacs indent on file. - -2013-07-14 Andrey Borzenkov - - * grub-core/net/bootp.c: Export net_* variables. - * grub-core/net/net.c: Likewise. - -2013-07-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c: Remove brackets around return value. - -2013-07-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs_lz4.c: Add missing packed attribute. - -2013-07-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (nvlist_next_nvpair): Fix improper cast. - -2013-07-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs_lz4.c: Remove restrict keyword. - -2013-07-14 Massimo Maggi - - * grub-core/fs/zfs/zfs.c (nvlist_next_nvpair): Error is encode_size - <= 0. - -2013-07-14 Massimo Maggi - - * grub-core/fs/zfs/zfs.c: Split nvpair iterators into separate - functions. - -2013-07-14 Massimo Maggi - - * grub-core/fs/zfs/zfs_lz4.c: New file. - * grub-core/fs/zfs/zfs.c: Tie up lz4 decompression. - -2013-07-14 Massimo Maggi - - * grub-core/fs/zfs/zfs.c: Check for feature compatibility. - -2013-07-14 Massimo Maggi - - * grub-core/fs/zfs/zfs.c (uberblock_verify): Accept version 5000. - (check_pool_label): Likewise. - * include/grub/zfs/zfs.h: Rewrite SPA_VERSION_* macros. - -2013-07-14 Massimo Maggi - - * grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Fix RAIDZ reporting. - -2013-07-13 Andrey Borzenkov - - * docs/grub.texi (Commands): Document postition parameters - for menuentry command. - -2013-07-13 Andrey Borzenkov - - * util/grub-mknetdir.in: Remove stray line from help output. - -2013-07-11 Vladimir Serbinenko - - Remove early sm712 init as there is no reason for it (the "watchdog" - effect was due to wrong GPIO map). - -2013-07-11 Vladimir Serbinenko - - * grub-core/commands/pcidump.c: Remove static variables. - -2013-07-11 Vladimir Serbinenko - - * grub-core/commands/sleep.c: Refresh screen before sleeping. - -2013-07-11 Vladimir Serbinenko - - * configure.ac: Move delimiter after the infos. - -2013-07-11 Vladimir Serbinenko - - * grub-core/bus/usb/usbhub.c: Fix recheck logic. - -2013-07-11 Vladimir Serbinenko - - * util/grub-mkfont.c (write_font_ascii_bitmap): Fix handling of glyphs - not filling whole 8x16 space. - -2013-07-11 Vladimir Serbinenko - - * grub-core/normal/charset.c (bidi_line_wrap): Fix spurios warning. - -2013-07-11 Vladimir Serbinenko - - * configure.ac: Indicate which liblzma is used if any. - -2013-06-21 Paul Wise -2013-06-21 Craig Sanders - - * util/grub-reboot.in: Document submenu usage. - -2013-06-25 Colin Watson - - * .bzrignore: Update with a number of new test-related files. - -2013-06-25 Colin Watson - - * util/grub-script-check.c: Fail on scripts containing no - commands, to guard against corrupted grub-mkconfig setups that - produce no useful output. - * tests/grub_script_no_commands.in: New test. - * Makefile.util.def (grub_script_no_commands): Add. - Reported by Hans Putter. Fixes Debian bug #713886. - -2013-06-16 Andrey Borzenkov - - * grub-core/disk/diskfilter.c: Forgot to remove comment - from previous commit. - -2013-06-16 Andrey Borzenkov - - * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use - grub_term_normal_color, do not hardcode GRUB_TERM_DEFAULT_NORMAL_COLOR. - -2013-06-16 Andrey Borzenkov - - * conf/Makefile.extra-dist: Add grub-core/fs/cpio_common.c. - -2013-06-16 Andrey Borzenkov - - * grub-core/disk/diskfilter.c (scan_devices): Iteratively - rescan diskfilter devices until nothing new is found. - -2013-06-16 Vladimir Serbinenko - - Fix casts when compiling coreboot-specific code for 64-bit EFI. - -2013-06-16 Vladimir Serbinenko - - Don't try to detect cbfs on *-emu. - -2013-06-16 Vladimir Serbinenko - - * grub-core/term/gfxterm.c: USe right background color when scrolling. - -2013-06-16 Vladimir Serbinenko - - Add support for processed coreboot payload chainloading. - -2013-06-16 Vladimir Serbinenko - - Enable coreboot information commands even when not loaded as - coreboot payload (e.g. when loaded from SeaBIOS-as-payload). - -2013-06-15 Vladimir Serbinenko - - Support for cbfs. Also factor out the part which is common - for all archives to a separate module. This splits tar from cpio - as they are very different but keeps cpio, cpio_be, odc and newc - together since they're very similar. - -2013-06-15 David Michael - - * configure.ac (FREETYPE): Change AC_CHECK_PROGS to AC_CHECK_TOOLS. - (freetype_cflags,freetype_libs): Change freetype-config to $FREETYPE. - -2013-06-15 Vladimir Serbinenko - - * tests/grub_script_eval.in: Really add the eval test. - -2013-06-14 Vladimir Serbinenko - - Move flavour-specific parts out of common cpio.c file and - rename remaining to cpio_common.c - -2013-06-07 Andrey Borzenkov - - * grub-core/script/execute.c (grub_script_execute_sourcecode): Split - off new function grub_script_execute_new_scope. Change callers to use - either of them as appropriate. - * grub-core/commands/eval.c: New command eval. - * docs/grub.texi (Commands): Document it. - -2013-06-07 Andrey Borzenkov - - * grub-core/kern/corecmd.c (grub_core_cmd_set): Use grub_env_get - to fetch values when listing. - -2013-06-07 Andrey Borzenkov - - Fix make dist on non-pc. - -2013-06-07 Francesco Lavra - - * grub-core/kern/corecmd.c (grub_core_cmd_ls): Fix handling of paths - without a device name. - -2013-06-07 Vladimir Serbinenko - - Remove enable_executable_check as it's not needed anymore. - Reported by: dougray. - -2013-06-07 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (insert_array): Fix order to discover - ambigouos RAID before discovering RAIDs on top of it. - Reported by: bodom. - -2013-06-07 Vladimir Serbinenko - - Fix typo (failback vs fallback). - -2013-05-31 Andrey Borzenkov - - * util/grub.d/30_os-prober.in: Add support for probing EFI - System Partition (as of os-prober 1.58). - -2013-05-31 Vladimir Serbinenko - - * configure.ac: Add yet another path to unifont. For parabola. - -2013-05-30 Josh Triplett - - * grub-core/normal/cmdline.c (grub_cmdline_get): Fix Ctrl-u - handling to copy the killed characters to the kill buffer as - UCS4 stored as grub_uint32_t rather than as 8-bit characters - stored as char. Eliminates UCS4 truncation and corruption - observed when killing characters with Ctrl-u and yanking them - back with Ctrl-y. - -2013-05-30 Vladimir Serbinenko - - Detach optional parts of gfxterm and integrate in with coreboot init. - -2013-05-30 Vladimir Serbinenko - - Move blit and fill dispatcher to appropriate files to decrease export - and relocation overhead. - -2013-05-30 Vladimir Serbinenko - - * grub-core/font/font.c, include/grub/font.h: Inline simple font - functions. - -2013-05-30 Vladimir Serbinenko - - * grub-core/Makefile.am: Fix compilation problem with some - automake versions. - -2013-05-30 Vladimir Serbinenko - - * configure.ac: Add Ubuntu path to unifont and report unifont path used. - -2013-05-30 Vladimir Serbinenko - - * Makefile.am, conf/Makefile.common: Fix compilation problem with some - automake versions. - -2013-05-30 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c: Fix handling of DSDT in presence of - SSDT. - -2013-05-15 Radosław Szymczyszyn - - * grub-core/partmap/dfly.c: New partition map. - -2013-05-15 Vladimir Serbinenko - - * grub-core/kern/corecmd.c (grub_core_cmd_ls): Fix empty path - checking. - Reported by: Francesco Lavra. - -2013-05-14 Andrey Borzenkov - - * gentpl.py: Replace EXTRA_DIST with dist_noinst_DATA or - dist__DATA. EXTRA_DIST is ignored by automake inside - false conditions. - * conf/Makefile.common: define dist_grubconf_DATA - -2013-05-14 Vladimir Serbinenko - - Progressively skip menu elements on small terminals rather - than crashing. - -2013-05-14 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (grub_cmdline_get): Fix off-by-one error - to avoid losing last column. - -2013-05-14 Vladimir Serbinenko - - * po/exclude.pot: Add missing string "%C". - -2013-05-14 Vladimir Serbinenko - - * tests/util/grub-shell.in: Remove the temporary directory on grub-emu - after the test. - -2013-05-11 Vladimir Serbinenko - - * util/grub-install.in: Gettextize "Not found" message. - -2013-05-11 Vladimir Serbinenko - - Fix distfiles list. - Reported by: Andrey Borzenkov - -2013-05-11 Paulo Flabiano Smorigo - - * grub-core/net/bootp.c (grub_cmd_bootp): Check if there is any card - present. - * include/grub/err.h (grub_err_t): New enum value GRUB_ERR_NET_NO_CARD. - -2013-05-11 Vladimir Serbinenko - - * grub-core/tests/setjmp_test.c: Ignore missing noreturn. - -2013-05-11 Vladimir Serbinenko - - * grub-core/fs/hfspluscomp.c (grub_hfsplus_compress_attr): Add packed - attribute since structure is not necessarily aligned. - -2013-05-11 Andrey Borzenkov - - * docs/grub.texi (Device syntax): Clarify description of network - drives. - -2013-05-10 Vladimir Serbinenko - - Redirect xasprintf to grub_xvasprintf rather than having #ifdef's - for vasprintf presence. - -2013-05-10 Vladimir Serbinenko - - * util/grub-install.in: Handle efibootmgr presence check. - Reported by: Leif Lindholm. - -2013-05-10 Vladimir Serbinenko - - * grub-core/commands/testspeed.c: Reuse formatting string to decrease - new strings to translate. - -2013-05-10 Vladimir Serbinenko - - * util/grub-mkrescue.in: Replace `STR' with `STRING' to avoid adding - yet another string (pun intended) to translate. - -2013-05-10 Vladimir Serbinenko - - * po/POTFILES-shell.in: Autogenerate it. - -2013-05-10 Vladimir Serbinenko - - * grub-core/net/net.c (grub_net_open_real): Autoload network modules. - -2013-05-10 Vladimir Serbinenko - - * grub-core/term/terminfo.c: Rename ANSI_C0 to ANSI_CSI to avoid - misnomer. - -2013-05-08 Andrey Borzenkov - - * docs/grub.texi (Network): Add description of net_default_interface, - net_default_ip and net_default_mac. Rewrite variables description - to emphasize that they are per-interface. - -2013-05-08 Vladimir Serbinenko - - New test: cmdline and cat. - -2013-05-08 Vladimir Serbinenko - - * grub-core/commands/cat.c: Show UTF-8 characters. - -2013-05-08 Vladimir Serbinenko - - * conf/Makefile.common: Poison float and double on non-emu. - -2013-05-08 Vladimir Serbinenko - - * configure.ac: Don't disable extended registers on emu. - -2013-05-07 Vladimir Serbinenko - - * configure.ac: Don't use extended registers on x86_64. - Reported by: Peter Jones. - -2013-05-07 Vladimir Serbinenko - - * grub-core/term/efi/console.c: Fix compile error. - -2013-05-07 Vladimir Serbinenko - - Compressed HFS+ support. - -2013-05-07 Vladimir Serbinenko - - * grub-core/commands/videoinfo.c: Use "paletted" rather than "packed - pixel". - -2013-05-07 Vladimir Serbinenko - - Menu color test. - -2013-05-07 Vladimir Serbinenko - - * grub-core/tests/setjmp_test.c: New test. - -2013-05-07 Vladimir Serbinenko - - New variables 'net_default_*' to determine MAC/IP of default interface. - -2013-05-07 Vladimir Serbinenko - - * tests/gettext_strings_test.in: A test to check for strings not - marked for translation. - -2013-05-07 Vladimir Serbinenko - - * autogen.sh: Exclude unused libgcrypt files from translation. - -2013-05-07 Vladimir Serbinenko - - Simplify few strings. - -2013-05-07 Vladimir Serbinenko - - Mark few forgotten strings for translation. - -2013-05-07 Vladimir Serbinenko - - * grub-core/loader/linux.c: Use grub_dprintf for debug statements - rather than printf. - -2013-05-07 Vladimir Serbinenko - - * grub-core/video/readers/jpeg.c: Use grub_dprintf for debug statements - rather than printf. - * grub-core/video/readers/tga.c: Likewise. - -2013-05-07 Vladimir Serbinenko - - * tests/priority_queue_unit_test.cc: New test. - -2013-05-07 Vladimir Serbinenko - - * grub-core/font/font.c: Use grub_dprintf for debug statements rather - than printf. - -2013-05-06 Andrey Borzenkov - - Reimplement grub-reboot to not depend on saved_entry. Use next_entry - variable for one time boot menu entry. - -2013-05-05 Bean - - * grub-core/commands/testspeed.c: New command testspeed. - -2013-05-05 Vladimir Serbinenko - - Factor-out human-size printing. - -2013-05-04 Vladimir Serbinenko - - Agglomerate more mallocs to speed-up gfxterm. - -2013-05-04 Vladimir Serbinenko - - Speed-up gfxterm by slightly agglomerating mallocs. - -2013-05-04 Vladimir Serbinenko - - More video checks. - -2013-05-04 Vladimir Serbinenko - - Speed-up gfxterm by saving intermediate results in index+alpha - format. - -2013-05-04 Vladimir Serbinenko - - * grub-core/tests/lib/functional_test.c: Don't stop on first failed - test. - -2013-05-04 Vladimir Serbinenko - - * grub-core/normal/menu_text.c (menu_clear_timeout): Clear second - line of timeout as it may contain the rest of long line. - -2013-05-04 Vladimir Serbinenko - - * grub-core/normal/main.c: Fix freed memory dereference. - -2013-05-04 Vladimir Serbinenko - - Fix several memory leaks. - -2013-05-04 Vladimir Serbinenko - - * grub-core/normal/menu.c (run_menu): Fix timeout reference point. - -2013-05-04 Vladimir Serbinenko - - * grub-core/gettext/gettext.c: Try $lang.gmo as well. - -2013-05-04 Vladimir Serbinenko - - Fix test -a and -o precedence. - Reported by: adrian15. - -2013-05-04 Vladimir Serbinenko - - * grub-core/font/font.c (grub_font_construct_glyph): Fix memory leak. - -2013-05-03 Andrey Borzenkov - - Rename grub-core/tests/checksums.c into grub-core/tests/checksums.h - and add it as source to functional_test module. - -2013-05-03 Vladimir Serbinenko - - * grub-core/tests/video_checksum.c: Don't set GENERATE_MODE. - -2013-05-03 Vladimir Serbinenko - - New series of tests for gfxterm and gfxmenu. - -2013-05-03 Vladimir Serbinenko - - * grub-core/gfxmenu/gfxmenu.c (grub_gfxmenu_try): Allow specifying - the theme path relative to $prefix/themes. - -2013-05-03 Vladimir Serbinenko - - * grub-core/video/fb/fbblit.c (grub_video_fbblit_blend_BGR888_RGBA8888): - Fix order bug. - (grub_video_fbblit_blend_RGB888_RGBA8888): Likewise. - -2013-05-03 Vladimir Serbinenko - - * include/grub/gui.h (grub_gfxmenu_timeout_unregister): Free cb - descriptor. - -2013-05-03 Vladimir Serbinenko - - * grub-core/gfxmenu/view.c (grub_gfxmenu_view_new): Clear - grub_gfxmenu_timeout_notifications. - (grub_gfxmenu_view_destroy): Likewise. - -2013-05-03 Vladimir Serbinenko - - * grub-core/normal/term.c (print_ucs4_real): Fix startwidth in dry run. - -2013-05-02 Vladimir Serbinenko - - Several fixes to ieee1275 and big-endian video. - -2013-05-02 Vladimir Serbinenko - - Add missing exports on mips. - -2013-05-02 Vladimir Serbinenko - - * grub-core/tests/videotest_checksum.c (videotest_checksum): Error out - if no unifont is found. - Restore original keyboard. - -2013-05-02 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add - GRUB_VIDEO_ADAPTER_CAPTURE: to handled drived ids. - -2013-05-02 Vladimir Serbinenko - - First automated video test (running videotest and comparing results) - -2013-05-02 Vladimir Serbinenko - - * grub-core/commands/videotest.c: Reduce flickering and draw 6 squares - instead of 2 to have full RGB/CMY test pattern. - -2013-04-30 Vladimir Serbinenko - - Add few more tests. - -2013-04-30 Vladimir Serbinenko - - * include/grub/arc/arc.h: Account for missing "other" peripheral on - ARCS. All users updated. - -2013-04-30 Vladimir Serbinenko - - * grub-core/kern/mips/loongson/init.c: Support halt for loongson 2E. - -2013-04-30 Vladimir Serbinenko - - * grub-core/partmap/amiga.c: Fix size of checksummed block. - -2013-04-29 Vladimir Serbinenko - - * configure.ac: Use -mcmodel=large on x86_64-emu as well. - Reported by: qwertial. - -2013-04-29 Vladimir Testov - - * grub-core/gfxmenu/circular_progress.c: Set start_angle in degrees - with syntax "XXX deg"/"XXX °". - -2013-04-29 Vladimir Serbinenko - - Make PCI init in i386-qemu port more robust. - -2013-04-29 Vladimir Testov - - * grub-core/gfxmenu/gui_list.c: Refresh first_shown_entry value when - cached view is reused. - * grub-core/gfxmenu/view.c: Call the refresh procedure for all - open boot menus. - -2013-04-29 Vladimir Serbinenko - - Unify more code in grub-install_header. - -2013-04-29 Vladimir Serbinenko - - Add few new tests. - -2013-04-29 Vladimir Serbinenko - - Enforce disabling of firmware disk drivers when native drivers kick in. - -2013-04-29 Vladimir Serbinenko - - * grub-core/commands/nativedisk.c: Customize the list of modules on - platform. Don't try to search for disks already using native drivers. - -2013-04-29 Vladimir Serbinenko - - * grub-core/bus/usb/uhci.c: Fix DMA handling and enable on all PCI - platforms. - -2013-04-29 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_arglist_to_argv): Fix - handling of variables containing backslash. - -2013-04-29 Vladimir Serbinenko - - * include/grub/list.h (FOR_LIST_ELEMENTS_SAFE):Fix a NULL pointer - dereference. - Reported by: qwertial. - -2013-04-29 Vladimir Serbinenko - - * grub-core/kern/mips/arc/init.c: Fix prefix detection. - -2013-04-29 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_show_help): Fix a NULL pointer - dereference. - Reported by: qwertial. - -2013-04-28 Vladimir Serbinenko - - * docs/grub.texi: Add a comment about usefullness of nativedisk. - -2013-04-28 Vladimir Serbinenko - - * grub-core/commands/nativedisk.c: Ignore unknown filesystem error. - -2013-04-28 Vladimir Serbinenko - - New command `nativedisk'. - -2013-04-28 Vladimir Serbinenko - - * grub-core/io/lzopio.c: Use GRUB_PROPERLY_ALIGNED_ARRAY. - * grub-core/loader/i386/bsd.c: Likewise. - -2013-04-28 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Fix compilation for amd64 (format warnings). - -2013-04-28 Vladimir Serbinenko - - * include/grub/efi/api.h (GRUB_EFI_DEVICE_PATH_LENGTH): Use - grub_get_unaligned16 rather than shifts. - -2013-04-28 Vladimir Serbinenko - - * grub-core/kern/file.c: Use const char * rather than casting to - non-const. - -2013-04-28 Vladimir Serbinenko - - * grub-core/commands/probe.c: Add missing grub_device_close. - -2013-04-28 Vladimir Serbinenko - - * INSTALL: Document linguas.sh. - -2013-04-28 Vladimir Serbinenko - - Remove POTFILES.in and regenerate it in autogen.sh. - -2013-04-28 Vladimir Serbinenko - - Move --directory/--override-directorry to grub-install_header and unify. - -2013-04-28 Vladimir Serbinenko - - * grub-core/term/morse.c: Macroify dih and dah. - -2013-04-27 Paulo Flabiano Smorigo - - * include/grub/macho.h: Set GRUB_MACHO_FAT_EFI_MAGIC as unsigned. - -2013-04-27 Vladimir Serbinenko - - * grub-core/term/ns8250.c: Systematically probe ports by writing - to SR before using them. - -2013-04-27 Paulo Flabiano Smorigo - - * util/ieee1275/ofpath.c (of_path_of_scsi): Fix path output for sas - disks. - (check_sas): Get sas_adress info. - -2013-04-27 Vladimir Serbinenko - - * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix handling of empty - ports. - -2013-04-27 Leon Drugi - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Fix cast in - BSS clearing. - -2013-04-27 Vladimir Serbinenko - - Core compression test. - -2013-04-27 Vladimir Serbinenko - - Implement grub_machine_get_bootlocation for ARC. - -2013-04-27 Vladimir Serbinenko - - Improve AHCI detection and command issuing. - -2013-04-26 Vladimir Serbinenko - - Fix pseries test. - -2013-04-26 Vladimir Serbinenko - - Make 'make check' work on emu. - -2013-04-26 Vladimir Serbinenko - - Replace libcurses with our own vt100 handling for the ease of testing - and decreasing prerequisites. - -2013-04-26 Vladimir Serbinenko - - * grub-core/Makefile.core.def: Fix grub-emu and grub-emu-lite sources. - -2013-04-26 Vladimir Serbinenko - - * util/getroot.c (exec_pipe): Put proper #if's so that its users don't - compile when not needed. - -2013-04-26 Vladimir Serbinenko - - * tests/pseries_test.in: New test. - -2013-04-26 Vladimir Serbinenko - - Add test to check that different boot mediums work. - -2013-04-26 Vladimir Serbinenko - - * util/grub-mkrescue.in: Rename i386-ieee1275 core image due to - ofw limited ISO support. - -2013-04-26 Vladimir Serbinenko - - * configure.ac: Fix loongson conditional. - -2013-04-25 Vladimir Serbinenko - - Enable mipsel-arc. - -2013-04-25 Vladimir Serbinenko - - Add serial on ARC platform. - -2013-04-25 Vladimir Serbinenko - - * grub-core/boot/powerpc/bootinfo.txt.in: Missing update from previous - commit. - -2013-04-25 Vladimir Serbinenko - - * tests/partmap_test.in: Add missing double semicolon. - -2013-04-25 Vladimir Serbinenko - - * util/grub-mkrescue.in: Fix loongson filename. - -2013-04-25 Vladimir Serbinenko - - * util/grub-mkrescue.in: Move all files that don't have a location - set in stone under /boot/grub. Use ISO hard links rather than copies - to save some space. - -2013-04-24 Vladimir Serbinenko - - * grub-core/term/ieee1275/console.c (grub_console_dimensions): Ignore - bogus SLOF values. - -2013-04-24 Vladimir Serbinenko - - Make check work on mips-arc. - -2013-04-24 Vladimir Serbinenko - - * util/grub-mkrescue.in: Alias sashARCS as sash. - -2013-04-24 Vladimir Serbinenko - - * grub-core/term/arc/console.c: Assume that console is 80x24 vt100 if - it's serial. - -2013-04-24 Vladimir Serbinenko - - * util/grub-install.in: Fix target fo qemu_mips. - Fix extension on EFI. - -2013-04-24 Vladimir Serbinenko - - * grub-core/normal/menu_text.c (print_entry): Put an asterisk - in front of chosen entry to mark it even if highlighting is lost. - -2013-04-24 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_linux_boot): Default to - gfxpayload=keep if cbfb is active. - -2013-04-24 Vladimir Serbinenko - - * grub-core/disk/ata.c (grub_ata_real_open): Use grub_error properly. - -2013-04-24 Vladimir Serbinenko - - Add missing video ids to coreboot and ieee1275 video. - -2013-04-24 Vladimir Serbinenko - - * util/grub-mkrescue.in: Add mips-arc support. - -2013-04-24 Vladimir Serbinenko - - * grub-core/kern/dl.c (grub_dl_resolve_symbols): Handle malloc failure. - -2013-04-24 Vladimir Serbinenko - - Move mips-arc link address. Previous link address was chosen - in belief that RAM on SGI platforms grows down while in fact it - grows up from an unusual base. - -2013-04-21 Vladimir Serbinenko - - * grub-core/disk/arc/arcdisk.c (grub_arcdisk_iterate_iter): - Fix a type which prevented CD-ROM and floppy boot. - -2013-04-21 Vladimir Serbinenko - - Support coreboot framebuffer. - - * grub-core/video/i386/coreboot/cbfb.c: New file. - -2013-04-20 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_mm_init_region): Fix condition for - detecting too small regions. - -2013-04-20 Vladimir Serbinenko - - * grub-core/Makefile.core.def (legacycfg): Enable on EFI. - -2013-04-20 Vladimir Serbinenko - - * grub-core/lib/efi/relocator.c (grub_relocator_firmware_alloc_region): - Remove dprintf. - * grub-core/lib/relocator.c (malloc_in_range): Likewise. - -2013-04-19 Vladimir Serbinenko - - * grub-core/kern/ieee1275/init.c (grub_claim_heap): Improve handling - of GRUB_IEEE1275_FLAG_FORCE_CLAIM. - * grub-core/loader/powerpc/ieee1275/linux.c - (grub_linux_claimmap_iterate): Handle GRUB_IEEE1275_FLAG_FORCE_CLAIM. - -2013-04-19 Vladimir Serbinenko - - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): - Look for /boot-rom as well as /rom/boot-rom. - -2013-04-19 Vladimir Serbinenko - - * grub-core/commands/videotest.c (grub_cmd_videotest): Fix error - handling when creating text_layer failed. - * grub-core/video/video.c (grub_video_create_render_target): - Set result to 0 on error. - (grub_video_delete_render_target): Do not dereference NULL. - -2013-04-19 Vladimir Serbinenko - - * grub-core/kern/elfXX.c (grub_elfXX_load): Handle - GRUB_ELF_LOAD_FLAGS_30BITS and GRUB_ELF_LOAD_FLAGS_62BITS. - * grub-core/loader/powerpc/ieee1275/linux.c (grub_linux_load32), - (grub_linux_load64): Mask out 2 high bits. - -2013-04-19 Andrey Borzenkov - - * util/grub.d/30_os-prober.in: Add onstr to linux entries in one - more place. - -2013-04-19 Vladimir Serbinenko - - Add support for pseries and other bootinfo machines to grub-mkrescue. - - Tested by: Paulo Flabiano Smorigo. - -2013-04-17 Vladimir Serbinenko - - * util/grub-mkrescue.in: Add GPT for EFI boot. - -2013-04-17 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c: Detect floppies by ACPI ID. - It improves performance in qemu. - -2013-04-17 Vladimir Serbinenko - - * build-aux/snippet: Add missing gnulib files. - -2013-04-16 Andrey Borzenkov - - * grub-core/disk/efi/efidisk.c: Really limit transfer chunk size. - -2013-04-16 Andrey Borzenkov - - * autogen.sh: Use "-f" in addition for "-h" when checking file presence. - -2013-04-15 Vladimir Serbinenko -2013-04-15 Peter Jones - - * grub-core/disk/efi/efidisk.c: Limit disk read or write chunk to 0x500 - sectors. - Based on patch by Peter Jones. - -2013-04-15 Vladimir Serbinenko - - Fix DMRAID partition handling. - -2013-04-15 Vladimir Serbinenko - - * tests/grub_cmd_date.in: Skip on sparc64. - -2013-04-15 Vladimir Serbinenko - - * tests/grub_script_expansion.in: Use fixed-string grep to skip over - firmware error messages. - -2013-04-15 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_devalias_next): Make - source and destination differ. - -2013-04-15 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c: Fix CD-ROM and boot device - detection. - -2013-04-14 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/sys/types.h: Make WORDS_BIGENDIAN definition - match config-util.h to avoid warnings and increase compatibility. - -2013-04-14 Szymon Janc -2013-04-14 Vladimir Serbinenko - - Add option to compress files on install/image creation. - -2013-04-14 Vladimir Serbinenko - - * docs/grub-dev.texi: Rearrange menu to match the section order. - Reported by: Bryan Hundven. - -2013-04-14 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c: Remove useless leftover pointer. - -2013-04-14 Vladimir Serbinenko - - Move GRUB out of system area when using xorriso 1.2.9 or later. - -2013-04-14 Vladimir Serbinenko - - * tests/grub_cmd_date.in: Add missing exit 1. - -2013-04-14 Vladimir Serbinenko - - * tests/partmap_test.in: Skip on sparc64. - -2013-04-14 Vladimir Serbinenko - - Support grub-shell on sparc64. - -2013-04-14 Vladimir Serbinenko - - Support mkrescue on sparc64. - -2013-04-14 Vladimir Serbinenko - - Allow IEEE1275 ports on path even if it wasn't detected automatically. - Needed on OpenBIOS due to incomplete device tree. - -2013-04-14 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c: Iterate over bootpath even if it - would be otherwise excluded. - -2013-04-14 Vladimir Serbinenko - - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): - Inline name defines used only once. - -2013-04-13 Vladimir Serbinenko - - Fix memory leaks in ofnet. - Reported by: Francesco Lavra. - -2013-04-12 Vladimir Serbinenko - - * docs/man/grub-glue-efi.h2m: Add missing file. - -2013-04-12 Vladimir Serbinenko - - * util/grub-mkrescue.in: Fix wrong architecture for ppc dir. - -2013-04-12 Vladimir Serbinenko - - Better support Apple Intel Macs on CD. - -2013-04-12 Vladimir Serbinenko - - Replace stpcpy with grub_stpcpy in tools. - -2013-04-12 Vladimir Serbinenko - - Handle Japanese special keys. - Reported by: Hiroyuki YAMAMORI. - Codes supplied by: Hiroyuki YAMAMORI. - -2013-04-12 Vladimir Serbinenko - - * util/grub-mkimage.c: Document memdisk implying --prefix. - -2013-04-12 Vladimir Serbinenko - - * grub-core/bus/usb/ehci.c (grub_ehci_fini_hw): Ignore errors, not - much we can do about it anyway. - -2013-04-12 Aleš Nesrsta - - Fix handling of split transfers. - -2013-04-12 Vladimir Serbinenko - - * grub-core/net/http.c: Fix bad free. - -2013-04-12 Vladimir Serbinenko - - * grub-core/net/drivers/ieee1275/ofnet.c: Don't attempt to send more - than buffer size. - -2013-04-12 Vladimir Serbinenko - - Disable partmap check on i386-ieee1275 due to openfirmware issues. - -2013-04-12 Vladimir Serbinenko - - * tests/util/grub-shell.in: Fix it on powerpc. - -2013-04-12 Vladimir Serbinenko - - Turn off QEMU ACPI-way since new releases don't have shutdown port - anymore. - -2013-04-12 Vladimir Serbinenko - - * docs/grub.texi: Update coreboot status info. - -2013-04-12 Vladimir Serbinenko - - * tests/grub_cmd_date.in: New test for datetime. - -2013-04-12 Vladimir Serbinenko - - * tests/partmap_test.in: Fix missing qemudisk setting. - -2013-04-11 Vladimir Serbinenko - - Support i386-ieee1275 grub-mkrescue and make check on it. - -2013-04-11 Vladimir Serbinenko - - Merge powerpc grub-mkrescue flavour with common. Use xorriso HFS+ - feature for it. - -2013-04-11 Vladimir Serbinenko - - * docs/grub.texi: Fix description of GRUB_CMDLINE_XEN and - GRUB_CMDLINE_XEN_DEFAULT. - Reported by: Marc Warne (GigaTux) - -2013-04-11 Vladimir Serbinenko - - Import new gnulib. - -2013-04-11 Vladimir Serbinenko - - Use ACPI shutdown intests as traditional port was removed. - -2013-04-11 Andrey Borzenkov - - * util/grub.d/30_os-prober.in: Add onstr to entries for visual - distinction. - -2013-04-11 Vladimir Serbinenko - - Fix missing PVs if they don't contain "interesting" LV. Closes #38677. - Fix few warining messages and leaks while on it. - -2013-04-09 Andrey Borzenkov - - * autogen.sh: Use "-h", not "-f", to test for existence of symbolic - links under grub-core/lib/libgcrypt-grub/mpi. - -2013-04-08 Vladimir Serbinenko - - Fix ia64-efi image generation on big-endian machines. Deduplicate - some code while on it. - Reported by: Leif Lindholm. - -2013-04-08 Andrey Borzenkov - - * grub-core/Makefile.core.def: Add kern/elfXX.c to elf module - as extra_dist. - -2013-04-08 Andrey Borzenkov - - * grub-core/term/i386/pc/console.c: Fix cursor moving algorithm. - -2013-04-08 Bryan Hundven - - * docs/grub-dev.texi: Move @itemize after @subsection to satisfy - texinfo-5.1. - -2013-04-08 Vladimir Serbinenko - - * grub-core/normal/term.c: Few more fixes for menu entry editor - rendering. - Reported by: Andrey Borzenkov - -2013-04-07 Vladimir Serbinenko - - * grub-core/normal/term.c: Few more fixes for menu entry editor - rendering. - Reported by: Andrey Borzenkov - -2013-04-06 Andrey Borzenkov - - * conf/Makefile.extra-dist (EXTRA_DIST): Add - grub-core/lib/libgcrypt/src/gcrypt.h.in and util/import_gcrypth.sed. - -2013-04-06 Andrey Borzenkov - - * util/grub-install_header: Use @PACKAGE@.mo in message catalog name - instead of hardcoding grub.mo. - -2013-04-05 Fedora Ninjas - - * util/grub.d/30_os-prober.in: Support btrrfs linux-prober extensions. - -2013-04-05 Vladimir Serbinenko - - Use GRUB_PROPERLY_ALIGNED_ARRAY in grub-core/disk/cryptodisk.c and - grub-core/disk/geli.c. - -2013-04-05 Vladimir Serbinenko - - * util/grub-mkfont.c: Prefer enum to #define. - -2013-04-05 Vladimir Serbinenko - - * grub-core/commands/acpi.c: Use sizeof rather than hardcoding the size. - -2013-04-05 Vladimir Serbinenko - - Replace 8 with GRUB_CHAR_BIT in several places when appropriate. - -2013-04-05 Vladimir Serbinenko - - Add new defines GRUB_RSDP_SIGNATURE_SIZE and GRUB_RSDP_SIGNATURE. - -2013-04-05 Vladimir Serbinenko - - * grub-core/commands/verify.c: Use GRUB_CHAR_BIT. - -2013-04-05 Vladimir Serbinenko - - * include/grub/bsdlabel.h: Use enums. - -2013-04-05 Vladimir Serbinenko - - Move GRUB_CHAR_BIT to types.h. - -2013-04-04 Andrey Borzenkov - - * docs/grub.texi: Document more user commands. - -2013-04-04 Andrey Borzenkov - - * docs/grub.texi: Document menuentry --id option. - -2013-04-04 Francesco Lavra - - * util/grub-mkimage.c: Introduce new define EFI32_HEADER_SIZE. - -2013-04-04 Vladimir Serbinenko - - Unify file copying setup across different install scripts. Add - options for performing partial install. - -2013-04-04 Vladimir Serbinenko -2013-04-04 Peter Jones - - * grub-core/disk/efi/efidisk.c: Handle partitions on non-512B disks. - -2013-04-04 Vladimir Serbinenko - - Use TSC as a possible time source on i386-ieee1275. - -2013-04-04 Vladimir Serbinenko - - * grub-core/bus/usb/usbtrans.c (grub_usb_bulk_readwrite_packetize): - Init err. - -2013-04-04 Vladimir Serbinenko - - * util/grub-setup.c (setup): Handle some corner cases. - -2013-04-04 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/locale.h [GRUB_UTIL]: Include host locale.h. - -2013-04-03 Vladimir Serbinenko - - * grub-core/commands/verify.c: Save verified file to avoid it being - tampered with after verification was done. - -2013-04-03 Vladimir Serbinenko - - * grub-core/term/i386/pc/console.c (grub_console_getwh): Decrease - reported width by one to compensate for curesor algorithm problem. - -2013-04-03 Vladimir Serbinenko - - Fix screen corruption in menu entry editor and simplify the code - flow while on it. - -2013-04-03 Andrey Borzenkov - - * util/grub-mount.c (fuse_init): Return error if fuse_main - failed. - -2013-04-03 Francesco Lavra - - * include/grub/elf.h: Add missing ARM relocation codes and fix - existing ones. - -2013-04-03 Vladimir Testov - - * grub-core/gfxmenu/gui_progress_bar.c: Handle padding sizes. - -2013-04-03 Vladimir Testov -2013-04-03 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_circular_progress.c: Take both width and height - into account when calculating radius. - -2013-04-03 Vladimir Testov - - * grub-core/gfxmenu/view.c: Fix off-by-one error. - -2013-04-03 Vladimir Testov - - * grub-core/gfxmenu/gui_circular_progress.c: Fix off-by-one error. - -2013-04-01 Radosław Szymczyszyn - - * grub-core/partmap/apple.c (apple_partition_map_iterate): Add - missing closing bracket. - -2013-04-01 Radosław Szymczyszyn - - * INSTALL: Mention xorriso requirement. - -2013-03-31 Andrey Borzenkov - - * grub-core/commands/verify.c: Fix hash algorithms values for - the first three hashes - they start with 1, not with 0. - -2013-03-26 Vladimir Serbinenko - - * grub-core/kern/efi/mm.c (grub_efi_finish_boot_services): - Try terminating EFI services several times due to quirks in some - implementations. - -2013-03-26 Colin Watson - - * grub-core/commands/acpihalt.c (skip_ext_op): Add support for - skipping Event, Device, Processor, PowerRes, ThermalZone, and - BankField extended opcodes. - (get_sleep_type): Add minimal scope handling (just enough to - handle setting the scope to the root path). - (grub_acpi_halt): Parse any SSDTs as well as the DSDT. - * include/grub/acpi.h: Add enumeration values for Event, Device, - Processor, PowerRes, ThermalZone, and BankField extended opcodes. - -2013-03-26 Vladimir Testov - - * grub-core/gfxmenu/font.c (grub_font_get_string_width): Fix - memory leak. - -2013-03-25 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Give more time for AHCI request. - -2013-03-25 Vladimir Serbinenko - - * grub-core/normal/menu.c: Wait if there were errors shown at "boot" - command. - -2013-03-25 Vladimir Serbinenko - - Replace the region at 0 from coreboot tables to available in BSD - memory map. - -2013-03-24 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Automatically add no-real-mode edd=off on - non-BIOS platforms. - -2013-03-24 Vladimir Serbinenko - - * grub-core/Makefile.core.def (vga): Disable on coreboot and multiboot - platforms. - -2013-03-24 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Fix - handling of multi-device filesystems. - -2013-03-24 Vladimir Serbinenko - - * grub-core/Makefile.core.def (vbe): Disable on coreboot and multiboot - platforms. - -2013-03-24 Vladimir Serbinenko - - Add new 'proc' filesystem framework and put luks_script into it. - -2013-03-23 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c: Increase robustness on coreboot - and qemu. - -2013-03-22 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c: Fix incorrect handling of special volumes. - -2013-03-22 Vladimir Serbinenko - - Add ability to generate newc additions on runtime. - -2013-03-22 Vladimir Serbinenko - - * grub-core/commands/i386/coreboot/cbls.c: Fix typos and wrong - description. - -2013-03-21 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - -2013-03-20 Vladimir Serbinenko - - * grub-core/commands/verify.c (hashes): Add several hashes - from the spec. - -2013-03-20 Vladimir Serbinenko - - Slight improve in USB-related boot-time checkpoints. - -2013-03-20 Vladimir Serbinenko - - * grub-core/commands/boottime.c: Fix copyright header. - -2013-03-20 Vladimir Serbinenko - - New commands cbmemc, lscoreboot, coreboot_boottime to inspect - coreboot tables content. Support for cbmemc. - -2013-03-20 Vladimir Serbinenko - - Fix a conflict between ports structures with 2 controllers of - same kind. - -2013-03-20 Vladimir Serbinenko - - * include/grub/boottime.h: Add missing file. - -2013-03-19 Vladimir Serbinenko - - Initialize USB ports in parallel to speed-up boot. - -2013-03-19 Vladimir Serbinenko - - Fix USB devices not being detected when requested - due to delayed attach. - -2013-03-19 Vladimir Serbinenko - - Implement boot time analysis framework. - -2013-03-19 Vladimir Serbinenko - - Remove get_endpoint_descriptor and change all functions needing - descriptor to just receive it as argument rather than endpoint - address. - -2013-03-19 Aleš Nesrsta - - Better estimate the maximum USB transfer size. - -2013-03-17 Vladimir Serbinenko - - Resend a packet if we got the wrong buffer in status. - -2013-03-10 Vladimir Serbinenko - - * grub-core/loader/i386/bsdXX.c (grub_openbsd_find_ramdisk): Use - multiplication rather than division. - -2013-03-10 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_list_alloc): Use shifts rather - than divisions. - -2013-03-10 Vladimir Serbinenko - - * grub-core/commands/verify.c (grub_verify_signature): Use unsigned - operations to have intended shifts and not divisions. - -2013-03-10 Vladimir Serbinenko - - * grub-core/loader/i386/pc/plan9.c (fill_disk): Fix types to use - intended shifts rather than division. - -2013-03-10 Vladimir Serbinenko - - * include/grub/datetime.h (grub_datetime2unixtime): Fix unixtime - computation for some years before epoch. Avode confusing division - while on it. - -2013-03-10 Vladimir Serbinenko - - * grub-core/video/i386/pc/vbe.c - (grub_video_vbe_print_adapter_specific_info): Replace division by - shifts. - -2013-03-10 Vladimir Serbinenko - - Adjust types in gdb module to have intended unsigned shifts rather than - signed divisions. - -2013-03-10 Vladimir Serbinenko - - * grub-core/fs/hfs.c (grub_hfs_read_file): Avoid divmod64 since the - maximum size is 4G - 1 on hfs - -2013-03-10 Vladimir Serbinenko - - Avoid costly 64-bit division in grub_get_time_ms on most platforms. - -2013-03-10 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (grub_fshelp_log2blksize): Remove now unused - function. - -2013-03-07 Andrey Borzenkov - - * grub-core/fs/iso9660.c (add_part): Remove always_inline attribute - causing gcc error with gcc 4.7.1. - -2013-03-07 Nickolai Zeldovich - - * grub-core/commands/acpi.c (grub_acpi_create_ebda): Don't - dereference null pointer. While the code is technically correct, gcc - may eliminate a null check if pointer is already dereferenced. - -2013-03-07 Nickolai Zeldovich - - * grub-core/normal/crypto.c (read_crypto_list): Fix incorrect - OOM check. - * grub-core/normal/term.c (read_terminal_list): Likewise. - -2013-03-07 Vladimir Serbinenko - - Lift up core size limits on some platforms. Fix potential memory - corruption with big core on small memory systems. Document remaining - limits. - -2013-03-05 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_terminfo_cls): Issue an explicit - gotoxy to 0,0. - -2013-03-03 Vladimir Serbinenko - - Remove all trampoline support. Add -Wtrampolines when - present. Remove symbols used for trampolines to make - link fail if trampolines are present. - -2013-03-03 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_arglist_to_argv): Move - append out of its parent. - -2013-03-03 Vladimir Serbinenko - - * grub-core/commands/regexp.c (set_matches): Move setvar out of its - parent. - -2013-03-03 Vladimir Serbinenko - - * grub-core/kern/env.c, include/grub/env.h: Change iterator through - all vars to a macro. All users updated. - -2013-03-03 Vladimir Serbinenko - - * grub-core/disk/ieee1275/nand.c: Fix compilation on - i386-ieee1275. - -2013-03-02 Vladimir Serbinenko - - * include/grub/cmos.h: Handle high CMOS addresses on sparc64. - -2013-03-02 Vladimir Serbinenko - - * include/grub/mips/loongson/cmos.h: Fix high CMOS addresses. - -2013-03-02 Vladimir Serbinenko - - Move to more hookless approach in IEEE1275 devices handling. - -2013-03-02 Vladimir Serbinenko - - * grub-core/kern/term.c (grub_term_normal_color), - (grub_term_highlight_color): Add back lost defaults. - -2013-03-02 Vladimir Serbinenko - - Make elfload not use hooks. Opt for flags and iterators instead. - -2013-03-02 Vladimir Serbinenko - - * grub-core/lib/ia64/longjmp.S: Fix the name of longjmp function. - * grub-core/lib/ia64/setjmp.S: Fix the name of setjmp function. - -2013-03-02 Vladimir Serbinenko - - * grub-core/script/execute.c (gettext_append): Remove nested functions. - -2013-03-02 Vladimir Serbinenko - - * grub-core/normal/charset.c (grub_bidi_logical_to_visual): Add - hook pass-through parameter. All users updated and unnested. - -2013-03-02 Vladimir Serbinenko - - * grub-core/commands/loadenv.c (grub_cmd_list_env): Move print_var - out of its parent. - -2013-03-02 Vladimir Serbinenko - - * grub-core/fs/hfs.c: Remove nested functions. - -2013-03-01 Vladimir Serbinenko - - * grub-core/fs/hfsplus.c (grub_hfsplus_btree_iterate_node): Pass - the context through. - (grub_hfsplus_iterate_dir): Move nested function out of its parent. - -2013-03-01 Vladimir Serbinenko - - * util/grub-editenv.c (list_variables): Move print_var out of its - parent. - -2013-03-01 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (read_device_map): Remove nested - function. - -2013-03-01 Vladimir Serbinenko - - * grub-core/gentrigtables.c: Make tables const. - -2013-03-01 Vladimir Serbinenko - - Remove nested functions from videoinfo iterators. - -2013-03-01 Vladimir Serbinenko - - * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Fix compilation - for 64-bit platforms. - -2013-03-01 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c: Transform iterate_child_devices into - a FOR_CHILDREN macro. - -2013-03-01 Vladimir Serbinenko - - * grub-core/kern/main.c (grub_set_prefix_and_root): Strip trailing - platform from firmware path. - -2013-02-28 Vladimir Serbinenko - - Enable linux16 on non-BIOS systems for i.a. memtest. - - * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Handle hole at 0 - correctly. - * grub-core/Makefile.core.def (linux16): Enable on all x86 flavours. - -2013-02-28 Vladimir Serbinenko - - * grub-core/kern/i386/coreboot/mmap.c (grub_linuxbios_table_iterate): - Fix end of table condition. - -2013-02-28 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_show_help): Move showargs - out of its parent. - -2013-02-28 Vladimir Serbinenko - - * grub-core/fs/jfs.c: Remove nested functions. - -2013-02-28 Vladimir Serbinenko - - * grub-core/fs/minix.c: Remove nested functions. - -2013-02-28 Vladimir Serbinenko - - * grub-core/fs/iso9660.c: Remove nested functions. - -2013-02-28 Vladimir Serbinenko - - * grub-core/commands/parttool.c (grub_cmd_parttool): Move show_help out - of parent function. - -2013-02-28 Vladimir Serbinenko - - * util/grub-fstest.c: Remove nested functions. - -2013-02-27 Vladimir Serbinenko - - * grub-core/loader/machoXX.c: Remove nested functions. - -2013-02-27 Colin Watson - - Remove nested functions from disk and file read hooks. - - * include/grub/disk.h (grub_disk_read_hook_t): New type. - (struct grub_disk): Add read_hook_data member. - * include/grub/file.h (struct grub_file): Likewise. - * include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data - argument. - - Update all callers. - -2012-02-27 Andrey Borzenkov - - * grub-core/partmap/msdos.c (grub_partition_msdos_iterate): - Fix off by one error in enumerating extended partitions. - -2013-02-26 Andrey Borzenkov - - * grub-core/disk/efi/efidisk.c(grub_efidisk_get_device_name): Fix - memory leak if device name is not found. - -2013-02-25 Andrey Borzenkov - - * grub-core/normal/menu_entry.c (update_screen): remove - unused variable `off' which caused scroll down arrow to be always shown. - -2013-02-25 Andrey Borzenkov - - * grub-core/normal/menu_entry.c (insert_string): fix off by one - access to unallocated memory. - -2013-02-25 Andrey Borzenkov - - * Makefile.util.def: Add partmap/msdos.c to common library. - * include/grub/msdos_partition.h: Add GRUB_PC_PARTITION_TYPE_LDM - * grub-core/disk/ldm.c: Check for existence of - GRUB_PC_PARTITION_TYPE_LDM. - -2013-02-25 Vladimir Serbinenko - - * grub-core/normal/misc.c (grub_normal_print_device_info): Use KiB to display - sizes and display sector size. - -2013-02-24 Vladimir Serbinenko - - Implement new command cmosdump. - -2013-02-19 Paulo Flabiano Smorigo - - Support Openfirmware disks with non-512B sectors. - - * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Get the block - size of the disk. - * (grub_ofdisk_get_block_size): New function. - * (grub_ofdisk_prepare): Use the correct block size. - * (grub_ofdisk_read): Likewise. - * (grub_ofdisk_write): Likewise. - * include/grub/ieee1275/ofdisk.h (grub_ofdisk_get_block_size): - New proto. - -2013-02-06 Vladimir Serbinenko - - * grub-core/commands/lsacpi.c: Fix types on 64-bit platform. - -2013-02-04 Vladimir Serbinenko - - * grub-core/disk/cryptodisk.c (grub_cryptodisk_scan_device): Don't stop - on first error. - -2013-02-01 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (find_file): Set oldnode to zero after - freeing it. - -2013-02-01 Vladimir Serbinenko - - Implement USBDebug (full USB stack variant). - -2013-02-01 Vladimir Serbinenko - - * grub-core/commands/lsacpi.c: Show more info. Hide some boring parts - unless they have unexpected values. - -2013-02-01 Vladimir Serbinenko - - * grub-core/bus/usb/usb.c (grub_usb_device_attach): Add missing - grub_print_error. - -2013-02-01 Vladimir Serbinenko - - * grub-core/bus/usb/serial/common.c (grub_usbserial_attach): Fix missing - zero-out of port structure. - -2013-01-30 Vladimir Serbinenko - - * grub-core/fs/xfs.c (grub_xfs_read_block): Fix computation in presence - of extended attributes. - -2013-01-27 Andrey Borzenkov - - * util/grub-install.in: change misleading comment about - device.map creation - -2013-01-27 Vladimir Serbinenko - - * grub-core/normal/menu_text.c (grub_menu_init_page): Fix behaviour - when menu highlight color isn't set. - -2013-01-27 C. Masloch - - Improve FreeDOS direct loading support compatibility. - - * include/grub/i386/relocator.h (grub_relocator16_state): - New member ebp. - * grub-core/lib/i386/relocator.c (grub_relocator16_ebp): New extern - variable. - (grub_relocator16_boot): Handle %ebp. - * grub-core/lib/i386/relocator16.S: Likewise. - * grub-core/loader/i386/pc/freedos.c: - Load BPB to pass kernel which partition to load from. - Check that kernel file is not too large. - Set register dl to BIOS unit number as well. - -2013-01-22 Colin Watson - - * util/grub-reboot.in (usage): Document the need for - GRUB_DEFAULT=saved. - * util/grub-set-default.in (usage): Likewise. - Reported by: Brian Candler. Fixes Ubuntu bug #1102925. - -2013-01-21 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Include sys/types.h rather - than defining WORDS_BIGENDIAN manually. - -2013-01-21 Vladimir Serbinenko - - * include/grub/kernel.h (FOR_MODULES): Adjust to preserve alignment - invariants. - -2013-01-21 Colin Watson - - * grub-core/font/font.c (blit_comb: do_blit): Make static instead of - nested. - (blit_comb: add_device_width): Likewise. - -2013-01-21 Colin Watson - - Remove nested functions from USB iterators. - - * include/grub/usb.h (grub_usb_iterate_hook_t): New type. - (grub_usb_controller_iterate_hook_t): Likewise. - (grub_usb_iterate): Add hook_data argument. - (grub_usb_controller_iterate): Likewise. - (struct grub_usb_controller_dev.iterate): Likewise. - - Update all implementations and callers. - -2013-01-21 Vladimir Serbinenko - - * grub-core/normal/term.c (print_ucs4_terminal): Don't output right - margin when not needed. - -2013-01-21 Vladimir Serbinenko - - Make color variables global instead of it being per-terminal. - -2013-01-21 Vladimir Serbinenko - - * grub-core/commands/ls.c (grub_ls_print_devices): Add missing - asterisk. - -2013-01-21 Colin Watson - - Fix powerpc and sparc64 build failures caused by un-nesting memory - map iterators. - -2013-01-21 Colin Watson - - * grub-core/disk/arc/arcdisk.c (grub_arcdisk_iterate): Fix - parameter declarations. - -2013-01-21 Vladimir Serbinenko - - * grub-core/commands/lsmmap.c: Fix unused variable on emu. - -2013-01-21 Vladimir Serbinenko - - Improve spkmomdem reliability by adding a separator between bytes. - -2013-01-21 Colin Watson - - * grub-core/partmap/msdos.c (embed_signatures): Add the signature of - an Acer registration utility with several sightings in the wild. - Reported by: Rickard Westman. Fixes Ubuntu bug #987022. - -2013-01-21 Colin Watson - - Remove nested functions from filesystem directory iterators. - - * include/grub/fs.h (grub_fs_dir_hook_t): New type. - (struct grub_fs.dir): Add hook_data argument. - - Update all implementations and callers. - -2013-01-21 Colin Watson - - * docs/grub.texi (Multi-boot manual config): Fix typo for - "recommended". - -2013-01-20 Leif Lindholm - - * util/grub-mkimage.c (main): Postpone freeing arguments.output - until after its use in generate_image. - -2013-01-20 Colin Watson - - * grub-core/loader/i386/linux.c (grub_cmd_initrd): Don't add the - initrd size to addr_min, since the initrd will be allocated after - this address. - -2013-01-20 Andrey Borzenkov - - * conf/Makefile.common: Fix autogen rules to pass definition - files on stdin; Makefile.util.am needs Makefile.utilgcry.def - -2013-01-20 Leif Lindholm - - * include/grub/elf.h: Update ARM definitions based on binutils. - -2013-01-20 Aleš Nesrsta - - Split long USB transfers into short ones. - -2013-01-20 Andrey Borzenkov - - * docs/grub.texi (Simple configuration): Clarify GRUB_HIDDEN_TIMEOUT - is interrupted by ESC. - -2013-01-20 Vladimir Serbinenko - - * util/grub-script-check.c (main): Uniform the error message. - -2013-01-20 Colin Watson - - Remove nested functions from ELF iterators. - -2013-01-20 Colin Watson - - Remove nested functions from device iterators. - - * include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type. - (grub_arc_iterate_devs): Add hook_data argument. - * include/grub/ata.h (grub_ata_dev_iterate_hook_t): New type. - (struct grub_ata_dev.iterate): Add hook_data argument. - * include/grub/device.h (grub_device_iterate_hook_t): New type. - (grub_device_iterate): Add hook_data argument. - * include/grub/disk.h (grub_disk_dev_iterate_hook_t): New type. - (struct grub_disk_dev.iterate): Add hook_data argument. - (grub_disk_dev_iterate): Likewise. - * include/grub/gpt_partition.h (grub_gpt_partition_map_iterate): - Likewise. - * include/grub/msdos_partition.h (grub_partition_msdos_iterate): - Likewise. - * include/grub/partition.h (grub_partition_iterate_hook_t): New - type. - (struct grub_partition_map.iterate): Add hook_data argument. - (grub_partition_iterate): Likewise. - * include/grub/scsi.h (grub_scsi_dev_iterate_hook_t): New type. - (struct grub_scsi_dev.iterate): Add hook_data argument. - - Update all callers. - -2013-01-20 Colin Watson - - Fix typos for "developer" and "development". - -2013-01-18 Vladimir Serbinenko - - Add license header to spkmodem-recv.c. - -2013-01-17 Vladimir Serbinenko - - Rewrite spkmodem to use PIT for timing. Double the speed. - -2013-01-16 Vladimir Serbinenko - - Add new command pcidump. - -2013-01-16 Vladimir Serbinenko - - New terminal outputs using serial: morse and spkmodem. - -2013-01-16 Vladimir Serbinenko - - Improve bidi handling in entry editor. - -2013-01-16 Vladimir Serbinenko - - * grub-core/script/lexer.c (grub_script_lexer_init): Rename getline - argument to prevent name collision. - -2013-01-15 Colin Watson - - Remove nested functions from script reading and parsing. - - * grub-core/kern/parser.c (grub_parser_split_cmdline): Add - getline_data argument, passed to getline. - * grub-core/kern/rescue_parser.c (grub_rescue_parse_line): Add - getline_data argument, passed to grub_parser_split_cmdline. - * grub-core/script/lexer.c (grub_script_lexer_yywrap): Pass - lexerstate->getline_data to lexerstate->getline. - (grub_script_lexer_init): Add getline_data argument, saved in - lexerstate->getline_data. - * grub-core/script/main.c (grub_normal_parse_line): Add getline_data - argument, passed to grub_script_parse. - * grub-core/script/script.c (grub_script_parse): Add getline_data - argument, passed to grub_script_lexer_init. - * include/grub/parser.h (grub_parser_split_cmdline): Update - prototype. Update all callers to pass appropriate getline data. - (struct grub_parser.parse_line): Likewise. - (grub_rescue_parse_line): Likewise. - * include/grub/reader.h (grub_reader_getline_t): Add void * - argument. - * include/grub/script_sh.h (struct grub_lexer_param): Add - getline_data member. - (grub_script_parse): Update prototype. Update all callers to pass - appropriate getline data. - (grub_script_lexer_init): Likewise. - (grub_normal_parse_line): Likewise. - - * grub-core/commands/legacycfg.c (legacy_file_getline): Add unused - data argument. - * grub-core/kern/parser.c (grub_parser_execute: getline): Make - static instead of nested. Rename to ... - (grub_parser_execute_getline): ... this. - * grub-core/kern/rescue_reader.c (grub_rescue_read_line): Add unused - data argument. - * grub-core/normal/main.c (read_config_file: getline): Make static - instead of nested. Rename to ... - (read_config_file_getline): ... this. - (grub_normal_read_line): Add unused data argument. - * grub-core/script/execute.c (grub_script_execute_sourcecode: - getline): Make static instead of nested. Rename to ... - (grub_script_execute_sourcecode_getline): ... this. - * util/grub-script-check.c (main: get_config_line): Make static - instead of nested. - -2013-01-15 Colin Watson - - Remove nested functions from memory map iterators. - - * grub-core/efiemu/mm.c (grub_efiemu_mmap_iterate): Add hook_data - argument, passed to hook. - * grub-core/kern/i386/coreboot/mmap.c - (grub_linuxbios_table_iterate): Likewise. - (grub_machine_mmap_iterate: iterate_linuxbios_table): Make static - instead of nested. - (grub_machine_mmap_iterate): Add hook_data argument. - * grub-core/kern/i386/multiboot_mmap.c (grub_machine_mmap_iterate): - Add hook_data argument, passed to hook. - * grub-core/kern/i386/pc/mmap.c (grub_machine_mmap_iterate): - Likewise. - * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_iterate): - Likewise. - * grub-core/kern/ieee1275/mmap.c (grub_machine_mmap_iterate): - Likewise. - * grub-core/kern/mips/arc/init.c (grub_machine_mmap_iterate): - Likewise. - * grub-core/kern/mips/loongson/init.c (grub_machine_mmap_iterate): - Likewise. - * grub-core/kern/mips/qemu_mips/init.c (grub_machine_mmap_iterate): - Likewise. - * grub-core/mmap/efi/mmap.c (grub_efi_mmap_iterate): Likewise. - (grub_machine_mmap_iterate): Likewise. - * grub-core/mmap/mmap.c (grub_mmap_iterate): Likewise. - * include/grub/efiemu/efiemu.h (grub_efiemu_mmap_iterate): Update - prototype. - * include/grub/memory.h (grub_memory_hook_t): Add data argument. - Remove NESTED_FUNC_ATTR from here and from all users. - (grub_mmap_iterate): Update prototype. - (grub_efi_mmap_iterate): Update prototype. Update all callers to - pass appropriate hook data. - (grub_machine_mmap_iterate): Likewise. - - * grub-core/commands/acpi.c (grub_acpi_create_ebda: find_hook): Make - static instead of nested. - * grub-core/commands/lsmmap.c (grub_cmd_lsmmap: hook): Likewise. - Rename to ... - (lsmmap_hook): ... this. - * grub-core/efiemu/mm.c (grub_efiemu_mmap_init: bounds_hook): - Likewise. - (grub_efiemu_mmap_fill: fill_hook): Likewise. - * grub-core/kern/i386/coreboot/init.c (grub_machine_init: - heap_init): Likewise. - * grub-core/kern/i386/pc/init.c (grub_machine_init: hook): Likewise. - Rename to ... - (mmap_iterate_hook): ... this. - * grub-core/kern/ieee1275/init.c (grub_claim_heap: heap_init): - Likewise. - * grub-core/lib/ieee1275/relocator.c - (grub_relocator_firmware_get_max_events: count): Likewise. - (grub_relocator_firmware_fill_events: fill): Likewise. Rename - to ... - (grub_relocator_firmware_fill_events_iter): ... this. - * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_align: - hook): Likewise. Rename to ... - (grub_relocator_alloc_chunk_align_iter): ... this. - * grub-core/loader/i386/bsd.c (generate_e820_mmap: hook): Likewise. - Rename to ... - (generate_e820_mmap_iter): ... this. - * grub-core/loader/i386/linux.c (find_mmap_size: hook): Likewise. - Rename to ... - (count_hook): ... this. - (grub_linux_boot: hook): Likewise. Rename to ... - (grub_linux_boot_mmap_find): ... this. - (grub_linux_boot: hook_fill): Likewise. Rename to ... - (grub_linux_boot_mmap_fill): ... this. - * grub-core/loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap: - hook): Likewise. Rename to ... - (grub_fill_multiboot_mmap_iter): ... this. - * grub-core/loader/multiboot.c (grub_get_multiboot_mmap_count: - hook): Likewise. Rename to ... - (count_hook): ... this. - * grub-core/loader/multiboot_mbi2.c (grub_fill_multiboot_mmap: - hook): Likewise. Rename to ... - (grub_fill_multiboot_mmap_iter): ... this. - * grub-core/loader/powerpc/ieee1275/linux.c - (grub_linux_claimmap_iterate: alloc_mem): Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c (alloc_phys: choose): - Likewise. Rename to ... - (alloc_phys_choose): ... this. - (determine_phys_base: get_physbase): Likewise. - * grub-core/mmap/i386/mmap.c (grub_mmap_malign_and_register: - find_hook): Likewise. - * grub-core/mmap/i386/pc/mmap.c (preboot: fill_hook): Likewise. - (malloc_hook: count_hook): Likewise. - * grub-core/mmap/i386/uppermem.c (grub_mmap_get_lower: hook): - Likewise. Rename to ... - (lower_hook): ... this. - (grub_mmap_get_upper: hook): Likewise. Rename to ... - (upper_hook): ... this. - (grub_mmap_get_post64: hook): Likewise. Rename to ... - (post64_hook): ... this. - * grub-core/mmap/mips/uppermem.c (grub_mmap_get_lower: hook): - Likewise. Rename to ... - (lower_hook): ... this. - (grub_mmap_get_upper: hook): Likewise. Rename to ... - (upper_hook): ... this. - * grub-core/mmap/mmap.c (grub_mmap_iterate: count_hook): Likewise. - (grub_mmap_iterate: fill_hook): Likewise. - (fill_mask): Pass addr and mask within a single struct. - (grub_cmd_badram: hook): Make static instead of nested. Rename - to ... - (badram_iter): ... this. - (grub_cmd_cutmem: hook): Likewise. Rename to ... - (cutmem_iter): ... this. - -2013-01-13 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (read_device_map): Explicitly - delimit path in strings using quotes. - * util/getroot.c (grub_guess_root_devices): Likewise. - (grub_make_system_path_relative_to_its_root): Likewise. - * util/grub-probe.c (probe): Likewise. - * util/ieee1275/ofpath.c (find_obppath): Likewise. - (xrealpath): Likewise. - -2013-01-13 Vladimir Serbinenko - - Fix compilation with older compilers. - - * grub-core/Makefile.core.def (mpi): Add mpi-inline.c. - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Remove redundant - declarations. - * grub-core/lib/posix_wrap/string.h: Include sys/types.h. - * grub-core/lib/posix_wrap/sys/types.h: Add common types. - * grub-core/lib/xzembed/xz_dec_lzma2.c (dict_put): Replace byte - identifier with b. - * grub-core/lib/xzembed/xz_dec_stream.c (dec_vli): Likewise. - * include/grub/crypto.h: Add type defines. - * util/import_gcrypth.sed: Remove duplicate type defines. - -2013-01-13 Vladimir Serbinenko - - New command list_trusted. - - * grub-core/commands/verify.c (grub_cmd_list): New function. - -2013-01-13 Colin Watson - - * util/grub-mkimage.c (generate_image): Fix "size of public key" - info message. - -2013-01-13 Colin Watson - - Remove nested functions from PCI iterators. - - * grub-core/bus/pci.c (grub_pci_iterate): Add hook_data argument, - passed to hook. Update all callers to pass appropriate hook data. - * grub-core/bus/emu/pci.c (grub_pci_iterate): Likewise. - * include/grub/pci.h (grub_pci_iteratefunc_t): Add data argument. - Remove NESTED_FUNC_ATTR from here and from all users. - (grub_pci_iterate): Update prototype. - * grub-core/bus/cs5536.c (grub_cs5536_find: hook): Make static - instead of nested. Rename to ... - (grub_cs5536_find_iter): ... this. - * grub-core/kern/efi/mm.c (stop_broadcom: find_card): Likewise. - * grub-core/kern/mips/loongson/init.c (init_pci: set_card): - Likewise. - * grub-core/kern/vga_init.c (grub_qemu_init_cirrus: find_card): - Likewise. - * grub-core/video/bochs.c (grub_video_bochs_setup: find_card): - Likewise. - * grub-core/video/cirrus.c (grub_video_cirrus_setup: find_card): - Likewise. - * grub-core/video/efi_uga.c (find_framebuf: find_card): Likewise. - * grub-core/video/radeon_fuloong2e.c - (grub_video_radeon_fuloong2e_setup: find_card): Likewise. - * grub-core/video/sis315pro.c (grub_video_sis315pro_setup: - find_card): Likewise. - * grub-core/video/sm712.c (grub_video_sm712_setup: find_card): - Likewise. - -2013-01-12 Vladimir Serbinenko - - * grub-core/commands/verify.c: Mark messages for translating. - -2013-01-12 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/mem.c (gcry_x*alloc): Make out of memory - fatal. - -2013-01-12 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/mem.c (_gcry_log_bug): Make gcrypt bugs - fatal. - -2013-01-12 Vladimir Serbinenko - - * autogen.sh: Do not try to delete nonexistant files. - * util/import_gcrypth.sed: Add some missing header removals. - -2013-01-12 Colin Watson - - Clean up dangling references to grub-setup. - Fixes Ubuntu bug #1082045. - - * docs/grub.texi (Images): Refer generally to grub-install rather - than directly to grub-setup. - (Installing GRUB using grub-install): Remove direct reference to - grub-setup. - (Device map) Likewise. - (Invoking grub-install): Likewise. - * docs/man/grub-install.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise. - * util/grub-install.in (usage): Likewise. - - * util/bash-completion.d/grub-completion.bash.in (_grub_setup): - Apply to grub-bios-setup and grub-sparc64-setup rather than to - grub-setup. - * configure.ac: Remove grub_setup output variable. - - * docs/man/grub-bios-setup.h2m (NAME): Change name from grub-setup - to grub-bios-setup. - * docs/man/grub-sparc64-setup.h2m (NAME): Change name from - grub-setup to grub-sparc64-setup. - -2013-01-11 Vladimir Serbinenko - - Import gcrypt public-key cryptography and implement signature checking. - -2013-01-10 Vladimir Serbinenko - - * grub-core/fs/ntfs.c: Ue more appropriate types. - * grub-core/fs/ntfscomp.c: Likewise. - * include/grub/ntfs.h: Likewise. - -2013-01-10 Vladimir Serbinenko - - Support Apple FAT binaries on non-Apple platforms. - - * include/grub/macho.h (GRUB_MACHO_FAT_EFI_MAGIC): New define. - * include/grub/i386/macho.h (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT): - Likewise. - * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Parse - Apple FAT binaries. - -2013-01-10 Vladimir Serbinenko - - * grub-core/kern/disk.c (grub_disk_write): Fix sector number on 4K - sector devices. - -2013-01-07 Colin Watson - - * grub-core/io/bufio.c (grub_bufio_open): Use grub_zalloc instead of - explicitly zeroing elements. - * grub-core/io/gzio.c (grub_gzio_open): Likewise. - * grub-core/io/lzopio.c (grub_lzopio_open): Remove explicit zeroing - of elements in a structure already allocated using grub_zalloc. - * grub-core/io/xzio.c (grub_xzio_open): Likewise. - -2013-01-07 Colin Watson - - * docs/grub.texi (grub_cpu): New subsection. - (grub_platform): Likewise. - -2013-01-07 Vladimir Serbinenko - - * grub-core/fs/minix.c (grub_minix_read_file): Simplify arithmetics. - -2013-01-05 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext2_read_block): Use shifts rather than - divisions. - -2013-01-05 Vladimir Serbinenko - - * grub-core/fs/ntfs.c: Eliminate useless divisions in favor of shifts. - * grub-core/fs/ntfscomp.c: Likewise. - * include/grub/ntfs.h (grub_ntfs_data): Replace spc with log_spc. - (grub_ntfs_comp): Likewise. - -2013-01-05 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (-grub_nilfs2_palloc_groups_per_desc_block): - Rename to ... - (grub_nilfs2_palloc_log_groups_per_desc_block): ... this. Return log - of groups_per_block. All users updated. - -2013-01-05 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_write): Call - grub_error properly. - * grub-core/disk/ieee1275/nand.c (grub_nand_write): Likewise. - * grub-core/disk/loopback.c (grub_loopback_write): Likewise. - -2013-01-03 Vladimir Serbinenko - - * util/grub.d/10_kfreebsd.in: Correct the patch to zpool.cache as it's - always in /boot/zfs. - Reported by: Yuta Satoh. - -2013-01-03 Yuta Satoh - - * util/grub.d/10_kfreebsd.in: Fix improper references to grub-probe by - ${grub_probe} - -2013-01-03 Vladimir Serbinenko - - * configure.ac: Extend -Wno-trampolines to host. - -2013-01-03 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_susp_iterate): Avoid hang if - entry->len = 0. - -2013-01-03 Colin Watson - - * docs/grub.texi (Invoking grub-mkrelpath): New section. - (Invoking grub-script-check): Likewise. - -2013-01-03 Colin Watson - - * docs/grub.texi (Invoking grub-mount): New section. - Reported by: Filipus Klutiero. Fixes Debian bug #666427. - -2013-01-02 Colin Watson - - * grub-core/tests/lib/test.c (grub_test_run): Return non-zero on - test failures, so that a failing unit test correctly causes 'make - check' to fail. - -2013-01-02 Colin Watson - - Fix failing printf test. - - * grub-core/kern/misc.c (grub_vsnprintf_real): Parse '-', '.', and - '$' in the correct order when collecting type information. - -2013-01-02 Colin Watson - - * docs/grub.texi (configfile): Explain environment variable - handling. - (source): New section. - Reported by: Arbiel Perlacremaz. Fixes Savannah bug #35564. - -2012-12-31 Colin Watson - - Remove several trivially-unnecessary uses of nested functions. - - * grub-core/commands/i386/pc/sendkey.c - (grub_cmd_sendkey: find_key_code, find_ascii_code): Make static - instead of nested. - * grub-core/commands/legacycfg.c (legacy_file: getline): Likewise. - Rename to ... - (legacy_file_getline): ... this. - * grub-core/commands/loadenv.c (grub_cmd_load_env: set_var): - Likewise. - * grub-core/kern/corecmd.c (grub_core_cmd_set: print_env): Likewise. - * grub-core/kern/fs.c (grub_fs_probe: dummy_func): Likewise. Rename - to ... - (probe_dummy_iter): ... this. - * grub-core/kern/i386/coreboot/mmap.c - (grub_linuxbios_table_iterate: check_signature): Likewise. - * grub-core/kern/parser.c (grub_parser_split_cmdline: - check_varstate): Likewise. Mark inline. - * grub-core/lib/arg.c (find_short: fnd_short): Likewise. Pass - an additional parameter. - (find_long: fnd_long): Likewise. Pass two additional parameters. - * grub-core/lib/crc.c (init_crc32c_table: reflect): Likewise. - * grub-core/lib/crc64.c (init_crc64_table: reflect): Likewise. - * grub-core/lib/ieee1275/cmos.c (grub_cmos_find_port: hook): - Likewise. Rename to ... - (grub_cmos_find_port_iter): ... this. - * grub-core/lib/ieee1275/datetime.c (find_rtc: hook): Likewise. - Rename to ... - (find_rtc_iter): ... this. - - * grub-core/normal/menu_entry.c (run): Fold nested editor_getsource - function directly into the function body, since it is only called - once. - -2012-12-30 Colin Watson - - * grub-core/bus/usb/ehci.c (grub_ehci_pci_iter): Remove incorrect - __attribute__ ((unused)). - * grub-core/video/bochs.c (find_card): Likewise. - * grub-core/video/cirrus.c (find_card): Likewise. - * grub-core/video/radeon_fuloong2e.c (find_card): Likewise. - * grub-core/video/sis315pro.c (find_card): Likewise. - * grub-core/video/sm712.c (find_card): Likewise. - -2012-12-28 Colin Watson - - * util/grub-mkconfig.in: Accept GRUB_TERMINAL_OUTPUT=vga_text. - Fixes Savannah bug #37821. - -2012-12-28 Colin Watson - - Apply program name transformations at build-time rather than at - run-time. Fixes Debian bug #696465. - - * acinclude.m4 (grub_TRANSFORM): New macro. - * configure.ac: Create output variables with transformed names for - most programs. - * util/bash-completion.d/grub-completion.bash.in: Use - pre-transformed variables for program names. - * util/grub-install.in: Likewise. - * 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. - * tests/util/grub-shell-tester.in: Remove unused assignment. - * tests/util/grub-shell.in: Likewise. - * util/grub.d/00_header.in: Likewise. - -2012-12-28 Colin Watson - - Backport gnulib fixes for C11. Fixes Savannah bug #37738. - - * grub-core/gnulib/stdio.in.h (gets): Warn on use only if - HAVE_RAW_DECL_GETS. - * m4/stdio_h.m4 (gl_STDIO_H): Check for gets. - -2012-12-11 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Addmissing assignment to machine. - Reported by: Eriks Latosheks . - -2012-12-10 Vladimir Serbinenko - - * docs/grub.texi (Network): Update instructions on generating netboot - image. - -2012-12-10 Vladimir Serbinenko - - * grub-core/disk/cryptodisk.c (grub_cmd_cryptomount): Strip brackets - around device name if necessarry. - -2012-12-10 Paulo Flabiano Smorigo - - * util/grub-install.in: Follow the symbolic link parameter added - to the file command. - -2012-12-10 Andrey Borzenkov - - * util/grub-install.in: Remove stale TODO. - -2012-12-10 Paulo Flabiano Smorigo - - * grub-core/kern/ieee1275/init.c (grub_machine_get_bootlocation): Use - dynamic allocation for the bootpath buffer. - -2012-12-10 Dr. Tilmann Bubeck - - * grub-core/gfxmenu/view.c (init_terminal): Avoid making terminal - window too small. - -2012-12-10 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Get font as - argument rather than font name. All users updated. - (grub_gfxterm_set_window): Likewise. - -2012-12-10 Vladimir Testov - - * util/grub-mkfont.c (argp_parser): Fix a typo which prevented --asce - from working. - -2012-12-10 Vladimir Serbinenko - - * util/getroot.c (convert_system_partition_to_system_disk): Support - nbd disks. - -2012-12-10 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_dir): Stop if direntlen is 0 to avoid - infinite loop on corrupted FS. - -2012-12-08 Vladimir Serbinenko - - Fix big-endian mtime. - - * grub-core/fs/ufs.c (grub_ufs_inode): Split improperly attached - together sec and usec. - (grub_ufs_dir): Use correct byteswapping for UFS time. - -2012-12-08 Vladimir Serbinenko - - Support big-endian UFS1. - - * Makefile.util.def (libgrubmods): Add ufs_be.c - * grub-core/Makefile.core.def (ufs1_be): New module. - * grub-core/fs/ufs_be.c: New file. - * grub-core/fs/ufs.c: Declare grub_ufs_to_le* and use them throughout - the file. - -2012-11-28 Leif Lindholm - - * include/grub/types.h: Fix functionality unaffecting typo in - GRUB_TARGET_WORDSIZE conditional macro. - -2012-11-28 Paulo Flabiano Smorigo - - * grub-core/net/bootp.c (parse_dhcp_vendor): Fix double increment. - -2012-10-28 Grégoire Sutre - - * util/grub.d/10_netbsd.in: Fix tab indentation and make sure - that /netbsd appears first (when it exists). - -2012-10-12 Christoph Junghans - - * grub-core/Makefile.am (moddep.lst): Use $(AWK) rather than awk. - Fixes Savannah bug #37558. - -2012-10-12 Colin Watson - - * grub-core/commands/configfile.c (GRUB_MOD_INIT): Correct - description of extract_entries_configfile. - -2012-10-05 Colin Watson - - * grub-core/loader/i386/linux.c (allocate_pages): Fix spelling of - preferred_address. - (grub_cmd_linux): Likewise. - * grub-core/net/icmp6.c (struct prefix_option): Fix spelling of - preferred_lifetime. Update all users. - -2012-09-26 Colin Watson - - * Makefile.util.def (grub-mknetdir): Move to $prefix/bin. - Reported by: Daniel Kahn Gillmor. Fixes Debian bug #688799. - -2012-09-26 Colin Watson - - * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Redirect - errors from grub-probe to /dev/null, not stdout. - -2012-09-26 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_mount): Support AFFS bootblock in - sector 1. - -2012-09-24 Colin Watson - - * util/grub-install.in: Make the error message if $source_dir - doesn't exist more useful. - -2012-09-22 Colin Watson - - Fix grub-emu build on FreeBSD. - - * Makefile.util.def (grub-mount): Add LIBGEOM to ldadd. - * grub-core/net/drivers/emu/emunet.c: Only include Linux-specific - headers on Linux. - (GRUB_MOD_INIT): Return immediately on non-Linux platforms; this - implementation is currently Linux-specific. - * util/getroot.c (exec_pipe): Define only on Linux or when either - libzfs or libnvpair is unavailable. - (find_root_devices_from_poolname): Remove unused path variable. - -2012-09-19 Colin Watson - - * grub-core/partmap/msdos.c (pc_partition_map_embed): Revert - incorrect off-by-one fix from 2011-02-12. A 62-sector core image - should fit before end == 63. - -2012-09-19 Colin Watson - - * util/grub-setup.c (write_rootdev): Remove unused core_img - parameter. Update all callers. - (setup): Define core_sectors only if GRUB_SETUP_BIOS, to appease - 'gcc -Wunused-but-set-variable'. Remove unnecessary nested #ifdef - GRUB_SETUP_BIOS. - -2012-09-18 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (grub_tab): New variable. - (grub_add_tab): New function. - * util/grub.d/10_hurd.in: Replace \t with $grub_tab orgrub_add_tab. - * 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/10_xnu.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - -2012-09-18 Vladimir Serbinenko - - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN on mac. - * grub-core/term/ieee1275/console.c (grub_console_init_lately): Use - ieee1275-nocursor if GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN is set. - * grub-core/term/terminfo.c (grub_terminfo_set_current): Add new type - ieee1275-nocursor. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New value - GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN. - -2012-09-18 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_cmd_linux): Fix incorrect - le-conversion. - Reported by: BURETTE, Bernard. - -2012-09-17 Colin Watson - - * util/grub-mkconfig_lib.in (grub_quote): Remove outdated sentence - from comment. - -2012-09-14 Colin Watson - - * grub-core/term/terminfo.c: Only fix up powerpc key repeat on - IEEE1275 machines. Fixes powerpc-emu compilation. - * include/grub/terminfo.h: Likewise. - -2012-09-12 Vladimir Serbinenko - - * include/grub/efi/api.h (grub_efi_runtime_services): Make vendor_guid - a const pointer. - * grub-core/efiemu/runtime/efiemu.c (efiemu_memcpy): Make from a - const pointer. - (efiemu_set_variable): Make vendor_guid a const pointer. - -2012-09-12 Vladimir Serbinenko - - Don't require grub-mkconfig_lib to generate manpages for programs. - - * gentpl.py (manpage): Additional argument adddeps. Add adddeps to - dependencies, don't add grub-mkconfig_lib. - (program): Pass empty adddeps. - (script): Pass grub-mkconfig_lib as adddeps. - -2012-09-11 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (free_array) [GRUB_UTIL]: Fix memory leak. - * util/getroot.c (grub_find_device): Likewise. - (get_mdadm_uuid): Likewise. - (grub_util_is_imsm): Likewise. - (grub_util_pull_device): Likewise. - * util/grub-probe.c (probe): Likewise. - -2012-09-10 Benoit Gschwind - - * grub-core/loader/efi/appleloader.c (devpath_8): New var. - (devs): Add devpath_8. - -2012-09-08 Peter Jones - - * grub-core/Makefile.core.def (efifwsetup): New module. - * grub-core/commands/efi/efifwsetup.c: New file. - * grub-core/kern/efi/efi.c (grub_efi_set_variable): New function - * include/grub/efi/api.h (GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI): - New define. - * include/grub/efi/efi.h (grub_efi_set_variable): New proto. - -2012-09-05 Jiri Slaby - - * configure.ac: Add SuSe path. - -2012-09-05 Colin Watson - - * NEWS: Fix typo. - -2012-09-05 Colin Watson - - * util/import_gcry.py: Sort cipher_files, to make build system - generation more deterministic. - -2012-09-05 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (scan): Check function return value. - * grub-core/lib/ieee1275/datetime.c (grub_get_datetime): Likewise. - (grub_set_datetime): Likewise. - -2012-09-05 Vladimir Serbinenko - - * grub-core/script/yylex.l: Ignore unused-function and sign-compare - warnings. - -2012-09-05 Vladimir Serbinenko - - * grub-core/partmap/dvh.c (grub_dvh_is_valid): Add missing byteswap. - -2012-09-05 Vladimir Serbinenko - - * grub-core/fs/xfs.c (grub_xfs_read_block): Make keys a const pointer. - -2012-09-04 Colin Watson - - * Makefile.am (EXTRA_DIST): Add linguas.sh. It's only strictly - required for checkouts from bzr, but it may be useful for users or - distributors wishing to update translations against a tarball - distribution, and it can be helpful for the tarball to be a superset - of what's in bzr. - -2012-09-04 Colin Watson - - * Makefile.am (EXTRA_DIST): Add - grub-core/tests/boot/linux.init-mips.S, - grub-core/tests/boot/linux.init-ppc.S, and - grub-core/tests/boot/linux-ppc.cfg. - -2012-09-04 Colin Watson - - * grub-core/mmap/mips/loongson: Remove empty directory. - -2012-09-04 Colin Watson - - * docs/man/grub-mkdevicemap.h2m: Remove, since grub-mkdevicemap is - gone. - -2012-09-04 Colin Watson - - * .bzrignore: Add grub-bios-setup, grub-ofpathname, and - grub-sparc64-setup. - -2012-08-05 Grégoire Sutre - - * configure.ac: Strengthen the test for working -nostdinc -isystem. - -2012-07-31 Grégoire Sutre - - * po/POTFILES.in: Regenerated. - -2012-07-31 Grégoire Sutre - - * docs/grub.texi: Note that NetBSD/i386 is Multiboot-compliant. - (NetBSD): New subsection. - -2012-07-22 Ales Nesrsta - - * grub-core/bus/usb/ehci.c: PCI iter. - added PCI bus master setting. - * grub-core/bus/usb/ohci.c: PCI iter. - added PCI bus master setting. - -2012-07-22 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (grub_quote): Remove extra layer of escape. - * util/grub.d/10_hurd.in: Add missing quoting. - * util/grub.d/10_illumos.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - -2012-07-22 Vladimir Serbinenko - - New command `lsefi'. - - * grub-core/Makefile.core.def (lsefi): New module. - * grub-core/commands/efi/lsefi.c: New file. - * include/grub/efi/api.h: Add more GUIDs. - -2012-07-22 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c (grub_bsd_elf32_size_hook): Fix mask. - (grub_bsd_elf32_hook): Likewise. - (grub_bsd_elf64_size_hook): Likewise. - (grub_bsd_elf64_hook): Likewise. - (grub_bsd_load_elf): Likewise. - -2012-07-22 Vladimir Serbinenko - - * grub-core/lib/xzembed/xz_dec_stream.c (hash_validate): Fix behaviour - if hash function is unavailable. - (dec_stream_header): Likewise. - -2012-07-22 Vladimir Serbinenko - - * grub-core/normal/autofs.c (autoload_fs_module): Save and restore - filter state. - -2012-07-22 Vladimir Serbinenko - - Fix coreboot compilation. - - * grub-core/term/i386/pc/vga_text.c (grub_vga_text_init): Rename to ... - (grub_vga_text_init_real): ... this. - (grub_vga_text_fini): Rename to ... - (grub_vga_text_fini_real): ... this. - -2012-07-07 Vladimir Serbinenko - - * grub-core/Makefile.am: Fix path to boot/i386/pc/startup_raw.S. - -2012-07-02 Vladimir Serbinenko - - * grub-core/lib/legacy_parse.c: Support clear and testload. - -2012-07-02 Vladimir Serbinenko - - * grub-core/term/efi/serial.c: Support 1.5 stop bits. - -2012-07-02 Vladimir Serbinenko - - * grub-core/fs/ext2.c: Experimental support for 64-bit. - -2012-07-02 Vladimir Serbinenko - - * grub-core/net/tftp.c (ack): Fix endianness problem. - (tftp_receive): Likewise. - Reported by: Michael Davidsaver. - -2012-07-02 Vladimir Serbinenko - - * gentpl.py: Make mans depend on grub-mkconfig_lib. - -2012-07-02 Vladimir Serbinenko - - * include/grub/list.h (FOR_LIST_ELEMENTS_SAFE): New macro. - * include/grub/command.h (FOR_COMMANDS_SAFE): Likewise. - * grub-core/commands/help.c (grub_cmd_help): Use FOR_COMMANDS_SAFE. - -2012-07-02 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (find_efi_mmap_size): Don't decrease - efi_mmap_size. - Reported by: Stuart Hayes. - -2012-06-28 Vladimir Serbinenko - - Add monochrome text support (mda_text, aka `hercules' in grub-legacy). - - * grub-core/Makefile.core.def (mda_text): New module. - * grub-core/lib/legacy_parse.c (grub_legacy_parse): Support `hercules'. - * grub-core/term/i386/vga_common.c (grub_console_cur_color): Moved to .. - * grub-core/term/i386/pc/vga_text.c (cur_color): ... here - * grub-core/term/i386/pc/console.c (grub_console_cur_color): ... and - here. - * grub-core/term/i386/vga_common.c (grub_console_getwh): Moved to .. - * grub-core/term/i386/pc/vga_text.c (grub_console_getwh): ... here - * grub-core/term/i386/pc/console.c (grub_console_getwh): ... and - here. - * grub-core/term/i386/vga_common.c (grub_console_setcolorstate): Moved - to .. - * grub-core/term/i386/pc/vga_text.c (grub_console_setcolorstate): - ... here - * grub-core/term/i386/pc/console.c (grub_console_setcolorstate): ... and - here. - * grub-core/term/i386/vga_common.c: Removed. - * include/grub/i386/vga_common.h: Likewise. - * include/grub/vga.h (grub_vga_cr_bw_write): New function. - (grub_vga_cr_bw_read): Likewise. - * include/grub/vgaregs.h (GRUB_VGA_IO_CR_BW_INDEX): New enum value. - (GRUB_VGA_IO_CR_BW_DATA): Likewise. - * grub-core/term/i386/pc/vga_text.c [MODE_MDA]: Call - grub_vga_cr_bw_read/grub_vga_cr_bw_write instead of - grub_vga_cr_read/grub_vga_cr_write. - (grub_vga_text_setcolorstate) [MODE_MDA]: Ignore color. - 2012-06-27 Vladimir Serbinenko * configure.ac: Bump version to 2.00. diff --git a/INSTALL b/INSTALL index 79a0af7d9..e325fa2b2 100644 --- a/INSTALL +++ b/INSTALL @@ -11,44 +11,40 @@ 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 5.1.0 or later - Experimental support for clang 3.8.0 or later (results in much bigger binaries) - for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64 +* GCC 4.1.3 or later * GNU Make * GNU Bison 2.3 or later * GNU gettext 0.17 or later * GNU binutils 2.9.1.0.23 or later * Flex 2.5.35 or later -* pkg-config * 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) -For optional grub-emu features, you need: +To build grub-emu, you need: +* ncurses +* libusb (recommended) * SDL (recommended) -* libpciaccess (optional) -* libusb (optional) To build GRUB's graphical terminal (gfxterm), you need: -* FreeType 2.1.5 or later +* FreeType 2 or later * GNU Unifont If you use a development snapshot or want to hack on GRUB you may need the following. -* Python 2.6 or later -* Autoconf 2.63 or later -* Automake 1.11 or later +* Python 2.5.2 or later +* Autoconf 2.60 or later +* Automake 1.10.1 or later +* Autogen 5.10 or later Prerequisites for make-check: * qemu, specifically the binary 'qemu-system-i386' -* xorriso 1.2.9 or later, for grub-mkrescue and grub-shell Configuring the GRUB ==================== @@ -79,18 +75,9 @@ Building the GRUB The simplest way to compile this package is: - 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'. - - * autogen.sh (called by bootstrap) uses python. By default the - invocation is "python", but it can be overridden by setting the - variable $PYTHON. - - 4. Type `./configure' to configure the package for your system. + 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. 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. @@ -98,15 +85,15 @@ 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. - 6. Type `make' to compile the package. + 2. Type `make' to compile the package. - 7. Optionally, type `make check' to run any self-tests that come with + 3. Optionally, type `make check' to run any self-tests that come with the package. - 8. Type `make install' to install the programs and any data files and + 4. Type `make install' to install the programs and any data files and documentation. - 9. You can remove the program binaries and object files from the + 5. 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 @@ -115,103 +102,6 @@ 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 --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 - -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_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. - 2. BUILD_CFLAGS= for C options for build. - 3. BUILD_CPPFLAGS= for C preprocessor options for build. - 4. BUILD_LDFLAGS= for linker options for build. - 5. 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) - 3. libusb is looked for in standard linker directories (-lusb) (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/Makefile.am b/Makefile.am index bf9c1ba64..db9e930ff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,7 @@ AUTOMAKE_OPTIONS = subdir-objects -Wno-portability DEPDIR = .deps-util -SUBDIRS = grub-core/lib/gnulib . -if COND_real_platform -SUBDIRS += grub-core -endif -SUBDIRS += po docs util/bash-completion.d +SUBDIRS = grub-core/gnulib . grub-core po docs util/bash-completion.d include $(top_srcdir)/conf/Makefile.common include $(top_srcdir)/conf/Makefile.extra-dist @@ -37,7 +33,7 @@ grub_script.yy.c: grub_script.yy.h CLEANFILES += grub_script.yy.c grub_script.yy.h # For libgrub.a -libgrub.pp: config-util.h grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES) +libgrub.pp: 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 @@ -64,197 +60,176 @@ 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) 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 +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) 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) build-grub-mkfont$(BUILD_EXEEXT) - ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1) +unicode.pf2: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) 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) build-grub-mkfont$(BUILD_EXEEXT) - ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) +ascii.pf2: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) CLEANFILES += ascii.pf2 -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) +euro.pf2: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) CLEANFILES += euro.pf2 -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.bitmaps: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) +CLEANFILES += ascii.bitmaps -widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec$(BUILD_EXEEXT) - ./build-grub-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1) +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 < $< > $@ CLEANFILES += widthspec.h # Install config.h into platformdir -nodist_platform_HEADERS = config.h +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 $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S - $(TARGET_CC) -o $@ $< -static -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +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.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.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S + $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.mips: $(srcdir)/grub-core/tests/boot/linux.init-mips.S - $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.ppc: $(srcdir)/grub-core/tests/boot/linux.init-ppc.S - $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.mipsel: $(srcdir)/grub-core/tests/boot/linux.init-mips.S - $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.loongson: $(srcdir)/grub-core/tests/boot/linux.init-mips.S - $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1 + $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1 -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 +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 -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.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.aout: kfreebsd.elf - $(TARGET_OBJCOPY) -O a.out-i386-linux $< $@ -j .text + $(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id -R .note.gnu.gold-version -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.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.bin: pc-chainloader.elf - $(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 $< $@; + $(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 $(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.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.bin: ntldr.elf - $(TARGET_OBJCOPY) -O binary --strip-unneeded -j .text $< $@; + $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; -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 +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 -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.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.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 $@ +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 $@ -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)\" +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)\" -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)\" +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)\" -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)\" +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)\" -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)\" +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)\" linux-initramfs.mips: linux.init.mips Makefile - 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 + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --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 -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --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 -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --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 -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --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 -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --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 -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --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 @@ -269,7 +244,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 - $(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@ + $(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 @@ -278,7 +253,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 - $(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@ + $(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 @@ -286,107 +261,100 @@ 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 - ./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 + 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 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 - ./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 + 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 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 - ./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 + 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 bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell - ./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 + 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 bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell - ./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 + 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 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 - ./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 + 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 bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux-mips: linux-initramfs.mips $(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux-ppc: linux-initramfs.ppc $(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux-mipsel: linux-initramfs.mipsel $(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux-loongson: linux-initramfs.loongson $(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux16-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - ./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 + 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 bootcheck-multiboot: multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg grub-shell - ./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 + 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 bootcheck-multiboot2: multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg grub-shell - ./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 + 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 bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg grub-shell - ./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 + 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 bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg grub-shell - ./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 + 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 bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell - ./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 + 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 if COND_i386_efi -# 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 -# 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 -# *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 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_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 +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 +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 +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 +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 endif if COND_i386_pc #pc chainloader by definition is only for i386-pc #ntldr and bootmgr require BIOS. -#legacy protocol (linux16) makes early BIOS calls. -# 32-bit NetBSD crashes early on non-BIOS +#legacy protocol makes early BIOS calls. +# 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 @@ -409,10 +377,12 @@ 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 FORCE + bootcheck-linux-mips # Randomly generated SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d @@ -420,68 +390,3 @@ 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 - -EXTRA_DIST += ChangeLog ChangeLog-2015 - -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 d9e2bd84d..b80187c81 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -3,29 +3,15 @@ AutoGen definitions Makefile.tpl; library = { name = libgrubkern.a; cflags = '$(CFLAGS_GNULIB)'; - cppflags = '$(CPPFLAGS_GNULIB) -I$(srcdir)/grub-core/lib/json'; + cppflags = '$(CPPFLAGS_GNULIB)'; 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 = 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 = util/raid.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; @@ -36,9 +22,7 @@ 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/cryptodisk.c; common = grub-core/disk/AFSplitter.c; @@ -48,15 +32,12 @@ 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 = '-fno-builtin -Wno-undef'; - cppflags = '-I$(srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -I$(srcdir)/grub-core/lib/zstd -DMINILZO_HAVE_CONFIG_H'; + 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'; common_nodist = grub_script.tab.c; common_nodist = grub_script.yy.c; @@ -65,7 +46,6 @@ 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; @@ -77,23 +57,10 @@ 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; @@ -101,11 +68,9 @@ library = { 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; @@ -125,13 +90,11 @@ 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; @@ -141,41 +104,40 @@ library = { common = grub-core/lib/crc.c; common = grub-core/lib/adler32.c; common = grub-core/lib/crc64.c; - common = grub-core/lib/datetime.c; + common = grub-core/normal/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/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; - 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 = { + 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; }; program = { @@ -183,24 +145,15 @@ 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/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBLZMA)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; cppflags = '-DGRUB_PKGLIBDIR=\"$(pkglibdir)\"'; @@ -212,12 +165,11 @@ 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/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -227,12 +179,11 @@ 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/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -241,24 +192,11 @@ 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/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -268,21 +206,34 @@ 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/lib/gnulib/libgnu.a; + ldadd = grub-core/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_LINKER; + 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; }; program = { @@ -292,12 +243,14 @@ program = { common = util/grub-fstest.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; - common = grub-core/osdep/init.c; + + cflags = '$(CFLAGS_GCRY)'; + cppflags = '$(CPPFLAGS_GCRY)'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -308,13 +261,12 @@ 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; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) -lfuse'; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; condition = COND_GRUB_MOUNT; }; @@ -322,17 +274,16 @@ 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)'; - cppflags = '-DGRUB_MKFONT=1'; + cflags = '$(freetype_cflags)'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; - ldadd = '$(FREETYPE_LIBS)'; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(freetype_libs)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; condition = COND_GRUB_MKFONT; }; @@ -342,15 +293,13 @@ program = { installdir = sbin; mansection = 8; common = util/grub-probe.c; - common = util/probe.c; - common = grub-core/osdep/ofpath.c; + common = util/ieee1275/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/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -359,22 +308,16 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/setup_bios.c; - extra_dist = util/setup.c; + common = util/lvm.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/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_SETUP_FUNC=grub_util_bios_setup'; + cppflags = '-DGRUB_SETUP_BIOS=1'; }; program = { @@ -382,19 +325,17 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/setup_sparc.c; + common = util/lvm.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/lib/reed_solomon.c; - common = grub-core/osdep/ofpath.c; - common = grub-core/osdep/blocklist.c; - common = grub-core/osdep/init.c; + common = util/ieee1275/ofpath.c; ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = libgrubgcry.a; - ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_SETUP_FUNC=grub_util_sparc_setup'; + cppflags = '-DGRUB_SETUP_SPARC64=1'; }; program = { @@ -402,14 +343,13 @@ program = { installdir = sbin; mansection = 8; common = util/ieee1275/grub-ofpathname.c; - common = grub-core/osdep/ofpath.c; - common = grub-core/osdep/init.c; + common = util/ieee1275/ofpath.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)'; }; program = { @@ -418,30 +358,14 @@ 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/lib/gnulib/libgnu.a; + ldadd = grub-core/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; @@ -515,12 +439,6 @@ script = { 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; @@ -533,168 +451,47 @@ script = { installdir = grubconf; }; -program = { +script = { mansection = 1; name = grub-mkrescue; - - 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; + 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; }; -program = { +script = { mansection = 1; name = grub-mkstandalone; - 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)'; + common = util/grub-mkstandalone.in; }; -program = { +script = { mansection = 8; installdir = sbin; name = grub-install; - 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)'; + common = util/grub-install.in; + enable = noemu; }; -program = { - mansection = 1; - installdir = bin; +script = { + mansection = 8; + installdir = sbin; name = grub-mknetdir; - 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)'; + common = util/grub-mknetdir.in; }; script = { @@ -742,194 +539,18 @@ script = { installdir = noinst; }; -script = { - name = grub-fs-tester; - common = tests/util/grub-fs-tester.in; - installdir = noinst; - dependencies = 'garbage-gen$(BUILD_EXEEXT)'; -}; - -script = { - testcase; - name = ext234_test; - common = tests/ext234_test.in; -}; - -script = { - testcase; - name = squashfs_test; - common = tests/squashfs_test.in; -}; - -script = { - testcase; - name = iso9660_test; - common = tests/iso9660_test.in; -}; - -script = { - testcase; - name = hfsplus_test; - common = tests/hfsplus_test.in; -}; - -script = { - testcase; - name = ntfs_test; - common = tests/ntfs_test.in; -}; - -script = { - testcase; - name = reiserfs_test; - common = tests/reiserfs_test.in; -}; - -script = { - testcase; - name = fat_test; - common = tests/fat_test.in; -}; - -script = { - testcase; - name = minixfs_test; - common = tests/minixfs_test.in; -}; - -script = { - testcase; - name = xfs_test; - common = tests/xfs_test.in; -}; - -script = { - testcase; - name = f2fs_test; - common = tests/f2fs_test.in; -}; - -script = { - testcase; - name = nilfs2_test; - common = tests/nilfs2_test.in; -}; - -script = { - testcase; - name = romfs_test; - common = tests/romfs_test.in; -}; - -script = { - testcase; - name = exfat_test; - common = tests/exfat_test.in; -}; - -script = { - testcase; - name = tar_test; - common = tests/tar_test.in; -}; - -script = { - testcase; - name = udf_test; - common = tests/udf_test.in; -}; - -script = { - testcase; - name = hfs_test; - common = tests/hfs_test.in; -}; - -script = { - testcase; - name = jfs_test; - common = tests/jfs_test.in; -}; - -script = { - testcase; - name = btrfs_test; - common = tests/btrfs_test.in; -}; - -script = { - testcase; - name = zfs_test; - common = tests/zfs_test.in; -}; - -script = { - testcase; - name = cpio_test; - common = tests/cpio_test.in; -}; - script = { testcase; name = example_scripted_test; common = tests/example_scripted_test.in; }; -script = { - testcase; - name = gettext_strings_test; - common = tests/gettext_strings_test.in; - extra_dist = po/exclude.pot; -}; - -script = { - testcase; - name = pata_test; - common = tests/pata_test.in; -}; - -script = { - testcase; - name = ahci_test; - common = tests/ahci_test.in; -}; - -script = { - testcase; - name = uhci_test; - common = tests/uhci_test.in; -}; - -script = { - testcase; - name = ohci_test; - common = tests/ohci_test.in; -}; - -script = { - testcase; - name = ehci_test; - common = tests/ehci_test.in; -}; - script = { testcase; name = example_grub_script_test; common = tests/example_grub_script_test.in; }; -script = { - testcase; - name = grub_script_eval; - common = tests/grub_script_eval.in; -}; - -script = { - testcase; - name = grub_script_test; - common = tests/grub_script_test.in; -}; - script = { testcase; name = grub_script_echo1; @@ -1044,24 +665,6 @@ script = { common = tests/grub_cmd_regexp.in; }; -script = { - testcase; - name = grub_cmd_date; - common = tests/grub_cmd_date.in; -}; - -script = { - testcase; - name = grub_cmd_set_date; - common = tests/grub_cmd_set_date.in; -}; - -script = { - testcase; - name = grub_cmd_sleep; - common = tests/grub_cmd_sleep.in; -}; - script = { testcase; name = grub_script_expansion; @@ -1074,144 +677,30 @@ script = { common = tests/grub_script_not.in; }; -script = { - testcase; - name = grub_script_no_commands; - common = tests/grub_script_no_commands.in; -}; - script = { testcase; name = partmap_test; common = tests/partmap_test.in; }; -script = { - testcase; - name = hddboot_test; - common = tests/hddboot_test.in; -}; - -script = { - testcase; - name = fddboot_test; - common = tests/fddboot_test.in; -}; - -script = { - testcase; - name = cdboot_test; - common = tests/cdboot_test.in; -}; - -script = { - testcase; - name = netboot_test; - common = tests/netboot_test.in; -}; - -script = { - testcase; - name = pseries_test; - common = tests/pseries_test.in; -}; - -script = { - testcase; - name = core_compress_test; - common = tests/core_compress_test.in; -}; - -script = { - testcase; - name = xzcompress_test; - common = tests/xzcompress_test.in; -}; - -script = { - testcase; - name = gzcompress_test; - common = tests/gzcompress_test.in; -}; - -script = { - testcase; - name = lzocompress_test; - common = tests/lzocompress_test.in; -}; - script = { testcase; name = grub_cmd_echo; common = tests/grub_cmd_echo.in; }; -script = { - testcase; - name = help_test; - common = tests/help_test.in; -}; - script = { testcase; name = grub_script_gettext; common = tests/grub_script_gettext.in; }; -script = { - testcase; - name = grub_script_escape_comma; - common = tests/grub_script_escape_comma.in; -}; - script = { testcase; name = grub_script_strcmp; common = tests/grub_script_strcmp.in; }; -script = { - testcase; - name = test_sha512sum; - common = tests/test_sha512sum.in; -}; - -script = { - testcase; - name = test_unset; - common = tests/test_unset.in; -}; - -script = { - testcase; - name = grub_func_test; - common = tests/grub_func_test.in; -}; - -script = { - testcase; - name = grub_cmd_tr; - common = tests/grub_cmd_tr.in; -}; - -script = { - testcase; - name = file_filter_test; - common = tests/file_filter_test.in; -}; - -script = { - testcase; - name = grub_cmd_test; - common = tests/grub_cmd_test.in; -}; - -script = { - testcase; - name = syslinux_test; - common = tests/syslinux_test.in; -}; - program = { testcase; name = example_unit_test; @@ -1223,7 +712,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -1238,42 +727,10 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; -program = { - testcase; - 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; - 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; name = cmp_test; @@ -1285,7 +742,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -1295,92 +752,10 @@ 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/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 = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; diff --git a/NEWS b/NEWS index e7ca7fb3f..f9b06ab48 100644 --- a/NEWS +++ b/NEWS @@ -1,203 +1,6 @@ -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: -* Appearance: +* Appearence: * Official theme for gfxmenu (starfield) * Menu is organised with submenus. * Better default video mode selection using EDID. @@ -221,6 +24,7 @@ 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. @@ -244,7 +48,7 @@ New in 2.00: * multidevice, mirrored and raidz(2,3) ZFS support. * RAID LVM (internal RAIDing) support. * ZFS crypto support. - * ZLE, LZ4 and GZIP on ZFS support. + * ZLE 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 685b01657..b30a4b68b 100644 --- a/README +++ b/README @@ -12,6 +12,8 @@ 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/TODO b/TODO index a9b6d3523..6ec1521cd 100644 --- a/TODO +++ b/TODO @@ -7,3 +7,7 @@ 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 78cdf6e1d..0eb2e2a17 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -19,8 +19,6 @@ 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], @@ -76,7 +74,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 ${TARGET_OBJCOPY} works for absolute addresses]) +[AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses]) AC_CACHE_VAL(grub_cv_prog_objcopy_absolute, [cat > conftest.c <<\EOF void cmain (void); @@ -93,13 +91,13 @@ else fi grub_cv_prog_objcopy_absolute=yes for link_addr in 0x2000 0x8000 0x7C00; do - 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 : + if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -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([${TARGET_OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : + if AC_TRY_COMMAND([${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : else - AC_MSG_ERROR([${TARGET_OBJCOPY-objcopy} cannot create binary files]) + AC_MSG_ERROR([${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 @@ -136,78 +134,110 @@ if test "x$grub_cv_prog_ld_build_id_none" = xyes; then fi ]) -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 - 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 test "x$grub_cv_prog_nm_works" != xyes; then - AC_MSG_ERROR([nm does not work]) +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 +else + sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s +fi + +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 fi ]) -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_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]) +AC_MSG_RESULT([$grub_cv_apple_cc])]) -if test "x$grub_cv_prog_nm_minus_p" = xyes; then - TARGET_NMFLAGS_MINUS_P="-P" +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 else - TARGET_NMFLAGS_MINUS_P= + grub_cv_apple_target_cc=no fi ]) -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_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]) +AC_MSG_RESULT([$grub_cv_apple_target_cc])]) -if test "x$grub_cv_prog_nm_defined_only" = xyes; then - TARGET_NMFLAGS_DEFINED_ONLY=--defined-only + +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 else - TARGET_NMFLAGS_DEFINED_ONLY= + grub_cv_i386_asm_prefix_requirement=no fi -]) + +rm -f conftest*]) + +if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then + grub_tmp_addr32="addr32" + grub_tmp_data32="data32" +else + grub_tmp_addr32="addr32;" + grub_tmp_data32="data32;" +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. @@ -216,12 +246,7 @@ 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([[ -asm (".globl start; start:"); -void __main (void); -void __main (void) {} -int main (void); -]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[asm ("incl __bss_start")]])], [grub_cv_check_uscore_uscore_bss_start_symbol=yes], [grub_cv_check_uscore_uscore_bss_start_symbol=no])]) @@ -230,11 +255,7 @@ 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([[ -asm (".globl start; start:"); -void __main (void); -void __main (void) {} -int main (void);]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[asm ("incl edata")]])], [grub_cv_check_edata_symbol=yes], [grub_cv_check_edata_symbol=no])]) @@ -243,11 +264,7 @@ 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([[ -asm (".globl start; start:"); -void __main (void); -void __main (void) {} -int main (void);]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[asm ("incl _edata")]])], [grub_cv_check_uscore_edata_symbol=yes], [grub_cv_check_uscore_edata_symbol=no])]) @@ -271,11 +288,7 @@ 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([[ -asm (".globl start; start:"); -void __main (void); -void __main (void) {} -int main (void);]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[asm ("incl end")]])], [grub_cv_check_end_symbol=yes], [grub_cv_check_end_symbol=no])]) @@ -284,11 +297,7 @@ 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([[ -asm (".globl start; start:"); -void __main (void); -void __main (void) {} -int main (void);]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[asm ("incl _end")]])], [grub_cv_check_uscore_end_symbol=yes], [grub_cv_check_uscore_end_symbol=no])]) @@ -304,6 +313,32 @@ 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'. AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[ @@ -334,7 +369,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 -Werror -o conftest.s" 2> /dev/null; then] +[if eval "$ac_compile -S -mstack-arg-probe -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 @@ -344,15 +379,15 @@ else [fi] ]) -dnl Check if ln -s can handle directories properly (mingw). +dnl Check if ln can handle directories properly (mingw). AC_DEFUN([grub_CHECK_LINK_DIR],[ -AC_MSG_CHECKING([whether ln -s can handle directories properly]) +AC_MSG_CHECKING([whether ln 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 && rm -f testdir/util 2>/dev/null ; then] +if ln -s $reldir testdir/util 2>/dev/null ; then] AC_MSG_RESULT([yes]) [link_dir=yes else @@ -390,58 +425,6 @@ 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,-d -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. @@ -469,9 +452,3 @@ 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 deleted file mode 100644 index 97c2546bf..000000000 --- a/asm-tests/arm.S +++ /dev/null @@ -1,20 +0,0 @@ -/* 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 deleted file mode 100644 index d037744f9..000000000 --- a/asm-tests/i386-pc.S +++ /dev/null @@ -1,18 +0,0 @@ -/* 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 deleted file mode 100644 index 30adc4fe2..000000000 --- a/asm-tests/i386.S +++ /dev/null @@ -1,4 +0,0 @@ -/* on x86 old clang doesn't support .code16 */ - - .code16 - movb %al, %bl diff --git a/asm-tests/mips.S b/asm-tests/mips.S deleted file mode 100644 index 1312d47d5..000000000 --- a/asm-tests/mips.S +++ /dev/null @@ -1,11 +0,0 @@ -/* 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 deleted file mode 100644 index 396a6cce9..000000000 --- a/asm-tests/powerpc.S +++ /dev/null @@ -1,8 +0,0 @@ -/* 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 deleted file mode 100644 index 03c5fe02a..000000000 --- a/asm-tests/sparc64.S +++ /dev/null @@ -1,9 +0,0 @@ - .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 31b0ced7e..db719cd1d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,43 +2,22 @@ set -e -if [ ! -e grub-core/lib/gnulib/stdlib.in.h ]; then - echo "Gnulib not yet bootstrapped; run ./bootstrap instead." >&2 - exit 1 -fi - -# Set ${PYTHON} to plain 'python' if not set already -: ${PYTHON:=python} - +export LC_CTYPE=C export LC_COLLATE=C unset LC_ALL -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 +autogen --version >/dev/null || exit 1 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 -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 +python util/import_gcry.py grub-core/lib/libgcrypt/ grub-core -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 "Creating Makefile.tpl..." +python gentpl.py | sed -e '/^$/{N;/^\n$/D;}' > Makefile.tpl -echo "Generating Automake input..." +echo "Running autogen..." # Automake doesn't like including files from a path outside the project. rm -f contrib grub-core/contrib @@ -62,8 +41,8 @@ for extra in contrib/*/Makefile.core.def; do fi done -${PYTHON} gentpl.py $UTIL_DEFS > Makefile.util.am -${PYTHON} gentpl.py $CORE_DEFS > grub-core/Makefile.core.am +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 for extra in contrib/*/Makefile.common; do if test -e "$extra"; then @@ -87,17 +66,6 @@ done echo "Saving timestamps..." echo timestamp > stamp-h.in -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 - +echo "Running autoreconf..." +autoreconf -vi exit 0 diff --git a/bootstrap b/bootstrap deleted file mode 100755 index 5b08e7e2d..000000000 --- a/bootstrap +++ /dev/null @@ -1,1073 +0,0 @@ -#! /bin/sh -# Print a version string. -scriptversion=2019-01-04.17; # UTC - -# Bootstrap this package from checked-out sources. - -# Copyright (C) 2003-2019 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=git://git.sv.gnu.org/gnulib - -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 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 -q -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=$(sed -n "$extract_package_name" configure.ac) \ - || die 'cannot find package name in configure.ac' -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" -} - -# 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;; - --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;; - *) - 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 - -# 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" -} - -# 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' - fi - git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ - || cleanup_gnulib - - 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 - -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 - } -} - -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 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 deleted file mode 100644 index 6d383240e..000000000 --- a/bootstrap.conf +++ /dev/null @@ -1,100 +0,0 @@ -# Bootstrap configuration. - -# Copyright (C) 2006-2019 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=d271f868a8df9bbec29049d01e056481b7a1a263 - -# gnulib modules used by this package. -# mbswidth is used by gnulib-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 -" - -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.63 -automake 1.11 -gettext 0.18.3 -git 1.5.5 -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 - for patchname in fix-base64 fix-null-deref fix-width no-abort; do - patch -d grub-core/lib/gnulib -p2 \ - < "grub-core/lib/gnulib-patches/$patchname.patch" - done - 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 new file mode 100644 index 000000000..7e3e2db82 --- /dev/null +++ b/build-aux/arg-nonnull.h @@ -0,0 +1,26 @@ +/* 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 new file mode 100644 index 000000000..0c2fad7a2 --- /dev/null +++ b/build-aux/c++defs.h @@ -0,0 +1,271 @@ +/* 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 new file mode 100755 index 000000000..c492a93b6 --- /dev/null +++ b/build-aux/config.rpath @@ -0,0 +1,614 @@ +#! /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 6cd71cbb2..b5615a14b 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -3,22 +3,39 @@ 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 - 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 + CFLAGS_PLATFORM += -mno-app-regs + LDFLAGS_PLATFORM = -Wl,-melf64_sparc -mno-relax endif # Other options @@ -30,23 +47,43 @@ CPPFLAGS_DEFAULT += -I$(top_builddir) CPPFLAGS_DEFAULT += -I$(top_srcdir) CPPFLAGS_DEFAULT += -I$(top_srcdir)/include CPPFLAGS_DEFAULT += -I$(top_builddir)/include -CPPFLAGS_DEFAULT += -I$(top_srcdir)/grub-core/lib/libgcrypt-grub/src/ -CCASFLAGS_DEFAULT = $(CPPFLAGS_DEFAULT) -DASM_FILE=1 -BUILD_CPPFLAGS += $(CPPFLAGS_DEFAULT) +CCASFLAGS_DEFAULT = -DASM_FILE=1 -CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding -LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 +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) CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) -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_CYGWIN +STRIPFLAGS_KERNEL = -F elf32-i386 -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version +else +STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .note.gnu.gold-version +endif -CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding -LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d +CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding +LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) -CFLAGS_IMAGE = $(CFLAGS_PLATFORM) -fno-builtin -LDFLAGS_IMAGE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S +CFLAGS_IMAGE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -fno-builtin +LDFLAGS_IMAGE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S CPPFLAGS_IMAGE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) CCASFLAGS_IMAGE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) @@ -65,15 +102,15 @@ grubconfdir = $(sysconfdir)/grub.d platformdir = $(pkglibdir)/$(target_cpu)-$(platform) starfielddir = $(pkgdatadir)/themes/starfield -CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib +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_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 @@ -86,11 +123,9 @@ CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_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_FDT_LIST) + $(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) # Define these variables to calm down automake @@ -109,7 +144,7 @@ bin_PROGRAMS = platform_DATA = sbin_PROGRAMS = check_SCRIPTS = -dist_grubconf_DATA = +grubconf_DATA = check_PROGRAMS = noinst_SCRIPTS = noinst_PROGRAMS = @@ -124,15 +159,20 @@ EXTRA_DIST = CLEANFILES = BUILT_SOURCES = -# Rules for Automake input +# 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 $@ .PRECIOUS: $(top_srcdir)/Makefile.util.am -$(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) +$(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) mv $@.new $@ .PRECIOUS: $(top_srcdir)/grub-core/Makefile.core.am -$(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) +$(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) mv $@.new $@ diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist index 37dc3aa10..c862206bc 100644 --- a/conf/Makefile.extra-dist +++ b/conf/Makefile.extra-dist @@ -2,21 +2,19 @@ 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-cygwin-img-ld.sc +EXTRA_DIST += conf/i386-pc-cygwin-img-ld.sc EXTRA_DIST += grub-core/Makefile.core.def EXTRA_DIST += grub-core/Makefile.gcry.def @@ -28,34 +26,16 @@ EXTRA_DIST += grub-core/gensymlist.sh EXTRA_DIST += grub-core/genemuinit.sh EXTRA_DIST += grub-core/genemuinitheader.sh -EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch -EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch -EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch -EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch - -EXTRA_DIST += grub-core/lib/libgcrypt -EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic +EXTRA_DIST += grub-core/lib/libgcrypt/cipher 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 @@ -71,85 +51,3 @@ 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-cygwin-img-ld.sc b/conf/i386-pc-cygwin-img-ld.sc similarity index 91% rename from conf/i386-cygwin-img-ld.sc rename to conf/i386-pc-cygwin-img-ld.sc index 3ac26fcce..90866c379 100644 --- a/conf/i386-cygwin-img-ld.sc +++ b/conf/i386-pc-cygwin-img-ld.sc @@ -5,8 +5,6 @@ SECTIONS .text : { start = . ; - _start = . ; - __start = . ; *(.text) etext = . ; } @@ -35,8 +33,6 @@ SECTIONS { *(.edata) end = . ; - _end = . ; - __end = . ; } .stab : { diff --git a/config.h.in b/config.h.in index 9e8f9911b..a7eaf1925 100644 --- a/config.h.in +++ b/config.h.in @@ -5,41 +5,16 @@ #if defined(__PPC__) && !defined(__powerpc__) #define __powerpc__ 1 #endif - -#define GCRYPT_NO_DEPRECATED 1 -#define HAVE_MEMMOVE 1 - -/* Define to 1 to enable disk cache statistics. */ -#define DISK_CACHE_STATS @DISK_CACHE_STATS@ -#define BOOT_TIME_STATS @BOOT_TIME_STATS@ - -/* 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 - -#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 -#define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ -#endif -#elif defined (GRUB_UTIL) || !defined (GRUB_MACHINE) +#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) #include +#define NESTED_FUNC_ATTR #else -#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 \"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. */ @@ -56,12 +31,26 @@ #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 to 1 to enable disk cache statistics. */ +#define DISK_CACHE_STATS @DISK_CACHE_STATS@ #define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" #define GRUB_PLATFORM "@GRUB_PLATFORM@" #define RE_ENABLE_I18N 1 -#define _GNU_SOURCE 1 +#if defined(__i386__) +#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) +#else +#define NESTED_FUNC_ATTR +#endif #endif diff --git a/configure.ac b/configure.ac index 7c10a4db7..91b36d0a4 100644 --- a/configure.ac +++ b/configure.ac @@ -26,98 +26,58 @@ 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 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. +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. -AC_INIT([GRUB],[2.05],[bug-grub@gnu.org]) +AC_INIT([GRUB],[2.00],[bug-grub@gnu.org]) AC_CONFIG_AUX_DIR([build-aux]) # We don't want -g -O2 by default in CFLAGS : ${CFLAGS=""} -# Checks for build, host and target systems. -AC_CANONICAL_BUILD +# Checks for host and target systems. AC_CANONICAL_HOST -save_program_prefix="${program_prefix}" AC_CANONICAL_TARGET -program_prefix="${save_program_prefix}" -AM_INIT_AUTOMAKE([1.11]) -AC_PREREQ(2.63) +AM_INIT_AUTOMAKE() +AC_PREREQ(2.60) AC_CONFIG_SRCDIR([include/grub/dl.h]) AC_CONFIG_HEADER([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-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]) # Optimization flag. Allow user to override. if test "x$TARGET_CFLAGS" = x; then - TARGET_CFLAGS=-Os + TARGET_CFLAGS="$TARGET_CFLAGS -Os" fi -# Enable support for "restrict" keyword and other -# features from gnu99 C language standard. -BUILD_CFLAGS="-std=gnu99 $BUILD_CFLAGS" -HOST_CFLAGS="-std=gnu99 $HOST_CFLAGS" -TARGET_CFLAGS="-std=gnu99 $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" - ;; - arm*) - target_cpu=arm - ;; - aarch64*) - target_cpu=arm64 - ;; - riscv32*) - target_cpu=riscv32 - ;; - riscv64*) - target_cpu=riscv64 + target_cpu=mips; + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS=1"; ;; esac @@ -135,19 +95,11 @@ 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 ;; - arm-*) platform=uboot ;; - arm64-*) platform=efi ;; - riscv32-*) platform=efi ;; - riscv64-*) platform=efi ;; - *) - AC_MSG_WARN([unsupported CPU: "$target_cpu" - only building utilities]) - platform=none - ;; + *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else platform="$with_platform" @@ -156,20 +108,14 @@ 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) ;; @@ -182,36 +128,22 @@ 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) ;; - riscv32-efi) ;; - riscv64-efi) ;; *-emu) ;; - *-none) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; 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 "$target_cpu" in + i386 | powerpc) target_m32=1 ;; + x86_64 | sparc64) target_m64=1 ;; +esac -if test x"$target_cpu-$platform" = xsparc64-emu ; then - target_m64=1 -fi - -case "$target_os" in - windows* | mingw32*) target_os=cygwin ;; +case "$host_os" in + mingw32*) host_os=cygwin ;; esac # This normalizes the names, and creates a new variable ("host_kernel") @@ -224,54 +156,31 @@ case "$host_os" in netbsd*) host_kernel=netbsd ;; solaris*) host_kernel=illumos ;; darwin*) host_kernel=xnu ;; - 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;; + cygwin) host_kernel=windows ;; 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" ;; - qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=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" ;; +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,`" + 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" 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) @@ -302,7 +211,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], @@ -330,6 +239,23 @@ 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 @@ -342,7 +268,7 @@ AC_PROG_LN_S if test "x$LEX" = "x:"; then AC_MSG_ERROR([flex is not found]) else - version=`$LEX --version | $AWK '{ split($2,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'` + version=`$LEX --version | $AWK '{ split($NF,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'` if test -n "$version" -a "$version" -ge 20535; then : else @@ -359,54 +285,26 @@ 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_CHECK_PROG(HAVE_CXX, $CXX, yes, no) - AC_GNU_SOURCE AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_VERSION([0.18.3]) AC_SYS_LARGEFILE # 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) -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 +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 if test x$USE_NLS = xno; then HOST_CFLAGS="$HOST_CFLAGS -fno-builtin-gettext" @@ -419,16 +317,8 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign getextmntent) -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. -SAVED_CFLAGS="$CFLAGS" -CFLAGS="$HOST_CFLAGS -Werror" -AC_HEADER_MAJOR -CFLAGS="$SAVED_CFLAGS" +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_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default #include @@ -452,75 +342,16 @@ 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]) -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) +AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc], + [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.])]) # 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. # @@ -532,32 +363,22 @@ 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(TARGET_OBJCOPY, objcopy) - AC_CHECK_TOOL(TARGET_STRIP, strip) - AC_CHECK_TOOL(TARGET_NM, nm) - AC_CHECK_TOOL(TARGET_RANLIB, ranlib) + AC_CHECK_TOOL(OBJCOPY, objcopy) + AC_CHECK_TOOL(STRIP, strip) + AC_CHECK_TOOL(NM, nm) ac_tool_prefix="$tmp_ac_tool_prefix" else if test "x$TARGET_CC" = x; then TARGET_CC=$CC fi - 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_CHECK_TOOL(OBJCOPY, objcopy) + AC_CHECK_TOOL(STRIP, strip) + AC_CHECK_TOOL(NM, nm) 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" @@ -571,6 +392,152 @@ 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" @@ -589,625 +556,24 @@ if test "x$target_m64" = x1; then TARGET_MODULE_FORMAT="elf64" fi -# 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 -fi - - -# 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="$TARGET_CFLAGS -falign-loops=1 -Werror" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_falign_loop=yes], - [grub_cv_cc_falign_loop=no]) - ]) - - AC_CACHE_CHECK([whether -malign-loops works], [grub_cv_cc_malign_loop], [ - CFLAGS="$TARGET_CFLAGS -malign-loops=1 -Werror" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_malign_loop=yes], - [grub_cv_cc_malign_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" - elif test "x$grub_cv_cc_malign_loop" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=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 - -# 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"], []) - 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"], []) - 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 - -# 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)'"/${grub_coredir}/conf/i386-cygwin-img-ld.sc" - TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT}" - TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/${grub_coredir}/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 +if test "$target_cpu"-"$platform" = x86_64-efi; then # Use large model to support 4G memory AC_CACHE_CHECK([whether option -mcmodel=large works], grub_cv_cc_mcmodel, [ - CFLAGS="$TARGET_CFLAGS -mcmodel=large" + SAVED_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -m64 -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" = xyes; then + if test "x$grub_cv_cc_mcmodel" = xno; then + AC_MSG_ERROR([-mcmodel=large not supported. Upgrade your gcc.]) + else 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="$TARGET_CFLAGS -mno-red-zone" + CFLAGS="$CFLAGS -m64 -mno-red-zone" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_no_red_zone=yes], [grub_cv_cc_no_red_zone=no]) @@ -1219,99 +585,29 @@ 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. # -CFLAGS="$TARGET_CFLAGS" +# Need __enable_execute_stack() for nested function trampolines? +grub_CHECK_ENABLE_EXECUTE_STACK # 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' or '-fpie' and '-pie' in the default specs. +# `-fPIE' in the default specs. if [ x"$pie_possible" = xyes ]; then - 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 + TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE" fi] -CFLAGS="$TARGET_CFLAGS" -LDFLAGS="$TARGET_LDFLAGS" - # Position independent executable. grub_CHECK_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" +[# 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" fi] -CFLAGS="$TARGET_CFLAGS" - # Smashing stack protector. grub_CHECK_STACK_PROTECTOR # Need that, because some distributions ship compilers that include @@ -1319,9 +615,6 @@ grub_CHECK_STACK_PROTECTOR if test "x$ssp_possible" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector" 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. @@ -1329,102 +622,101 @@ if test x"$sap_possible" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe" fi -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 +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" 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"$platform" = xemu ; then -CFLAGS="$TARGET_CFLAGS -Wno-error" -elif test "x$TARGET_APPLE_LINKER" = x1 ; then -CFLAGS="$TARGET_CFLAGS -nostdlib -static -Wno-error" -else +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$TARGET_APPLE_LINKER" = x0 && test x"$platform" != xemu; then if test x$grub_cv_asm_uscore = xyes; then -DEFSYM="-Wl,--defsym,_abort=_main -Wl,--defsym,__main=_main" +CFLAGS="$CFLAGS -Wl,--defsym,_abort=_main" else -DEFSYM="-Wl,--defsym,abort=main -Wl,--defsym,_main=main -Wl,--defsym,__main=main" -fi -CFLAGS="$TARGET_CFLAGS -nostdlib $DEFSYM" +CFLAGS="$CFLAGS -Wl,--defsym,abort=main" fi # Check for libgcc symbols -if test x"$platform" = xemu; then -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 +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$TARGET_APPLE_LINKER" = x1 ; then -CFLAGS="$TARGET_CFLAGS -nostdlib -static" -else +if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" +else +CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100" fi LIBS="" # Defined in aclocal.m4. grub_PROG_TARGET_CC -if test "x$TARGET_APPLE_LINKER" != x1 ; then +if test "x$TARGET_APPLE_CC" != 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_LINKER" != x1 ; then + if test "$platform" != emu && test "x$TARGET_APPLE_CC" != 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},0x8000" + CFLAGS="$TARGET_CFLAGS -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},8000 -Wl,--defsym,___main=0x8100" 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 -nostdlib -nostdinc -isystem `$TARGET_CC -print-file-name=include`" + CPPFLAGS="$TARGET_CPPFLAGS -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]) @@ -1436,16 +728,21 @@ if test x"$grub_cv_cc_isystem" = xyes ; then fi fi -AC_CACHE_CHECK([whether -Wtrampolines work], [grub_cv_cc_wtrampolines], [ - CFLAGS="$TARGET_CFLAGS -Wtrampolines -Werror" +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_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include int va_arg_func (int fixed, va_list args);]], [[]])], - [grub_cv_cc_wtrampolines=yes], - [grub_cv_cc_wtrampolines=no]) + [grub_cv_cc_wnotrampolines=yes], + [grub_cv_cc_wnotrampolines=no]) + CFLAGS="$SAVED_CFLAGS" ]) -if test x"$grub_cv_cc_wtrampolines" = xyes ; then - TARGET_CFLAGS="$TARGET_CFLAGS -Wtrampolines" +if test x"$grub_cv_cc_wnotrampolines" = xyes ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Wno-trampolines" fi # Restore the flags. @@ -1462,11 +759,9 @@ LIBS="$tmp_LIBS" # Memory manager debugging. AC_ARG_ENABLE([mm-debug], AS_HELP_STRING([--enable-mm-debug], - [include memory manager debugging])) -if test x$enable_mm_debug = xyes; then - AC_DEFINE([MM_DEBUG], [1], - [Define to 1 if you enable memory manager debugging.]) -fi + [include memory manager debugging]), + [AC_DEFINE([MM_DEBUG], [1], + [Define to 1 if you enable memory manager debugging.])]) AC_ARG_ENABLE([cache-stats], AS_HELP_STRING([--enable-cache-stats], @@ -1479,16 +774,9 @@ else fi AC_SUBST([DISK_CACHE_STATS]) -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-usb], + [AS_HELP_STRING([--enable-grub-emu-usb], + [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) AC_ARG_ENABLE([grub-emu-sdl], [AS_HELP_STRING([--enable-grub-emu-sdl], @@ -1499,9 +787,53 @@ 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_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="explicitly disabled" + grub_emu_sdl_excuse="explicitely disabled" fi [if [ x"$grub_emu_sdl_excuse" = x ]; then # Check for libSDL libraries.] @@ -1517,7 +849,7 @@ AC_CHECK_LIB([SDL], [SDL_Init], [LIBSDL="-lSDL"], [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)]) + 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 @@ -1529,6 +861,10 @@ 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"], @@ -1537,7 +873,7 @@ fi [fi] [if [ x"$grub_emu_pci_excuse" = x ]; then # Check for headers.] - AC_CHECK_HEADERS([pciaccess.h], [], + AC_CHECK_HEADERS([pci/pci.h], [], [grub_emu_pci_excuse=["need libpciaccess headers"]]) [fi] @@ -1549,13 +885,8 @@ enable_grub_emu_pci=no fi AC_SUBST([enable_grub_emu_sdl]) +AC_SUBST([enable_grub_emu_usb]) AC_SUBST([enable_grub_emu_pci]) - -else - -# Ignore --enable-emu-* if platform is not emu -enable_grub_emu_sdl=no -enable_grub_emu_pci=no fi AC_ARG_ENABLE([grub-mkfont], @@ -1565,120 +896,51 @@ 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"] + fi +fi if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. - 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"]]) + 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 ($grub_mkfont_excuse)]) + AC_MSG_ERROR([grub-mkfont was explicitly requested but can't be compiled]) fi if test x"$grub_mkfont_excuse" = x ; then 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]) +fi AC_SUBST([enable_grub_mkfont]) - -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_LDFAGS" - -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"]]) - 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" - +AC_SUBST([freetype_cflags]) +AC_SUBST([freetype_libs]) DJVU_FONT_SOURCE= starfield_excuse= -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 && test x"$enable_build_grub_mkfont" = xno ; then - starfield_excuse="No build-time grub-mkfont" +if test x$enable_grub_mkfont = xno; then + starfield_excuse="No grub-mkfont" 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 /usr/share/fonts/truetype; 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 @@ -1691,47 +953,8 @@ if test x"$starfield_excuse" = x; then fi 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]) -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 /usr/share/fonts/uni /usr/share/fonts/truetype/unifont /usr/share/fonts/misc; 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 - -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)])]) @@ -1747,14 +970,14 @@ fi if test x"$grub_mount_excuse" = x ; then # Check for fuse headers. SAVED_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -DFUSE_USE_VERSION=26" + 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" 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 ($grub_mount_excuse)]) + AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled]) fi if test x"$grub_mount_excuse" = x ; then enable_grub_mount=yes @@ -1790,7 +1013,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 @@ -1806,32 +1029,10 @@ 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_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 - + [LIBLZMA="-llzma" + AC_DEFINE([HAVE_LIBLZMA], [1], + [Define to 1 if you have the LZMA library.])],) AC_SUBST([LIBLZMA]) AC_ARG_ENABLE([libzfs], @@ -1853,13 +1054,13 @@ if test x"$libzfs_excuse" = x ; then fi if test x"$libzfs_excuse" = x ; then - AC_CHECK_LIB([nvpair], [nvlist_lookup_string], + AC_CHECK_LIB([nvpair], [nvlist_print], [], [libzfs_excuse="need nvpair library"]) 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 ($libzfs_excuse)]) + AC_MSG_ERROR([libzfs support was explicitly requested but requirements are not satisfied]) fi if test x"$libzfs_excuse" = x ; then @@ -1880,65 +1081,23 @@ 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_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" -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) +AC_SUBST(NEED_ENABLE_EXECUTE_STACK) +AC_SUBST(NEED_REGISTER_FRAME_INFO) # # Automake conditionals # -AM_CONDITIONAL([COND_real_platform], [test x$platform != xnone]) AM_CONDITIONAL([COND_emu], [test x$platform = xemu]) 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]) @@ -1948,28 +1107,14 @@ AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = 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_x86_64_xen], [test x$target_cpu = xx86_64 -a x$platform = xxen]) 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 -o x$target_cpu = xmipsel ")" -a x$platform = xarc]) +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_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu]) 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_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_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_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) @@ -1980,71 +1125,45 @@ 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_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_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) -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_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) +AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = 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]) - -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. -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 +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 - # 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 + 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 AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([grub-core/Makefile]) -AC_CONFIG_FILES([grub-core/lib/gnulib/Makefile]) +AC_CONFIG_FILES([grub-core/gnulib/Makefile]) AC_CONFIG_FILES([po/Makefile.in]) AC_CONFIG_FILES([docs/Makefile]) AC_CONFIG_FILES([util/bash-completion.d/Makefile]) @@ -2057,6 +1176,11 @@ 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 +else +echo USB support for grub-emu: No "($grub_emu_usb_excuse)" +fi if [ x"$grub_emu_sdl_excuse" = x ]; then echo SDL support for grub-emu: Yes else @@ -2083,13 +1207,6 @@ 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 @@ -2107,7 +1224,6 @@ echo grub-mount: No "($grub_mount_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 @@ -2116,21 +1232,5 @@ 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 echo "*******************************************************" ] diff --git a/coreboot.cfg b/coreboot.cfg deleted file mode 100644 index 188090d3a..000000000 --- a/coreboot.cfg +++ /dev/null @@ -1,3 +0,0 @@ -if test -f (cbfsdisk)/etc/grub.cfg; then - source (cbfsdisk)/etc/grub.cfg -fi diff --git a/docs/autoiso.cfg b/docs/autoiso.cfg deleted file mode 100644 index 9ce51c692..000000000 --- a/docs/autoiso.cfg +++ /dev/null @@ -1,244 +0,0 @@ -# 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 24d17b8ec..a4a38206e 100644 --- a/docs/grub-dev.texi +++ b/docs/grub-dev.texi @@ -74,18 +74,16 @@ This edition documents version @value{VERSION}. @menu * Getting the source code:: -* Coding style:: * Finding your way around:: +* Coding style:: * Contributing Changes:: -* Updating External Code:: * Porting:: * Error Handling:: -* Stack and heap size:: +* CIA:: * BIOS port memory map:: * Video Subsystem:: * PFF2 Font File Format:: * Graphical Menu Software Design:: -* Verifiers framework:: * Copying This Manual:: Copying This Manual * Index:: @end menu @@ -94,36 +92,24 @@ This edition documents version @value{VERSION}. @node Getting the source code @chapter Getting the source code -GRUB is maintained using the @uref{GIT revision -control system}. To fetch: +GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision +control system}. To fetch the primary development branch: @example -git clone git://git.sv.gnu.org/grub.git +bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub @end example -Web access is available under +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: + @example -http://git.savannah.gnu.org/cgit/grub.git/ +bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental @end example -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 +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 local version, you may need to resolve conflicts when pulling. @node Coding style @@ -183,44 +169,38 @@ 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{} */}. -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. + +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. 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 render_page; /* The page # that is the back buffer. */ +int displayed_page; /* The page # that is the front 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 be repeated at -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 not be repeated a 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 @@ -228,16 +208,7 @@ Unacceptable: * It is long. */ @end example -@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. +The opening @samp{/*} and closing @samp{*/} should be placed together on a line with text. @node Finding your way around @chapter Finding your way around @@ -245,12 +216,12 @@ long. So, its usage is disallowed. Here is a brief map of the GRUB code base. GRUB uses Autoconf and Automake, with most of the Automake input generated -by a Python script. The top-level build rules are in @file{configure.ac}, +by AutoGen. 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 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 +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 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 @@ -315,19 +286,14 @@ 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 @@ -363,10 +329,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 GIT 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 Bazaar (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} +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} @item Compile it and try it out. @@ -482,106 +448,6 @@ 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 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:: -@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 http://www.oberhumer.com/opensource/lzo/download/minilzo-2.08.tar.gz -tar -zxf minilzo-2.08.tar.gz -rm minilzo-2.08/testmini.c -rm -r grub-core/lib/minilzo/* -cp minilzo-2.08/*.[hc] grub-core/lib/minilzo -rm -r minilzo-2.08* -@end example - @node Porting @chapter Porting @@ -788,7 +654,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 -./bootstrap +./autogen.sh ./configure --target=$cpu --with-platform=$platform TARGET_CC=.. OBJCOPY=... STRIP=... make > /dev/null @end example @@ -1024,68 +890,33 @@ if (grub_errno != GRUB_ERR_NONE) grub_error_pop (); @end example -@node Stack and heap size -@chapter Stack and heap size +@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. -On emu stack and heap are just normal host OS stack and heap. Stack is typically -8 MiB although it's OS-dependent. +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 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. +In the @file{.bzr/branch/branch.conf} of your checkout branch, +"set nickname = /path_to_this_branch" and "cia_project = GNU GRUB". -On *-xen stack is 4MiB. If compiled for x86-64 with GCC 4.4 or later adressable -space is unlimited. When compiled for x86-64 with older GCC version adressable -space is limited to 2GiB. When compiling for i386 adressable space is limited -to 4GiB. All adressable pages except the ones for stack, GRUB binary, special -pages and page table are in the heap. +Additionally, please set cia_send_revno in the [DEFAULT] section +of your @file{~/.bazaar/bazaar.conf}. E.g.: -On *-efi GRUB uses same stack as EFI. If compiled for x86-64 with GCC 4.4 or -later adressable space is unlimited. When compiled for x86-64 with older GCC -version adressable space is limited to 2GiB. For all other platforms adressable -space is limited to 4GiB. GRUB allocates pages from EFI for its heap, at most -1.6 GiB. +@example +[DEFAULT] +cia_send_revno = true +@end example -On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275. -It allocates at most 32MiB for its heap. - -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 < 32 MiB -@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 +Remember to install cia-clients (Debian/Ubuntu package) to be able to use CIA. +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 @@ -1098,8 +929,9 @@ In short: @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 0x71000 - 1 @tab Disk buffer +@item 0x68000 @tab 0x78000 - 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 @@ -1116,8 +948,8 @@ driver manager works are not included here. @menu * Video API:: -* Example usage of Video API:: * Bitmap API:: +* Example usage of Video API:: @end menu @node Video API @@ -1276,47 +1108,6 @@ 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: @@ -1343,37 +1134,6 @@ 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: @@ -1634,8 +1394,8 @@ grub_video_blit_glyph (&glyph, color, 0, 0); @node Bitmap API @section Bitmap API -@subsection grub_video_bitmap_create @itemize +@subsection grub_video_bitmap_create @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) @@ -1929,9 +1689,7 @@ 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 -@ifnottex -@image{font_char_metrics,,,,.png} -@end ifnottex +@image{font_char_metrics,,,,png} An illustration of how the various font metrics apply to characters. @@ -2066,63 +1824,6 @@ 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 Copying This Manual @appendix Copying This Manual diff --git a/docs/grub.texi b/docs/grub.texi index 37f7ce7da..b5954da82 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,2013 Free Software Foundation, Inc. +Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -36,11 +36,8 @@ 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 @@ -81,9 +78,6 @@ 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 @@ -92,13 +86,12 @@ 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 * Internationalisation:: Topics relating to language support -* Security:: Authentication, authorisation, and signatures +* Security:: Authentication and authorisation * Platform limitations:: The list of platform-specific limitations * Platform-specific operations:: Platform-specific operations * Supported kernels:: The list of supported kernels @@ -107,11 +100,8 @@ This edition documents version @value{VERSION}. * 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-script-check:: Check GRUB script file for syntax errors * 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 @@ -321,10 +311,8 @@ 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@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. +compliance (primarily FreeBSD, NetBSD, 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. @@ -360,9 +348,8 @@ 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{F2FS}, @dfn{HFS}, @dfn{HFS+}, -@dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files), +@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{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}, @@ -542,75 +529,6 @@ 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 @@ -657,7 +575,7 @@ For example, under Linux the following will install GRUB into the MBR of the first IDE disk: @example -# @kbd{grub-install /dev/sda} +# @kbd{grub-install /dev/hda} @end example Likewise, under GNU/Hurd, this has the same effect: @@ -696,31 +614,11 @@ 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 other tools such as @command{grub-mkimage}. 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 +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. @node Making a GRUB bootable CD-ROM @section Making a GRUB bootable CD-ROM @@ -782,8 +680,8 @@ storage devices. @section The map between BIOS drives and OS devices If the device map file exists, the GRUB utilities (@command{grub-probe}, -etc.) read it to map BIOS drives to OS devices. This file consists of lines -like this: +@command{grub-setup}, etc.) read it to map BIOS drives to OS devices. This +file consists of lines like this: @example (@var{device}) @var{file} @@ -894,7 +792,6 @@ 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 @@ -992,26 +889,6 @@ way. Please consider alternative boot methods like copying all files from the image to actual partition. Consult your OS documentation for 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 @@ -1020,7 +897,6 @@ Here, we describe some caveats on several operating systems. @menu * GNU/Hurd:: * GNU/Linux:: -* NetBSD:: * DOS/Windows:: @end menu @@ -1114,62 +990,11 @@ grub> @kbd{initrd16 /initrd} Finally, run the command @command{boot} (@pxref{boot}). @end enumerate - -@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 +@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 DOS/Windows @@ -1229,11 +1054,10 @@ 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 -* Root Identifcation 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 +* 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 @end menu @@ -1271,14 +1095,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 id may be +menu entry, or the special string @samp{saved}. Using the title 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 --id example-gnu-linux { +menuentry 'Example GNU/Linux distribution' --class gnu-linux { ... } @end verbatim @@ -1286,17 +1110,12 @@ menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-li then you can make this the default using: @example -GRUB_DEFAULT=example-gnu-linux +GRUB_DEFAULT='Example GNU/Linux distribution' @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} or @command{grub-set-default}. This relies on -the environment block, which may not be available in all situations -(@pxref{Environment block}). +saved by @samp{GRUB_SAVEDEFAULT}, @command{grub-set-default}, or +@command{grub-reboot}. The default is @samp{0}. @@ -1305,7 +1124,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}. Unset by default. +@command{grub-set-default} or @command{grub-reboot}. Unset by default. This option relies on the environment block, which may not be available in all situations (@pxref{Environment block}). @@ -1315,26 +1134,22 @@ 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. -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 +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. -@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_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_DEFAULT_BUTTON @itemx GRUB_TIMEOUT_BUTTON -@itemx GRUB_TIMEOUT_STYLE_BUTTON +@itemx GRUB_HIDDEN_TIMEOUT_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}. @@ -1348,9 +1163,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} (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 +@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 using the HID Boot Protocol, for cases where the firmware does not handle this). @@ -1361,21 +1176,9 @@ 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} (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 +@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). The default is to use the platform's native terminal output. @@ -1407,33 +1210,15 @@ As @samp{GRUB_CMDLINE_LINUX}, but for GNU Mach. @item GRUB_CMDLINE_XEN @itemx GRUB_CMDLINE_XEN_DEFAULT -The values of these options are passed to Xen hypervisor Xen menu entries, -for all respectively normal entries. +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. @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_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 @@ -1441,30 +1226,10 @@ 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 explicilty 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, @@ -1510,28 +1275,6 @@ Normally, @command{grub-mkconfig} will try to use the external systems installed on the same system and generate appropriate menu entries for them. Set this option to @samp{true} to disable this. -@item GRUB_OS_PROBER_SKIP_LIST -List of space-separated FS UUIDs of filesystems to be ignored from os-prober -output. For efi chainloaders it's @@ - -@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 for users unable to see the screen. The value of this option is passed @@ -1548,97 +1291,12 @@ 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 Identifcation Heuristics -@section Root Identifcation 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{false} when they are unset. @node Shell-like scripting @section Writing full configuration files directly @@ -1784,7 +1442,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}] [@option{--id=id}] @{ @var{command}; @dots{} @} +@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--unrestricted}] [@option{--hotkey=key}] @{ @var{command}; @dots{} @} @xref{menuentry}. @end table @@ -1816,10 +1474,6 @@ 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 @@ -1924,7 +1578,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 recommended 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 recommened due to device name instability. @end itemize @node Embedded configuration @@ -2017,8 +1671,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 (@ref{loadfont}). To see the list of -loaded fonts, execute the ``lsfonts'' command (@ref{lsfonts}). If there are too many fonts to +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 fit on screen, do ``set pager=1'' before executing ``lsfonts''. @@ -2158,60 +1812,15 @@ 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 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. +@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. @end multitable @@ -2245,34 +1854,21 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.2 0.7 - @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. + @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``. @end multitable @item image - A component that displays an image. The image is scaled to fit - the component. + 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. 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 @@ -2282,45 +1878,17 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.2 0.7 - @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. + @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. @end multitable @item circular_progress @@ -2334,9 +1902,6 @@ 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 @@ -2346,13 +1911,14 @@ 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``. 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. + ``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. @end multitable - @item boot_menu Displays the GRUB boot menu. It allows selecting items and executing them. @@ -2386,8 +1952,6 @@ 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 @@ -2400,39 +1964,10 @@ 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 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. + @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. @end multitable @item canvas @@ -2476,10 +2011,7 @@ The following properties are supported by all components: recognizes: @multitable @columnfractions 0.2 0.7 - @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``. + @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. @end multitable @end table @@ -2488,138 +2020,67 @@ The following properties are supported by all components: @node Network @chapter Booting GRUB from the network -The following instructions don't work for *-emu, i386-qemu, i386-coreboot, -i386-multiboot, mips_loongson, mips-arc and mips_qemu_mips +The following instructions only work on PC BIOS systems where the Preboot +eXecution Environment (PXE) is available. -To generate a netbootable directory, run: +To generate a PXE boot image, run: @example @group -grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/ +grub-mkimage --format=i386-pc-pxe --output=grub.pxe --prefix='(pxe)/boot/grub' pxe pxecmd @end group @end example -E.g. for i386-pc: +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). -@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-@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 loouk 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-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}). +You can also use the @command{grub-mknetdir} utility to generate an image +and a GRUB directory tree, rather than copying files around manually. After GRUB has started, files on the TFTP server will be accessible via the -@samp{(tftp)} device. +@samp{(pxe)} device. -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. +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. GRUB provides several environment variables which may be used to inspect or -change the behaviour of the PXE device. In the following description -@var{} is placeholder for the name of network interface (platform -dependent): +change the behaviour of the PXE device: @table @samp -@item net_@var{}_ip -The network interface's IP address. Read-only. +@item net_pxe_ip +The IP address of this machine. Read-only. -@item net_@var{}_mac +@item net_pxe_mac The network interface's MAC address. Read-only. -@item net_@var{}_hostname +@item net_pxe_hostname The client host name provided by DHCP. Read-only. -@item net_@var{}_domain +@item net_pxe_domain The client domain name provided by DHCP. Read-only. -@item net_@var{}_rootpath +@item net_pxe_rootpath The path to the client's root disk provided by DHCP. Read-only. -@item net_@var{}_extensionspath +@item net_pxe_extensionspath The path to additional DHCP vendor extensions provided by DHCP. Read-only. -@item net_@var{}_boot_file +@item net_pxe_boot_file The boot file name provided by DHCP. Read-only. -@item net_@var{}_dhcp_server_name +@item net_pxe_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 used by network drives (@pxref{Device syntax}). Read-write, -although setting this is only useful before opening a network device. +The default server. Read-write, although setting this is only useful +before opening a network device. @end table @@ -2676,28 +2137,21 @@ 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_TIMEOUT_STYLE_BUTTON}, @samp{GRUB_DEFAULT_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_DEFAULT_BUTTON}, @samp{GRUB_HIDDEN_TIMEOUT_BUTTON} and @samp{GRUB_BUTTON_CMOS_ADDRESS} variables in default/grub (@pxref{Simple -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: +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: @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 @@ -2762,8 +2216,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-install} hardcodes the location of the first sector of the -core image into @file{boot.img} when installing GRUB. +@command{grub-setup} 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 @@ -2856,44 +2310,6 @@ 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 @@ -2927,17 +2343,16 @@ 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 name. -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''. +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. 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/. For LVM additionally you can use the syntax -lvmid//. +uuid/. @example (fd0) @@ -2949,8 +2364,7 @@ lvmid//. (usb0) (cryptouuid/123456789abcdef0123456789abcdef0) (mduuid/123456789abcdef0123456789abcdef0) -(lvm/system-root) -(lvmid/F1ikgD-2RES-306G-il9M-7iwa-4NKW-EbV1NV/eLGuCQ-L4Ka-XUgR-sjtJ-ffch-bajr-fCNfz5) +(lv/system-root) (md/myraid) (md/0) (ieee1275/disk2) @@ -2981,10 +2395,8 @@ of the partition when installing GRUB). (hd0,1,3) @end example -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. +If you enabled the network support, the special drives @samp{(tftp)}, +@samp{(http)} and so on ars also available. Before using the network drive, you must initialize the network. @xref{Network}, for more information. @@ -3007,13 +2419,6 @@ 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 @@ -3193,39 +2598,28 @@ These variables have special meaning to GRUB. @menu * biosnum:: -* check_signatures:: * chosen:: -* cmdpath:: * color_highlight:: * color_normal:: -* config_directory:: -* config_file:: * debug:: * default:: * fallback:: * gfxmode:: * gfxpayload:: * gfxterm_font:: -* grub_cpu:: -* grub_platform:: * icondir:: * lang:: * locale_dir:: * menu_color_highlight:: * menu_color_normal:: -* net_@var{}_boot_file:: -* 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:: +* 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:: * pager:: * prefix:: * pxe_blksize:: @@ -3235,7 +2629,6 @@ These variables have special meaning to GRUB. * superusers:: * theme:: * timeout:: -* timeout_style:: @end menu @@ -3252,12 +2645,6 @@ 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 @@ -3269,16 +2656,6 @@ 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 @@ -3286,7 +2663,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/light-gray}. +The default is @samp{black/white}. @node color_normal @@ -3315,48 +2692,7 @@ those colors. Each color must be a name from the following list: @item white @end itemize -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. +The default is @samp{white/black}. @node debug @@ -3365,52 +2701,34 @@ processed by commands @command{configfile} (@pxref{configfile}) or @command{norm 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. The facility names are the first argument to grub_dprintf. Consult -source for more details. +output. @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 (starting from 0 at each level of -the hierarchy), by title, or by id. +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. -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: +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: @example -default=example-gnu-linux +Submenu 1 + Menu Entry 1 + Menu Entry 2 +Submenu 2 + Submenu 3 + Menu Entry 3 + Menu Entry 4 + Menu Entry 5 @end example -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}. +``Menu Entry 3'' would then be identified as +@samp{Submenu 2>Submenu 3>Menu Entry 3}. This variable is often set by @samp{GRUB_DEFAULT} (@pxref{Simple configuration}), @command{grub-set-default}, or @command{grub-reboot}. @@ -3431,8 +2749,7 @@ 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. Supported -modes can be listed by @samp{videoinfo} command in GRUB. +selects a platform-specific default that should look reasonable. The resolution may be specified as a sequence of one or more modes, separated by commas (@samp{,}) or semicolons (@samp{;}); each will be tried @@ -3473,20 +2790,6 @@ 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 @@ -3542,80 +2845,50 @@ variable changes those colors. For the available color names, The default is the value of @samp{color_normal} (@pxref{color_normal}). -@node net_@var{}_boot_file -@subsection net_@var{}_boot_file +@node net_pxe_boot_file +@subsection net_pxe_boot_file @xref{Network}. -@node net_@var{}_dhcp_server_name -@subsection net_@var{}_dhcp_server_name +@node net_pxe_dhcp_server_name +@subsection net_pxe_dhcp_server_name @xref{Network}. -@node net_@var{}_domain -@subsection net_@var{}_domain +@node net_pxe_domain +@subsection net_pxe_domain @xref{Network}. -@node net_@var{}_extensionspath -@subsection net_@var{}_extensionspath +@node net_pxe_extensionspath +@subsection net_pxe_extensionspath @xref{Network}. -@node net_@var{}_hostname -@subsection net_@var{}_hostname +@node net_pxe_hostname +@subsection net_pxe_hostname @xref{Network}. -@node net_@var{}_ip -@subsection net_@var{}_ip +@node net_pxe_ip +@subsection net_pxe_ip @xref{Network}. -@node net_@var{}_mac -@subsection net_@var{}_mac +@node net_pxe_mac +@subsection net_pxe_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 +@node net_pxe_rootpath +@subsection net_pxe_rootpath @xref{Network}. @@ -3693,21 +2966,8 @@ 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. -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. +This variable is often set by @samp{GRUB_TIMEOUT} or +@samp{GRUB_HIDDEN_TIMEOUT} (@pxref{Simple configuration}). @node Environment block @@ -3757,7 +3017,6 @@ shell}. * Menu-specific commands:: * General commands:: * Command-line and menu entry commands:: -* Networking commands:: @end menu @@ -3795,13 +3054,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}] [@option{--id=id}] @ - [@var{arg} @dots{}] @{ @var{command}; @dots{} @} + [@option{--unrestricted}] [@option{--hotkey=key}] @ + @{ @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 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. +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. The @option{--class} option may be used any number of times to group menu entries into classes. Menu themes may display different classes using @@ -3816,13 +3075,6 @@ 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 @@ -3831,7 +3083,7 @@ when list of commands is executed with @var{title} always assigned to @code{$1}. @deffn Command submenu @var{title} @ [@option{--class=class} @dots{}] [@option{--users=users}] @ - [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @ + [@option{--unrestricted}] [@option{--hotkey=key}] @ @{ @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 @@ -3948,37 +3200,24 @@ 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:: Compute or check CRC32 checksums -* cryptomount:: Mount a crypto device +* crc:: Calculate CRC32 checksums * 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 -* eval:: Evaluate agruments as GRUB commands * export:: Export an environment variable * false:: Do nothing, unsuccessfully * 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) @@ -3987,60 +3226,28 @@ you forget a command, you can run the command @command{help} * 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 * play:: Play a tune -* probe:: Retrieve device info -* rdmsr:: Read values from model-specific registers +* pxe_unload:: Unload the PXE environment * 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 * true:: Do nothing, successfully -* trust:: Add public key to list of trusted keys * unset:: Unset an environment variable -@comment * vbeinfo:: List available video modes -* verify_detached:: Verify detached digital signature -* videoinfo:: List available video modes -@comment * xen_*:: Xen boot commands for AArch64 -* wrmsr:: Write values to model-specific registers -* xen_hypervisor:: Load xen hypervisor binary (only on AArch64) -* xen_module:: Load xen modules for xen hypervisor (only on AArch64) +* uppermem:: Set the upper memory size @end menu -@node [ -@subsection [ -@deffn Command @code{[} expression @code{]} -Alias for @code{test @var{expression}} (@pxref{test}). -@end deffn - - @node acpi @subsection acpi @@ -4062,42 +3269,6 @@ Normally, this command will replace the Root System Description Pointer GRUB, but may be used by GRUB's EFI emulation. @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 @@ -4170,42 +3341,6 @@ load a defective boot loader, such as SCO UnixWare 7.1. @end deffn -@node clear -@subsection clear - -@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 @@ -4233,24 +3368,19 @@ 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. Any environment -variable changes made by the commands in @var{file} will not be preserved -after @command{configfile} returns. +entries, then show a menu containing them immediately. @end deffn @node cpuid @subsection cpuid -@deffn Command cpuid [-l] [-p] +@deffn Command cpuid [-l] 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 @@ -4259,25 +3389,8 @@ invoked with @option{-l}. This may change in the future. @node crc @subsection crc -@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 cryptomount -@subsection cryptomount - -@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b} -Setup access to encrypted device. If necessary, passphrase -is requested interactively. Option @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. - -GRUB suports 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. +@deffn Command crc file +Display the CRC32 checksum of @var{file}. @end deffn @@ -4294,31 +3407,6 @@ 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. -@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 @@ -4388,15 +3476,6 @@ character will print that character. @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 @@ -4457,30 +3536,6 @@ is shut down using APM. @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 - - @node help @subsection help @@ -4497,22 +3552,22 @@ about each of the commands whose names begin with those @var{patterns}. @node initrd @subsection initrd -@deffn Command initrd file [file @dots{}] -Load, in order, all initial ramdisks 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}. +@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 @node initrd16 @subsection initrd16 -@deffn Command initrd16 file [file @dots{}] -Load, in order, all initial ramdisks 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}. +@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 @@ -4579,69 +3634,23 @@ This command is only available on x86 systems. @node list_env @subsection list_env -@deffn Command list_env [@option{--file} file] +@deffn Command list_env [@option{-f} file] List all variables in the environment block file. @xref{Environment block}. -The @option{--file} option overrides the default location of the -environment block. +The @option{-f} 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{--file} file] [@option{--skip-sig}] [whitelisted_variable_name] @dots{} +@deffn Command load_env [@option{-f} file] Load all variables from the environment block file into the environment. @xref{Environment block}. -The @option{--file} option overrides the default location of the environment +The @option{-f} 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 @@ -4671,76 +3680,13 @@ 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 print the name of the filesystem of that device. +syntax}), then list all files at the root directory 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 @@ -4798,7 +3744,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 -Windows and multiple primary FAT partitions exist in one disk. See also +Wwindows and multiple primary FAT partitions exist in one disk. See also @ref{DOS/Windows}. @end table @end deffn @@ -4826,7 +3772,7 @@ to generate password hashes. @xref{Security}. @node play @subsection play -@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] @dots{} +@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] ... Plays a tune If the argument is a file name (@pxref{File name syntax}), play the tune @@ -4842,32 +3788,13 @@ a rest. @end deffn -@node probe -@subsection probe +@node pxe_unload +@subsection pxe_unload -@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. +@deffn Command pxe_unload +Unload the PXE environment (@pxref{Network}). -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. +This command is only available on PC BIOS systems. @end deffn @@ -4889,45 +3816,15 @@ 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{--file} file] var @dots{} +@deffn Command save_env [@option{-f} file] var @dots{} Save the named variables from the environment to the environment block file. @xref{Environment block}. -The @option{--file} option overrides the default location of the environment +The @option{-f} 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 @@ -5111,202 +4008,6 @@ arguments, print all environment variables with their values. @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 true @subsection true @@ -5315,22 +4016,6 @@ 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 @@ -5340,291 +4025,23 @@ Unset the environment variable @var{envvar}. @end deffn -@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. -@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 Networking commands -@section The list of 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 -@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 uppermem +@subsection uppermem +This command is not yet implemented for GRUB 2, although it is planned. @node Internationalisation -@chapter Internationalisation - -@section Charset +@chapter 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. -@section Filesystems +@chapter 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), -F2FS, RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed +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 @@ -5653,41 +4070,32 @@ 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. -@section Output terminal +@chapter 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. - -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 +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 -developer team. +developper team. -@section Input terminal +@chapter 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 @@ -5697,15 +4105,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. -@section Gettext +@chapter Gettext GRUB supports being translated. For this you need to have language *.mo files in $prefix/locale, load gettext module and set ``lang'' variable. -@section Regexp +@chapter Regexp Regexps work on unicode characters, however no attempt at checking cannonical equivalence has been made. Moreover the classes like [:alpha:] match only ASCII subset. -@section Other +@chapter 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 @@ -5722,23 +4130,13 @@ 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} (@pxref{test}) tests <, >, <=, >=, -pgt and -plt compare the strings in the +@command{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 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 -* Measured Boot:: Measuring boot components -@end menu - -@node Authentication and authorisation -@section Authentication and authorisation in GRUB +@chapter Authentication and authorisation 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 @@ -5763,13 +4161,10 @@ 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 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. Note: The environment variable needs to be exported to also affect -the section defined by the @samp{submenu} command (@pxref{submenu}). +@samp{superusers} is set, then use of the command line is automatically +restricted to superusers. -Other users may be allowed to execute specific menu entries by giving a list of +Other users may be given access to 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. @@ -5808,146 +4203,6 @@ 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. - -@comment Unfortunately --pubkey is not yet supported by grub-install, -@comment but we should not bring up internal detail grub-mkimage here -@comment in the user guide (as opposed to developer's manual). - -@comment An initial trusted public key can be embedded within the GRUB -@comment @file{core.img} using the @code{--pubkey} option to -@comment @command{grub-mkimage} (@pxref{Invoking grub-install}). Presently it -@comment is necessary to write a custom wrapper around @command{grub-mkimage} -@comment using the @code{--grub-mkimage} flag to @command{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, except the @command{chainloader} command, works with the UEFI secure -boot and the shim. This functionality is provided by the shim_lock module. It -is recommend to build in this and other required modules into the @file{core.img}. -All modules not stored in the @file{core.img} and the ACPI tables for the -@command{acpi} command have to be signed, e.g. using PGP. Additionally, the -@command{iorw}, the @command{memrw} and the @command{wrmsr} commands are -prohibited if the UEFI secure boot is enabled. This is done due to -security reasons. All above mentioned requirements are enforced by the -shim_lock module. And itself it is a persistent module which means that -it cannot be unloaded if it was loaded into the memory. - -@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 platforms. @node Platform limitations @chapter Platform limitations @@ -5960,7 +4215,8 @@ ARC platform is unable to change datetime (firmware doesn't seem to provide a function for it). EMU has similar limitation. -On EMU platform no serial port is available. +ARC platform no serial port is available. +EMU has similar limitation. Console charset refers only to firmware-assisted console. gfxterm is always Unicode (see Internationalisation section for its limitations). Serial is @@ -5977,6 +4233,9 @@ 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. + Direct ATA/AHCI support allows to circumvent various firmware limitations but isn't needed for normal operation except on baremetal ports. @@ -5984,8 +4243,6 @@ 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. @@ -6000,16 +4257,6 @@ 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 @@ -6017,18 +4264,14 @@ to install to is specified, UUID is used instead as well. @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 @@ -6038,18 +4281,14 @@ to install to is specified, UUID is used instead as well. @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 @@ -6059,39 +4298,31 @@ to install to is specified, UUID is used instead as well. @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 @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 +@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 @end multitable @node Platform-specific operations @@ -6107,15 +4338,14 @@ Information retrieval: @itemize @item mipsel-loongson: lsspd @item mips-arc: lsdev -@item efi: lsefisystab, lssal, lsefimmap, lsefi +@item efi: lsefisystab, lssal, lsefimmap @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, fakebios, fix_video +@item i386-efi/x86_64-efi: loadbios, fixvideo @item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): acpi (override ACPI tables) @item i386-pc: drivemap @@ -6130,7 +4360,7 @@ Advanced operations for power users: Miscelaneous: @itemize @item cmos (x86-*, ieee1275, mips-qemu_mips, mips-loongson): cmostest - (used on some laptops to check for special power-on key), cmosclean + (used on some laptops to check for special power-on key) @item i386-pc: play @end itemize @@ -6145,10 +4375,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 (5) -@item 64-bit kFreeBSD @tab yes @tab crashes (5) +@item 32-bit kFreeBSD @tab yes @tab crashes (2,6) +@item 64-bit kFreeBSD @tab yes @tab crashes (2,6) @item 32-bit kNetBSD @tab yes @tab crashes (1) -@item 64-bit kNetBSD @tab yes @tab crashes +@item 64-bit kNetBSD @tab yes @tab crashes (2) @item 32-bit kOpenBSD @tab yes @tab yes @item 64-bit kOpenBSD @tab yes @tab yes @item Multiboot @tab yes @tab yes @@ -6159,9 +4389,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 (2) @tab no (2) -@item 64-bit EFI chainloader @tab no (2) @tab no (2) -@item Appleloader @tab no (2) @tab no (2) +@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) @end multitable @multitable @columnfractions .50 .22 .22 @@ -6171,8 +4401,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 (5) @tab crashes (5) -@item 64-bit kFreeBSD @tab crashes (5) @tab crashes (5) +@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) +@item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6) @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 @@ -6185,9 +4415,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 (2) @tab no (2) -@item 64-bit EFI chainloader @tab no (2) @tab no (2) -@item Appleloader @tab no (2) @tab no (2) +@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) @end multitable @multitable @columnfractions .50 .22 .22 @@ -6210,9 +4440,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 (4) @tab yes -@item 32-bit EFI chainloader @tab yes @tab no (3) -@item 64-bit EFI chainloader @tab no (3) @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 Appleloader @tab yes @tab yes @end multitable @@ -6223,8 +4453,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 (5) -@item 64-bit kFreeBSD @tab crashes (5) +@item 32-bit kFreeBSD @tab crashes (6) +@item 64-bit kFreeBSD @tab crashes (6) @item 32-bit kNetBSD @tab crashes (1) @item 64-bit kNetBSD @tab ? @item 32-bit kOpenBSD @tab ? @@ -6237,13 +4467,14 @@ 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 (2) -@item 64-bit EFI chainloader @tab no (2) -@item Appleloader @tab no (2) +@item 32-bit EFI chainloader @tab no (3) +@item 64-bit EFI chainloader @tab no (3) +@item Appleloader @tab no (3) @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 @@ -6253,7 +4484,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. -@section Boot tests +@chapter 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. @@ -6261,7 +4492,7 @@ Following variables must be defined: @multitable @columnfractions .30 .65 @item GRUB_PAYLOADS_DIR @tab directory containing the required kernels -@item GRUB_CBFSTOOL @tab cbfstool from Coreboot package (for coreboot platform only) +@item GRUB_CBFSTOOL @tab cbfstoll 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 @@ -6286,7 +4517,6 @@ Required files are: @menu * GRUB only offers a rescue shell:: -* Firmware stalls instead of booting GRUB:: @end menu @@ -6352,28 +4582,17 @@ 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 with unsupported encryption scheme, nor from file systems for which -support has not yet been added to GRUB. +devices, nor from file systems for which support has not yet been added to +GRUB. @end itemize -@node Firmware stalls instead of booting GRUB -@section Firmware stalls instead of booting GRUB - -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 Invoking grub-install @chapter 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: +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: @example grub-install @var{install_device} @@ -6419,21 +4638,9 @@ 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 @@ -6488,33 +4695,6 @@ Length of the salt. Defaults to 64. @end table -@node Invoking grub-mkrelpath -@chapter 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 @@ -6573,93 +4753,6 @@ built-in default. @end table -@node Invoking grub-mount -@chapter 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 @@ -6746,33 +4839,6 @@ Print verbose messages. @end table -@node Invoking grub-script-check -@chapter 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 @@ -6810,8 +4876,8 @@ just do: @end group @end example -Also, the latest version is available using Git. See -@uref{http://www.gnu.org/software/grub/grub-download.html} for more +Also, the latest version is available using Bazaar. See +@uref{http://www.gnu.org/software/grub/grub-download.en.html} for more information. @node Reporting bugs diff --git a/docs/man/grub-bios-setup.h2m b/docs/man/grub-bios-setup.h2m index ac6ede362..eebe3ef38 100644 --- a/docs/man/grub-bios-setup.h2m +++ b/docs/man/grub-bios-setup.h2m @@ -1,5 +1,5 @@ [NAME] -grub-bios-setup \- set up a device to boot using GRUB +grub-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 deleted file mode 100644 index e09bb4d31..000000000 --- a/docs/man/grub-file.h2m +++ /dev/null @@ -1,2 +0,0 @@ -[NAME] -grub-file \- check file type diff --git a/docs/man/grub-glue-efi.h2m b/docs/man/grub-glue-efi.h2m deleted file mode 100644 index c1c6ded49..000000000 --- a/docs/man/grub-glue-efi.h2m +++ /dev/null @@ -1,4 +0,0 @@ -[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 8cbbc87a0..2de371a3f 100644 --- a/docs/man/grub-install.h2m +++ b/docs/man/grub-install.h2m @@ -3,4 +3,5 @@ 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 deleted file mode 100644 index 0197c0087..000000000 --- a/docs/man/grub-macbless.h2m +++ /dev/null @@ -1,4 +0,0 @@ -[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 new file mode 100644 index 000000000..3ef8e9712 --- /dev/null +++ b/docs/man/grub-mkdevicemap.h2m @@ -0,0 +1,4 @@ +[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 f0fbc2bb1..ca08b0c5c 100644 --- a/docs/man/grub-mkimage.h2m +++ b/docs/man/grub-mkimage.h2m @@ -2,5 +2,6 @@ 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-render-label.h2m b/docs/man/grub-render-label.h2m deleted file mode 100644 index 50ae5247c..000000000 --- a/docs/man/grub-render-label.h2m +++ /dev/null @@ -1,3 +0,0 @@ -[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 18f803a50..eebe3ef38 100644 --- a/docs/man/grub-sparc64-setup.h2m +++ b/docs/man/grub-sparc64-setup.h2m @@ -1,5 +1,5 @@ [NAME] -grub-sparc64-setup \- set up a device to boot using GRUB +grub-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 deleted file mode 100644 index ad25c8ab7..000000000 --- a/docs/man/grub-syslinux2cfg.h2m +++ /dev/null @@ -1,4 +0,0 @@ -[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 deleted file mode 100644 index 47455601d..000000000 --- a/docs/osdetect.cfg +++ /dev/null @@ -1,331 +0,0 @@ -# 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 c86550d4f..13a60816f 100644 --- a/gentpl.py +++ b/gentpl.py @@ -1,6 +1,6 @@ #! /usr/bin/python # GRUB -- GRand Unified Bootloader -# Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc. +# Copyright (C) 2010,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 @@ -15,24 +15,15 @@ # 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.*.am +# This is the python script used to generate Makefile.tpl # 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", "arm_uboot", "arm_efi", "arm64_efi", - "arm_coreboot", "riscv32_efi", "riscv64_efi" ] + "mips_qemu_mips" ] GROUPS = {} @@ -45,18 +36,10 @@ 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["riscv32"] = [ "riscv32_efi" ] -GROUPS["riscv64"] = [ "riscv64_efi" ] # Groups based on firmware -GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", - "riscv32_efi", "riscv64_efi" ] +GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_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") @@ -64,30 +47,21 @@ 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"] + ["arm_coreboot"] +GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel -GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ] +GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"] GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) # Similar for terminfo -GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips", "i386_xen_pvh" ] + GROUPS["xen"] + GROUPS["ieee1275"] + GROUPS["uboot"]; +GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) -# Flattened Device Trees (FDT) -GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_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 +# Miscelaneous groups schedulded to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") @@ -115,410 +89,81 @@ 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): - output(var + " += " + value + "\n") + GVARS.add(var) + return var + " += " + value + "\n" + +def global_variable_initializers(): + r = "" + for var in sorted(GVARS): + r += var + " ?= \n" + return r # # Per PROGRAM/SCRIPT variables # -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 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) def var_set(var, value): - output(var + " = " + value + "\n") + return var + " = " + value + "\n" def var_add(var, value): - output(var + " += " + value + "\n") + return var + " += " + value + "\n" # -# Variable names and rules +# Autogen constructs # -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 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` +]" def rule(target, source, cmd): if cmd[0] == "\n": - output("\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n") + return "\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n" else: - output("\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n") + return "\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n" # -# Handle keys with platform names as values, for example: +# Template for keys with platform names as values, for example: # # kernel = { # nostrip = emu; # ... # } # -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 +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 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 + 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 # -# Handle tagged values +# Template for tagged values # # module = { # extra_dist = ... @@ -526,14 +171,11 @@ def if_platform_tagged(defn, platform, tag, snippet_if, snippet_else=None): # ... # }; # -def foreach_value(defn, tag, closure): - r = [] - for value in defn.find_all(tag): - r.append(closure(value)) - return ''.join(r) +def foreach_value(tag, closure): + return "[+ FOR " + tag + " +]" + closure("[+ ." + tag + " +]") + "[+ ENDFOR +]" # -# Handle best matched values for a platform, for example: +# Template for handling best matched values for a platform, for example: # # module = { # cflags = '-Wall'; @@ -541,21 +183,34 @@ def foreach_value(defn, tag, closure): # ... # } # -def foreach_platform_specific_value(defn, platform, suffix, nonetag, closure): - r = [] +def foreach_platform_specific_value(platform, suffix, nonetag, closure): + r = "" for group in RMAP[platform]: - 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) + 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 # -# Handle values from sum of all groups for a platform, for example: +# 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: # # module = { # common = kern/misc.c; @@ -563,20 +218,18 @@ def foreach_platform_specific_value(defn, platform, suffix, nonetag, closure): # ... # } # -def foreach_platform_value(defn, platform, suffix, closure): - r = [] +def foreach_platform_value (platform, suffix, closure): + r = "" for group in RMAP[platform]: - for value in defn.find_all(group + suffix): - r.append(closure(value)) - return ''.join(r) + gtag = group + suffix -def platform_conditional(platform, closure): - output("\nif COND_" + platform + "\n") - closure(platform) - output("endif\n") + r += "[+ IF " + gtag + " +]" + r += "[+ FOR " + gtag + " +]" + closure("[+ ." + gtag + " +]") + "[+ ENDFOR +]" + r += "[+ ENDIF +]" + return r # -# Handle guarding with platform-specific "enable" keys, for example: +# Template for gaurding with platform specific "enable" keys, for example: # # module = { # name = pci; @@ -591,17 +244,20 @@ def platform_conditional(platform, closure): # enable = i386_coreboot; # }; # -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) +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 # -# Handle guarding with platform-specific automake conditionals, for example: +# Template for gaurding with platform specific automake conditionals, +# for example: # # module = { # name = usb; @@ -611,298 +267,352 @@ def foreach_enabled_platform(defn, closure): # enable = emu; # enable = i386; # enable = mips_loongson; -# emu_condition = COND_GRUB_EMU_SDL; +# emu_condition = COND_GRUB_EMU_USB; # }; # -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 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 platform_specific_values(defn, platform, suffix, nonetag): - return foreach_platform_specific_value(defn, platform, suffix, nonetag, +def platform_specific_values(platform, suffix, nonetag): + return foreach_platform_specific_value(platform, suffix, nonetag, lambda value: value + " ") -def platform_values(defn, platform, suffix): - return foreach_platform_value(defn, platform, suffix, lambda value: value + " ") +def platform_values(platform, suffix): + return foreach_platform_value(platform, suffix, lambda value: value + " ") -def extra_dist(defn): - return foreach_value(defn, "extra_dist", lambda value: value + " ") +def extra_dist(): + return foreach_value("extra_dist", lambda value: value + " ") -def platform_sources(defn, p): return platform_values(defn, p, "") -def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist") +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 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") +# +# 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 +]" # # Emit snippet only the first time through for the current name. # -seen_target = set() +def first_time(snippet): + r = "[+ IF (if (not (assoc-ref seen-target (get \".name\"))) \"seen\") +]" + r += snippet + r += "[+ ENDIF +]" + return r -def first_time(defn, snippet): - if defn['name'] not in seen_target: - return snippet - return '' +def module(platform): + r = set_canonical_name_suffix(".module") -def is_platform_independent(defn): - if 'enable' in defn: - return False - for suffix in [ "", "_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 += gvar_add("platform_PROGRAMS", "[+ name +].module") + r += gvar_add("MODULE_FILES", "[+ name +].module$(EXEEXT)") - 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 += 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)) - return True + r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") -def module(defn, platform): - name = defn['name'] - set_canonical_name_suffix(".module") - - gvar_add("platform_PROGRAMS", name + ".module") - gvar_add("MODULE_FILES", name + ".module$(EXEEXT)") - - 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)) - - 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") - 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) + 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 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)") +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("dist_noinst_DATA", extra_dist(defn)) - gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)") - gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)") + r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_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 $< $@; \ + 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 $< $@; \ elif test ! -z '$(TARGET_OBJ2ELF)'; then \ - $(TARGET_OBJ2ELF) $< $@ || (rm -f $@; exit 1); \ + cp $< $@.bin; $(TARGET_OBJ2ELF) $@.bin && cp $@.bin $@ || (rm -f $@.bin; exit 1); \ else cp $< $@; fi""", -"""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 $@ $<; \ +"""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 $@ $<; \ fi""")) + return r -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)) +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)) - 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("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") - 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 \ + 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 \ $(MACHO2IMG) $< $@; \ else \ - $(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 $< $@; \ + $(OBJCOPY) $(""" + cname() + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ fi """) + return r -def library(defn, platform): - name = defn['name'] - set_canonical_name_suffix("") +def library(platform): + r = set_canonical_name_suffix("") - vars_init(defn, - cname(defn) + "_SOURCES", - "nodist_" + cname(defn) + "_SOURCES", - cname(defn) + "_CFLAGS", - cname(defn) + "_CPPFLAGS", - cname(defn) + "_CCASFLAGS") - # cname(defn) + "_DEPENDENCIES") + r += vars_init(cname() + "_SOURCES", + "nodist_" + cname() + "_SOURCES", + cname() + "_CFLAGS", + cname() + "_CPPFLAGS", + cname() + "_CCASFLAGS") + # cname() + "_DEPENDENCIES") - 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 += 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)) - 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)") + 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 -def installdir(defn, default="bin"): - return defn.get('installdir', default) +def installdir(default="bin"): + return "[+ IF installdir +][+ installdir +][+ ELSE +]" + default + "[+ ENDIF +]" -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 + """ +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 +] """) - gvar_add("CLEANFILES", name + "." + mansection) - output("endif\n") + r += gvar_add("CLEANFILES", "[+ name +].[+ mansection +]") + r += "endif\n" + return r -def program(defn, platform, test=False): - name = defn['name'] - set_canonical_name_suffix("") +def program(platform, test=False): + r = set_canonical_name_suffix("") - if 'testcase' in defn: - gvar_add("check_PROGRAMS", name) - gvar_add("TESTS", name) - else: - var_add(installdir(defn) + "_PROGRAMS", name) - if 'mansection' in defn: - manpage(defn, "") + 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 +]" - 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 += 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)) - 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("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + 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 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 transform_data(defn, platform): - name = defn['name'] +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 +]" - 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 += rule("[+ name +]", platform_sources(platform) + " $(top_builddir)/config.status", """ +$(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 script(defn, platform): - name = defn['name'] - - if 'testcase' in defn: - gvar_add("check_SCRIPTS", name) - gvar_add ("TESTS", 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)) + r += gvar_add("CLEANFILES", "[+ name +]") + r += gvar_add("dist_noinst_DATA", platform_sources(platform)) + return r def rules(target, closure): - seen_target.clear() - seen_vars.clear() + # 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) +]" - 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']) + 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 -parser = OptionParser(usage="%prog DEFINITION-FILES") -_, args = parser.parse_args() +def module_rules(): + return rules("module", module) -for arg in args: - defparser.read_definitions(arg) +def kernel_rules(): + return rules("kernel", kernel) -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 image_rules(): + return rules("image", image) -write_output(section='decl') -write_output() +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) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 3ea8e7ff4..7dc25197c 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -7,8 +7,12 @@ include $(top_srcdir)/conf/Makefile.common CC=$(TARGET_CC) CPP=$(TARGET_CC) CCAS=$(TARGET_CC) -RANLIB=$(TARGET_RANLIB) -STRIP=$(TARGET_STRIP) + +if COND_GRUB_MKFONT +if COND_HAVE_FONT_SOURCE +TARGET_CFLAGS += -DUSE_ASCII_FAILBACK=1 -DHAVE_UNIFONT_WIDTHSPEC=1 +endif +endif MACHO2IMG=$(top_builddir)/grub-macho2img @@ -26,28 +30,25 @@ 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$(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) +gentrigtables: gentrigtables.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) $< -lm +CLEANFILES += gentrigtables # trigtables.c -trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac - ./gentrigtables$(BUILD_EXEEXT) > $@ +trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac + $(builddir)/gentrigtables > $@ 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 $< @@ -59,9 +60,12 @@ 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.h: $(srcdir)/lib/reed_solomon.c +rs_decoder.S: $(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 @@ -80,11 +84,6 @@ 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/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 @@ -92,102 +91,56 @@ 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/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/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 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.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/tsc.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.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_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 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_multiboot -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 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_qemu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.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/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/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 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.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/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.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 @@ -197,12 +150,18 @@ 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 @@ -214,10 +173,12 @@ 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 @@ -249,63 +210,16 @@ 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_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/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/export.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 +endif if COND_GRUB_EMU_PCI KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h endif @@ -321,7 +235,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 | $(SHELL) $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1) + cat symlist.p | /bin/sh $(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 @@ -349,12 +263,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 $(MODULE_FILES) - rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@ +grub_emu_init.h: genemuinitheader.sh $(MOD_FILES) + rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(NM) > $@ CLEANFILES += grub_emu_init.h -grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES) - rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@ +grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES) + rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(NM) > $@ CLEANFILES += grub_emu_init.c endif @@ -401,16 +315,6 @@ 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`; \ @@ -445,11 +349,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 -$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT) +$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ platform_DATA += $(MOD_FILES) platform_DATA += modinfo.sh @@ -457,44 +361,43 @@ CLEANFILES += $(MOD_FILES) if COND_ENABLE_EFIEMU efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) - -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 \ - mv $@.bin $@ ; \ - fi - -# Link format -arch,x86_64 means Apple linker -efiemu64_c.o: efiemu/runtime/efiemu.c - $(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 - $(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 $@ - -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 $@; \ + 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; \ else \ - mv $@.bin $@ ; \ + $(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; \ + fi + +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 + +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 + +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 $@.bin; \ + else \ + $(TARGET_CC) -m64 -nostdlib -Wl,-r -o $@ $^ || exit 1; \ + if test ! -z "$(TARGET_OBJ2ELF)"; then $(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi; \ 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 b5f47fc41..39e77a450 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1,49 +1,35 @@ AutoGen definitions Makefile.tpl; -transform_data = { +script = { installdir = noinst; name = gensyminfo.sh; common = gensyminfo.sh.in; }; -transform_data = { +script = { installdir = noinst; name = genmod.sh; common = genmod.sh.in; }; -transform_data = { +script = { installdir = noinst; name = modinfo.sh; common = modinfo.sh.in; }; -transform_data = { +script = { installdir = platform; name = gmodule.pl; common = gmodule.pl.in; }; -transform_data = { +script = { 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; @@ -59,56 +45,31 @@ kernel = { ia64_efi_ldflags = '-Wl,-r,-d'; ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - arm_efi_ldflags = '-Wl,-r,-d'; - arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - - arm64_efi_ldflags = '-Wl,-r,-d'; - arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; - - riscv32_efi_ldflags = '-Wl,-r,-d'; - riscv32_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; - - riscv64_efi_ldflags = '-Wl,-r,-d'; - 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),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'; + i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; + + 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,$(TARGET_LINK_ADDR)'; + mips_arc_ldflags = '-Wl,-Ttext,0x8bd00000'; mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; - mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + mips_loongson_cppflags = '-DUSE_ASCII_FAILBACK'; 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,-d'; - arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - arm_coreboot_ldflags = '-Wl,-r,-d'; - 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; @@ -116,12 +77,6 @@ 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; - riscv32_efi_startup = kern/riscv/efi/startup.S; - riscv64_efi_startup = kern/riscv/efi/startup.S; common = kern/command.c; common = kern/corecmd.c; @@ -141,13 +96,13 @@ kernel = { common = kern/rescue_reader.c; common = kern/term.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; @@ -158,122 +113,57 @@ 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 = kern/i386/coreboot/init.c; - i386_multiboot = kern/i386/coreboot/init.c; - i386_qemu = kern/i386/qemu/init.c; + i386_coreboot_multiboot_qemu = kern/i386/coreboot/init.c; i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; - coreboot = video/coreboot/cbfb.c; + + i386_coreboot_multiboot_qemu = term/i386/vga_common.c; + i386_pc = term/i386/vga_common.c; + + x86 = kern/i386/pit.c; efi = disk/efi/efidisk.c; efi = kern/efi/efi.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; - 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 = kern/x86_64/dl.c; - x86_64_xen = kern/x86_64/dl.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_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; - - 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; - 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_coreboot = kern/i386/coreboot/mmap.c; + i386_coreboot = kern/i386/tsc.c; i386_multiboot = kern/i386/multiboot_mmap.c; + i386_multiboot = kern/i386/tsc.c; mips = kern/mips/cache.S; mips = kern/mips/dl.c; @@ -283,10 +173,9 @@ 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; @@ -299,55 +188,26 @@ 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; - - 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; @@ -355,31 +215,23 @@ kernel = { emu = kern/emu/mm.c; emu = kern/emu/time.c; emu = kern/emu/cache.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; + emu = term/emu/console.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; @@ -393,9 +245,9 @@ program = { emu = kern/emu/full.c; emu_nodist = grub_emu_init.c; - ldadd = 'kernel.exec$(EXEEXT)'; + ldadd = 'kernel.img$(EXEEXT)'; ldadd = '$(MODULE_FILES)'; - ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; enable = emu; }; @@ -406,8 +258,8 @@ program = { emu = kern/emu/lite.c; emu_nodist = symlist.c; - ldadd = 'kernel.exec$(EXEEXT)'; - ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = 'kernel.img$(EXEEXT)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; enable = emu; }; @@ -425,14 +277,8 @@ 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)'; - /* 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'; + sparc64_ieee1275_objcopyflags = '-O a.out-sunos-big'; + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x4000'; objcopyflags = '-O binary'; enable = i386_pc; @@ -440,36 +286,12 @@ 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; }; @@ -519,13 +341,15 @@ image = { 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_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; - cflags = '-Wno-unreachable-code'; + 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'; enable = mips; }; @@ -537,14 +361,17 @@ image = { cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1'; objcopyflags = '-O binary'; - mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + 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'; 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'; @@ -555,7 +382,7 @@ image = { name = fwstart; mips_loongson = boot/mips/loongson/fwstart.S; objcopyflags = '-O binary'; - ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; enable = mips_loongson; }; @@ -563,16 +390,10 @@ image = { name = fwstart_fuloong2f; mips_loongson = boot/mips/loongson/fuloong2f.S; objcopyflags = '-O binary'; - ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + ldflags = '-static-libgcc -lgcc -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; @@ -585,6 +406,13 @@ 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; @@ -599,6 +427,12 @@ 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; @@ -617,16 +451,10 @@ 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 = pci; + enable = x86; }; module = { @@ -638,16 +466,12 @@ 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; @@ -655,21 +479,11 @@ 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; }; @@ -680,11 +494,11 @@ module = { enable = mips_arc; }; -module = { - name = lsxen; - common = commands/xen/lsxen.c; - - enable = xen; +library = { + name = libgnulib.a; + common = gnulib/regex.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; }; module = { @@ -693,53 +507,17 @@ module = { enable = cmos; }; -module = { - name = cmosdump; - common = commands/i386/cmosdump.c; - enable = cmos; -}; - module = { name = iorw; common = commands/iorw.c; 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; - common = lib/gnulib/regex.c; + ldadd = libgnulib.a; cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; }; @@ -748,8 +526,10 @@ module = { name = acpi; common = commands/acpi.c; - i386_pc = kern/acpi.c; - i386_pc = kern/i386/pc/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; enable = efi; enable = i386_pc; @@ -792,18 +572,6 @@ 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 = blocklist; common = commands/blocklist.c; @@ -813,18 +581,7 @@ module = { name = boot; common = commands/boot.c; i386_pc = lib/i386/pc/biosnum.c; - 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 = riscv32_efi; - enable = riscv64_efi; + enable = videomodules; }; module = { @@ -844,11 +601,8 @@ module = { module = { name = cpuid; - common = commands/i386/cpuid.c; + x86 = commands/i386/cpuid.c; enable = x86; - enable = i386_xen_pvh; - enable = i386_xen; - enable = x86_64_xen; }; module = { @@ -869,11 +623,6 @@ module = { common = commands/echo.c; }; -module = { - name = eval; - common = commands/eval.c; -}; - module = { name = extcmd; common = commands/extcmd.c; @@ -905,28 +654,22 @@ 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; }; @@ -935,27 +678,10 @@ module = { common = commands/hashsum.c; }; -module = { - name = pgp; - common = commands/pgp.c; - cflags = '$(CFLAGS_POSIX)'; - cppflags = '-I$(srcdir)/lib/posix_wrap'; -}; - -module = { - name = verifiers; - common = commands/verifiers.c; -}; - -module = { - name = shim_lock; - common = commands/efi/shim_lock.c; - enable = efi; -}; - module = { name = hdparm; common = commands/hdparm.c; + common = lib/hexdump.c; enable = pci; enable = mips_qemu_mips; }; @@ -1037,18 +763,6 @@ 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; @@ -1086,32 +800,11 @@ 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; @@ -1176,27 +869,10 @@ module = { common = disk/cryptodisk.c; }; -module = { - name = json; - common = lib/json/json.c; -}; - -module = { - name = afsplitter; - common = disk/AFSplitter.c; -}; - module = { name = luks; common = disk/luks.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'; + common = disk/AFSplitter.c; }; module = { @@ -1331,11 +1007,6 @@ module = { enable = videomodules; }; -module = { - name = procfs; - common = fs/proc.c; -}; - module = { name = affs; common = fs/affs.c; @@ -1351,37 +1022,12 @@ 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 -I$(srcdir)/lib/zstd -DMINILZO_HAVE_CONFIG_H'; -}; - -module = { - name = archelp; - common = fs/archelp.c; -}; - -module = { - name = cbfs; - common = fs/cbfs.c; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; }; module = { @@ -1419,11 +1065,6 @@ module = { common = fs/exfat.c; }; -module = { - name = f2fs; - common = fs/f2fs.c; -}; - module = { name = fshelp; common = fs/fshelp.c; @@ -1439,11 +1080,6 @@ module = { common = fs/hfsplus.c; }; -module = { - name = hfspluscomp; - common = fs/hfspluscomp.c; -}; - module = { name = iso9660; common = fs/iso9660.c; @@ -1536,11 +1172,6 @@ module = { common = fs/ufs.c; }; -module = { - name = ufs1_be; - common = fs/ufs_be.c; -}; - module = { name = ufs2; common = fs/ufs2.c; @@ -1555,7 +1186,6 @@ 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; }; @@ -1570,11 +1200,6 @@ module = { common = fs/zfs/zfsinfo.c; }; -module = { - name = macbless; - common = commands/macbless.c; -}; - module = { name = pxe; i386_pc = net/drivers/i386/pc/pxe.c; @@ -1589,6 +1214,7 @@ 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; @@ -1615,11 +1241,6 @@ module = { common = io/gzio.c; }; -module = { - name = offsetio; - common = io/offset.c; -}; - module = { name = bufio; common = io/bufio.c; @@ -1629,8 +1250,6 @@ module = { module = { name = elf; common = kern/elf.c; - - extra_dist = kern/elfXX.c; }; module = { @@ -1651,29 +1270,15 @@ 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; @@ -1681,25 +1286,19 @@ 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 = { @@ -1712,9 +1311,6 @@ 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; }; module = { @@ -1744,8 +1340,9 @@ module = { module = { name = linux16; - common = loader/i386/pc/linux.c; - enable = x86; + i386_pc = loader/i386/pc/linux.c; + i386_pc = lib/cmdline.c; + enable = i386_pc; }; module = { @@ -1754,14 +1351,6 @@ 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; @@ -1781,7 +1370,6 @@ module = { common = loader/multiboot.c; common = loader/multiboot_mbi2.c; enable = x86; - enable = i386_xen_pvh; enable = mips; }; @@ -1789,89 +1377,34 @@ 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/arm64/linux.c; - arm_uboot = loader/arm/linux.c; - arm64 = loader/arm64/linux.c; - riscv32 = loader/riscv/linux.c; - riscv64 = loader/riscv/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 = { @@ -1886,7 +1419,6 @@ 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; @@ -1897,8 +1429,6 @@ 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; @@ -1908,12 +1438,7 @@ module = { mips = mmap/mips/uppermem.c; enable = x86; - enable = i386_xen_pvh; enable = ia64_efi; - enable = arm_efi; - enable = arm64_efi; - enable = riscv32_efi; - enable = riscv64_efi; enable = mips; }; @@ -1926,6 +1451,7 @@ 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; @@ -1934,7 +1460,6 @@ 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; @@ -2008,11 +1533,6 @@ module = { common = partmap/sunpc.c; }; -module = { - name = part_dfly; - common = partmap/dfly.c; -}; - module = { name = msdospart; common = parttool/msdospart.c; @@ -2021,7 +1541,6 @@ module = { module = { name = at_keyboard; common = term/at_keyboard.c; - common = term/ps2.c; enable = x86; }; @@ -2031,22 +1550,15 @@ module = { enable = videomodules; }; -module = { - name = gfxterm_background; - common = term/gfxterm_background.c; -}; - module = { name = serial; common = term/serial.c; x86 = term/ns8250.c; ieee1275 = term/ieee1275/serial.c; - mips_arc = term/arc/serial.c; efi = term/efi/serial.c; enable = terminfomodule; enable = ieee1275; - enable = mips_arc; }; module = { @@ -2072,21 +1584,17 @@ 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; @@ -2103,10 +1611,6 @@ 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 = { @@ -2114,107 +1618,16 @@ 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 = { @@ -2249,6 +1662,8 @@ module = { name = vbe; common = video/i386/pc/vbe.c; enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; }; module = { @@ -2263,12 +1678,8 @@ module = { module = { name = video; common = video/video.c; - enable = videomodules; -}; - -module = { - name = video_colors; common = video/colors.c; + enable = videomodules; }; module = { @@ -2320,12 +1731,6 @@ module = { enable = ieee1275; }; -module = { - name = ubootnet; - common = net/drivers/uboot/ubootnet.c; - enable = uboot; -}; - module = { name = efinet; common = net/drivers/efi/efinet.c; @@ -2343,22 +1748,8 @@ 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 = { @@ -2392,14 +1783,8 @@ 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 = { @@ -2411,7 +1796,7 @@ module = { module = { name = keylayouts; common = commands/keylayouts.c; - enable = x86; + enable = videomodules; }; module = { @@ -2430,12 +1815,6 @@ 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; @@ -2446,36 +1825,6 @@ 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; @@ -2491,46 +1840,3 @@ 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 = 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; -}; diff --git a/grub-core/boot/decompressor/minilib.c b/grub-core/boot/decompressor/minilib.c index fc46ee07b..94edfd561 100644 --- a/grub-core/boot/decompressor/minilib.c +++ b/grub-core/boot/decompressor/minilib.c @@ -21,7 +21,7 @@ #include void * -grub_memset (void *s, int c, grub_size_t len) +memset (void *s, int c, grub_size_t len) { grub_uint8_t *ptr; for (ptr = s; len; ptr++, len--) @@ -68,6 +68,15 @@ 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 2bd0b2d28..314f14016 100644 --- a/grub-core/boot/i386/pc/boot.S +++ b/grub-core/boot/i386/pc/boot.S @@ -28,86 +28,6 @@ #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 @@ -131,66 +51,47 @@ 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. */ - .org GRUB_BOOT_MACHINE_BPB_START - .org 4 -#endif -#ifdef HYBRID_BOOT - floppy -#else - scratch -#endif + . = _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_END /* * End of BIOS parameter block. */ -LOCAL(kernel_address): +kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR -#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_KERNEL_SECTOR +kernel_sector: + .long 1, 0 - .org GRUB_BOOT_MACHINE_BOOT_DRIVE + . = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE boot_drive: .byte 0xff /* the disk to load kernel from */ /* 0xff means use the boot drive */ @@ -208,7 +109,7 @@ LOCAL(after_BPB): * possible boot drive. If GRUB is installed into a floppy, * this does nothing (only jump). */ - .org GRUB_BOOT_MACHINE_DRIVE_CHECK + . = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK boot_drive_check: jmp 3f /* grub-setup may overwrite this jump */ testb $0x80, %dl @@ -275,7 +176,7 @@ real_start: andw $1, %cx jz LOCAL(chs_mode) -LOCAL(lba_mode): +lba_mode: xorw %ax, %ax movw %ax, 4(%si) @@ -290,9 +191,9 @@ LOCAL(lba_mode): movw $0x0010, (%si) /* the absolute address */ - movl LOCAL(kernel_sector), %ebx + movl kernel_sector, %ebx movl %ebx, 8(%si) - movl LOCAL(kernel_sector_high), %ebx + movl kernel_sector + 4, %ebx movl %ebx, 12(%si) /* the segment of buffer address */ @@ -325,12 +226,11 @@ LOCAL(chs_mode): int $0x13 jnc LOCAL(final_init) - popw %dx /* * The call failed, so maybe use the floppy probe instead. */ - testb %dl, %dl - jnb LOCAL(floppy_probe) + testb $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl + jz LOCAL(floppy_probe) /* Nope, we definitely have a hard disk, and we're screwed. */ ERR(hd_probe_error_string) @@ -361,13 +261,13 @@ LOCAL(final_init): setup_sectors: /* load logical sector start (top half) */ - movl LOCAL(kernel_sector_high), %eax + movl kernel_sector + 4, %eax orl %eax, %eax jnz LOCAL(geometry_error) /* load logical sector start (bottom half) */ - movl LOCAL(kernel_sector), %eax + movl kernel_sector, %eax /* zero %edx */ xorl %edx, %edx @@ -452,7 +352,7 @@ LOCAL(copy_buffer): popa /* boot kernel */ - jmp *(LOCAL(kernel_address)) + jmp *(kernel_address) /* END OF MAIN LOOP */ @@ -510,14 +410,7 @@ LOCAL(message): * number here. */ -#ifdef HYBRID_BOOT - .org 0x1b0 -LOCAL(kernel_sector): - .long 1 -LOCAL(kernel_sector_high): - .long 0 -#endif - .org GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC + . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC nt_magic: .long 0 .word 0 @@ -526,17 +419,62 @@ 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? - */ + */ - .org GRUB_BOOT_MACHINE_PART_START + . = _start + GRUB_BOOT_MACHINE_PART_START +part_start: -#ifndef HYBRID_BOOT - floppy -#else - scratch -#endif +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 - .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 de4f80929..d939835a9 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 - .org 8 + . = start + 8 bi_pvd: .long 0 /* LBA of primary volume descriptor. */ @@ -93,12 +93,11 @@ LOCAL(read_cdrom): pushw $CDBLK_LENG /* Block number. */ - incl %esi pushl %eax pushl %esi /* Buffer address. */ - pushw $((DATA_ADDR - 0x200)>> 4) + pushw $((DATA_ADDR - 0x400)>> 4) pushl %eax pushw $0x10 @@ -168,6 +167,6 @@ err_noboot_msg: err_cdfail_msg: .ascii "cdrom read fails\0" - .org 0x7FF + . = start + 0x1FF .byte 0 diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S index c1addc0df..d030a14c9 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 0x8000 and is jumped to with - * CS:IP 0:0x8000 in kernel. + * _start is loaded at 0x2000 and is jumped to with + * CS:IP 0:0x2000 in kernel. */ /* @@ -362,7 +362,7 @@ LOCAL(message): .word 0 .word 0 - .org 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE + . = _start + 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 2dda0e06b..e4bc8b425 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) - .org 0x1F1 + . = data_start + 0x1F1 setup_sects: .byte CODE_SECTORS @@ -207,10 +207,6 @@ 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 @@ -292,4 +288,4 @@ LOCAL(fail): err_int15_msg: .ascii "move memory fails\0" - .org (CODE_SECTORS * 512 + 512) + . = _start + CODE_SECTORS * 512 diff --git a/grub-core/boot/i386/pc/pxeboot.S b/grub-core/boot/i386/pc/pxeboot.S index b695b24d0..446bfc781 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. */ - .org 0x8200 - 0x7C00 - 0x200 - 1 + . = _start + 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 28974821e..81c0bc457 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. */ - .org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE LOCAL(compressed_size): .long 0 - .org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE LOCAL(uncompressed_size): .long 0 - .org GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY + . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY reed_solomon_redundancy: .long 0 - .org GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH + . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH .short (LOCAL(reed_solomon_part) - _start) /* * This is the area for all of the special variables. */ - .org GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + . = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE LOCAL(boot_dev): .byte 0xFF, 0xFF, 0xFF LOCAL(boot_drive): @@ -89,17 +89,18 @@ LOCAL (codestart): sti /* we're safe again */ /* save the boot drive */ - movb %dl, LOCAL(boot_drive) + ADDR32 movb %dl, LOCAL(boot_drive) /* reset disk system (%ah = 0) */ int $0x13 /* transition to protected mode */ - calll real_to_prot + DATA32 call real_to_prot /* The ".code32" directive takes GAS out of 16-bit mode. */ .code32 + incl %eax cld call grub_gate_a20 @@ -118,21 +119,12 @@ LOCAL (codestart): #include "../../../kern/i386/realmode.S" -/* - * - * 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 +#include .text /* - * grub_gate_a20(void) + * grub_gate_a20(int on) * * Gate address-line 20 for high memory. * @@ -142,10 +134,12 @@ 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 - testb %al, %al + cmpb %al, %dl jnz gate_a20_try_bios ret @@ -155,15 +149,18 @@ gate_a20_try_bios: call prot_to_real .code16 - movw $0x2401, %ax - int $0x15 + movw $0x2400, %ax + testb %dl, %dl + jz 1f + incw %ax +1: int $0x15 - calll real_to_prot + DATA32 call real_to_prot .code32 popl %ebp call gate_a20_check_state - testb %al, %al + cmpb %al, %dl jnz gate_a20_try_system_control_port_a ret @@ -175,13 +172,20 @@ 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 - outb $0x92 +6: 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 - testb %al, %al + cmpb %al, %dl jnz gate_a20_try_keyboard_controller - ret +7: ret gate_a20_flush_keyboard_buffer: inb $0x64 @@ -207,8 +211,11 @@ gate_a20_try_keyboard_controller: andb $0x02, %al jnz 4b - movb $0xdf, %al - outb $0x60 + movb $0xdd, %al + testb %dl, %dl + jz 5f + orb $0x02, %al +5: outb $0x60 call gate_a20_flush_keyboard_buffer /* output a dummy command (USB keyboard hack) */ @@ -217,7 +224,7 @@ gate_a20_try_keyboard_controller: call gate_a20_flush_keyboard_buffer call gate_a20_check_state - testb %al, %al + cmpb %al, %dl /* everything failed, so restart from the beginning */ jnz gate_a20_try_bios ret @@ -227,7 +234,7 @@ gate_a20_check_state: movl $100, %ecx 1: call 3f - testb %al, %al + cmpb %al, %dl jz 2f loop 1b 2: @@ -256,8 +263,9 @@ gate_a20_check_state: pushl %ebx addl $0x100000, %ebx movb (%ebx), %ch - /* this result is 0 if A20 is on or 1 if it is off */ + /* this result is 1 if A20 is on or 0 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 8c3a1db71..97aeab9e6 100644 --- a/grub-core/boot/i386/qemu/boot.S +++ b/grub-core/boot/i386/qemu/boot.S @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,7 @@ _start: jmp 1f - .org GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR + . = _start + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR VARIABLE(grub_core_entry_addr) .long 0 1: @@ -48,17 +49,10 @@ VARIABLE(grub_core_entry_addr) /* Transition to protected mode. We use pushl to force generation of a flat return address. */ pushl $1f - jmp real_to_prot + DATA32 jmp real_to_prot .code32 1: - /* 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 + movl grub_core_entry_addr, %edx jmp *%edx #include "../../../kern/i386/realmode.S" @@ -66,9 +60,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. */ - .org GRUB_BOOT_MACHINE_SIZE - 16 + . = GRUB_BOOT_MACHINE_SIZE - 16 .code16 jmp _start - .org GRUB_BOOT_MACHINE_SIZE + . = GRUB_BOOT_MACHINE_SIZE diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index 28c634614..ec57be6a1 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_2F) - lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE_2F) + lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) + lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) 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_2F) - 1) + andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 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_2F) ($t0) - lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_PCI_REG_PCI_ID) ($t1) + 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 @@ -86,9 +86,9 @@ retry_cs5536: move $a0, $t4 #endif - lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE_2F) + lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED - sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0) + sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + 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_2F + GRUB_CS5536_LBAR_SMBUS) + lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS) /* Disable SMB. */ - sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) /* Disable interrupts. */ - sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0) + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0) /* Set as master. */ - sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0) + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + 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_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) + 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) /* Yeeloong and Fuloong2f have only one memory slot. */ /* Output first byte on serial for debugging. */ @@ -162,7 +162,7 @@ retry_cs5536: b continue - .org GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START + . = start + 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) - .org GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START + . = start + 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) - .org GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START + . = start + 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_2F + GRUB_CS5536_LBAR_GPIO) - addiu $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_GPIO) + 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 $t1, %hi (gpio_dump) addiu $t1, $t1, %lo (gpio_dump) @@ -344,7 +344,7 @@ printhex: nop srl $t1, $a0, 28 addiu $t1, $t1, -10 - bltz $t1, 2f + blt $t1, $zero, 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_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) + 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) jr $ra - sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0) + sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + 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_2F) - lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) + 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) 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, %lo(read_spd_fail) + addiu $a0, $a0, %hi(read_spd_fail) /* Send START. */ - 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) + 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) 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_2F) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send device address. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) sll $t1, $a1, 1 bal smbus_wait - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send ACK. */ - 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) + 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) 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_2F) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send byte address. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) bal smbus_wait - sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) + sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send START. */ - 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) + 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) 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_2F) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send device address. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) 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_2F) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) /* Send STOP. */ - 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) + 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) 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_2F) ($t0) + sb $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_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) + 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) jr $t3 andi $v0, $v0, 0xff read_spd_fail: @@ -547,7 +547,7 @@ gpio_dump: #endif gpio_dump_end: - .p2align 3 + .p2align write_dumpreg: ld $t2, 0($t6) @@ -754,3 +754,140 @@ 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 6a81b3733..bbbc1dbec 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -22,13 +22,11 @@ #include #include #include -#include #define BASE_ADDR 8 .extern __bss_start .extern _end -.extern _edata .globl __start, _start, start .set noreorder @@ -40,13 +38,13 @@ start: bal codestart nop base: - .org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE compressed_size: .long 0 - .org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE uncompressed_size: .long 0 - .org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR uncompressed_addr: .long 0 codestart: @@ -119,50 +117,50 @@ parsestr: move $v0, $zero move $t3, $t1 3: - lb GRUB_ASM_T4, 0($t2) - lb GRUB_ASM_T5, 0($t3) + lb $t4, 0($t2) + lb $t5, 0($t3) addiu $t2, $t2, 1 addiu $t3, $t3, 1 - beq GRUB_ASM_T5, $zero, 1f + beq $t5, $zero, 1f nop - beq GRUB_ASM_T5, GRUB_ASM_T4, 3b + beq $t5, $t4, 3b nop - bne GRUB_ASM_T4, $zero, 1f + bne $t4, $zero, 1f nop addiu $t3, $t3, 0xffff digcont: - lb GRUB_ASM_T5, 0($t3) + lb $t5, 0($t3) /* Substract '0' from digit. */ - addiu GRUB_ASM_T5, GRUB_ASM_T5, 0xffd0 - bltz GRUB_ASM_T5, 1f + addiu $t5, $t5, 0xffd0 + bltz $t5, 1f nop - addiu GRUB_ASM_T4, GRUB_ASM_T5, 0xfff7 - bgtz GRUB_ASM_T4, 1f + addiu $t4, $t5, 0xfff7 + bgtz $t4, 1f nop /* Multiply $v0 by 10 with bitshifts. */ sll $v0, $v0, 1 - sll GRUB_ASM_T4, $v0, 2 - addu $v0, $v0, GRUB_ASM_T4 - addu $v0, $v0, GRUB_ASM_T5 + sll $t4, $v0, 2 + addu $v0, $v0, $t4 + addu $v0, $v0, $t5 addiu $t3, $t3, 1 b digcont nop 1: jr $ra nop -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" +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" .p2align 2 argdone: @@ -183,10 +181,10 @@ argdone: b argdone addiu $a1, $a1, 4 do_check: - lb GRUB_ASM_T4, 0($t7) - beq GRUB_ASM_T4, $zero, 1f + lb $t4, 0($t7) + beq $t4, $zero, 1f lb $t3, 0($t6) - bne $t3, GRUB_ASM_T4, 2f + bne $t3, $t4, 2f addiu $t6, $t6, 1 b do_check addiu $t7, $t7, 1 @@ -198,21 +196,6 @@ 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) @@ -223,8 +206,8 @@ cmdlinedone: 1: beq $t1, $t3, 2f - lb GRUB_ASM_T4, 0($t2) - sb GRUB_ASM_T4, 0($t1) + lb $t4, 0($t2) + sb $t4, 0($t1) addiu $t1, $t1, 1 b 1b addiu $t2, $t2, 1 @@ -250,9 +233,8 @@ cmdlinedone: #include "../../kern/mips/cache_flush.S" /* Decompress the payload. */ - lui $a0, %hi(_edata) - addiu $a0, $a0, %lo(_edata) - + lui $a0, %hi(__bss_start) + addiu $a0, $a0, %lo(__bss_start) lui $t0, %hi(base) addiu $t0, $t0, %lo(base) subu $a0, $a0, $t0 @@ -268,18 +250,13 @@ cmdlinedone: */ move $s6, $a3 - lui $t9, %hi(EXT_C(grub_decompress_core)) - addiu $t9, $t9, %lo(EXT_C(grub_decompress_core)) + lui $t0, %hi(EXT_C(grub_decompress_core)) + addiu $t0, $t0, %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 $t9 + jalr $t0 addiu $sp, $sp, %lo(_start - 256) -#endif + move $a0, $s1 move $a1, $s6 @@ -290,11 +267,3 @@ 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 deleted file mode 100644 index bc831daa9..000000000 --- a/grub-core/boot/powerpc/bootinfo.txt.in +++ /dev/null @@ -1,73 +0,0 @@ - -@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 deleted file mode 100644 index 9b2218352..000000000 --- a/grub-core/boot/powerpc/grub.chrp.in +++ /dev/null @@ -1,172 +0,0 @@ - - -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 ff8a79d3b..f79699502 100644 --- a/grub-core/boot/sparc64/ieee1275/boot.S +++ b/grub-core/boot/sparc64/ieee1275/boot.S @@ -21,24 +21,6 @@ .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 */ @@ -46,9 +28,8 @@ 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/sparc64/ieee1275/boot.h, + * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/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 @@ -58,27 +39,13 @@ 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. */ - .org GRUB_BOOT_MACHINE_BOOT_DEVPATH + GRUB_BOOT_AOUT_HEADER_SIZE + . = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH boot_path: - .org GRUB_BOOT_MACHINE_KERNEL_BYTE + GRUB_BOOT_AOUT_HEADER_SIZE + . = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE 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" @@ -91,10 +58,6 @@ 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 @@ -166,11 +129,7 @@ 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. @@ -199,10 +158,8 @@ 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) @@ -237,26 +194,13 @@ 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 -#endif - .org GRUB_BOOT_MACHINE_CODE_END + + . = _start + 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 35e02c1b6..e020f6221 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 - .org (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE) + . = _start + (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 9a63f073c..985608181 100644 --- a/grub-core/bus/bonito.c +++ b/grub-core/bus/bonito.c @@ -30,66 +30,8 @@ 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_2f (void) +write_bases (void) { int i; grub_uint32_t reg = 0; @@ -97,54 +39,38 @@ write_bases_2f (void) 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_2F = reg; + GRUB_MACHINE_PCI_IO_CTRL_REG = reg; } volatile void * grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), grub_addr_t base, grub_size_t size) { - if (grub_bonito_type == GRUB_BONITO_2F) - { - int i; - grub_addr_t newbase; + 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_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); - } + /* 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."); } void * @@ -160,17 +86,14 @@ grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), volatile void *mem, grub_size_t size __attribute__ ((unused))) { - 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"); - } + 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 bb9aa27e5..9e7796ea1 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -29,39 +29,28 @@ 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) { - struct grub_cs5536_find_ctx ctx = { - .devp = devp, - .found = 0 - }; + int found = 0; + auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, + grub_pci_id_t pciid); - grub_pci_iterate (grub_cs5536_find_iter, &ctx); + 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; + } - return ctx.found; + grub_pci_iterate (hook); + + return found; } grub_uint64_t diff --git a/grub-core/bus/emu/pci.c b/grub-core/bus/emu/pci.c index 267f2622d..d1beb561d 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, void *hook_data) +grub_pci_iterate (grub_pci_iteratefunc_t hook) { struct pci_device_iterator *iter; struct pci_slot_match slot; @@ -43,7 +43,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) 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_data); + hook (dev, dev->vendor_id | (dev->device_id << 16)); pci_iterator_destroy (iter); } @@ -55,8 +55,7 @@ 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%llx failed (error %d)", - (unsigned long long) base, err); + grub_util_error ("mapping 0x%x failed (error %d)\n", base, err); return addr; } @@ -67,12 +66,12 @@ grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem, pci_device_unmap_range (dev, mem, size); } -GRUB_MOD_INIT (emupci) +GRUB_MOD_INIT (pci) { pci_system_init (); } -GRUB_MOD_FINI (emupci) +GRUB_MOD_FINI (pci) { pci_system_cleanup (); } diff --git a/grub-core/bus/fdt.c b/grub-core/bus/fdt.c deleted file mode 100644 index 135da497b..000000000 --- a/grub-core/bus/fdt.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * 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 deleted file mode 100644 index 1fd3b5610..000000000 --- a/grub-core/bus/i386/ieee1275/pci.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 b388ce5c8..17dea30a1 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, void *hook_data) +grub_pci_iterate (grub_pci_iteratefunc_t hook) { grub_pci_device_t dev; grub_pci_address_t addr; @@ -125,7 +125,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) continue; } - if (hook (dev, id, hook_data)) + if (hook (dev, id)) return; /* Probe only func = 0 if the device if not multifunction */ diff --git a/grub-core/bus/spi/rk3288_spi.c b/grub-core/bus/spi/rk3288_spi.c deleted file mode 100644 index aacb79ffe..000000000 --- a/grub-core/bus/spi/rk3288_spi.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 deleted file mode 100644 index 29b50bdd5..000000000 --- a/grub-core/bus/usb/ehci-fdt.c +++ /dev/null @@ -1,45 +0,0 @@ -/* 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 deleted file mode 100644 index 65e6cb574..000000000 --- a/grub-core/bus/usb/ehci-pci.c +++ /dev/null @@ -1,208 +0,0 @@ -/* 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 d966fc210..b7005192b 100644 --- a/grub-core/bus/usb/ehci.c +++ b/grub-core/bus/usb/ehci.c @@ -22,11 +22,12 @@ #include #include #include +#include +#include +#include #include #include -#include -#include -#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -36,6 +37,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); * - is not supporting interrupt transfers */ +#define GRUB_EHCI_PCI_SBRN_REG 0x60 + /* Capability registers offsets */ enum { @@ -49,6 +52,7 @@ 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 */ @@ -79,6 +83,13 @@ 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 { @@ -325,21 +336,6 @@ 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) @@ -440,12 +436,9 @@ 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_CMD_HC_RESET + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); /* Ensure command is written */ grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); /* XXX: How long time could take reset of HC ? */ @@ -461,24 +454,102 @@ grub_ehci_reset (struct grub_ehci *e) } /* PCI iteration function... */ -void -grub_ehci_init_device (volatile void *regs) +static int NESTED_FUNC_ATTR +grub_ehci_pci_iter (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused))) { + 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; + return 1; e->framelist_chunk = NULL; e->td_chunk = NULL; e->qh_chunk = NULL; - e->iobase_ehcc = regs; + e->iobase_ehcc = grub_pci_device_map_range (dev, + (base & GRUB_EHCI_ADDR_MEM_MASK), + 0x100); + 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", @@ -494,7 +565,7 @@ grub_ehci_init_device (volatile void *regs) if (caplen & (sizeof (grub_uint32_t) - 1)) { grub_dprintf ("ehci", "Unaligned caplen\n"); - return; + return 0; } e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc + (caplen / sizeof (grub_uint32_t))); @@ -504,8 +575,8 @@ grub_ehci_init_device (volatile void *regs) #endif grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llxx\n", - (unsigned long long) (grub_addr_t) e->iobase_ehcc + caplen); + "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", + (base & GRUB_EHCI_ADDR_MEM_MASK) + 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", @@ -521,6 +592,10 @@ grub_ehci_init_device (volatile void *regs) 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 */ @@ -580,23 +655,23 @@ grub_ehci_init_device (volatile void *regs) 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_compile_time (GRUB_EHCI_TERMINATE); - e->td_virt[i].alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + 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[GRUB_EHCI_N_TD - 1].next_td = - grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td = - grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32 (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_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].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].td_overlay.alt_next_td = - grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); /* Also set Halted bit in token */ - e->qh_virt[0].td_overlay.token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); + e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); /* Set the H bit in first QH used for AL */ - e->qh_virt[1].ep_char = grub_cpu_to_le32_compile_time (GRUB_EHCI_H); + e->qh_virt[1].ep_char = grub_cpu_to_le32 (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 */ @@ -607,12 +682,12 @@ grub_ehci_init_device (volatile void *regs) e->qh_chunk) & GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH); e->qh_virt[i].td_overlay.next_td = - grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); e->qh_virt[i].td_overlay.alt_next_td = - grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); /* Also set Halted bit in token */ e->qh_virt[i].td_overlay.token = - grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); + grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); } /* Note: QH 0 and QH 1 are reserved and must not be used anywhere. @@ -624,6 +699,67 @@ grub_ehci_init_device (volatile void *regs) 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 */ @@ -655,7 +791,7 @@ grub_ehci_init_device (volatile void *regs) /* Set ownership of root hub ports to EHCI */ grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG, GRUB_EHCI_CF_EHCI_OWNER); - /* Enable both lists */ + /* Enable asynchronous list */ grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, GRUB_EHCI_CMD_AS_ENABL | GRUB_EHCI_CMD_PS_ENABL @@ -691,13 +827,11 @@ grub_ehci_init_device (volatile void *regs) 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: %08llx\n", - (unsigned long long) (grub_addr_t) regs); + "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", + (base & GRUB_EHCI_ADDR_MEM_MASK)); 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", @@ -713,7 +847,7 @@ grub_ehci_init_device (volatile void *regs) grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); - return; + return 0; fail: if (e) @@ -727,11 +861,11 @@ fail: } grub_free (e); - return; + return 0; } static int -grub_ehci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) +grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev)) { struct grub_ehci *e; struct grub_usb_controller dev; @@ -739,7 +873,7 @@ grub_ehci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) for (e = ehci; e; e = e->next) { dev.data = e; - if (hook (&dev, hook_data)) + if (hook (&dev)) return 1; } @@ -801,9 +935,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->split_hubport << GRUB_EHCI_DEVPORT_OFF) + ep_cap |= (transfer->dev->port << GRUB_EHCI_DEVPORT_OFF) & GRUB_EHCI_DEVPORT_MASK; - ep_cap |= (transfer->dev->split_hubaddr << GRUB_EHCI_HUBADDR_OFF) + ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF) & GRUB_EHCI_HUBADDR_MASK; if (transfer->dev->speed == GRUB_USB_SPEED_LOW && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) @@ -835,70 +969,28 @@ 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_compile_time (GRUB_EHCI_TARGET_MASK); + mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK); - /* 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 */ + /* First try to find existing QH with proper target */ + 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 */ + 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]; + } } - + /* 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. */ { @@ -913,6 +1005,14 @@ 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 */ @@ -975,7 +1075,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 transfer + /* Check state of TD - if it did not transfered * whole data then set last_trans - it should be last executed TD * in case when something went wrong. */ if (transfer && (td->size != to_transfer)) @@ -1054,7 +1154,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_compile_time (GRUB_EHCI_TERMINATE); + td->next_td = grub_cpu_to_le32 (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 @@ -1143,27 +1243,25 @@ 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 */ - status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS); - if ((status & GRUB_EHCI_ST_HC_HALTED) != 0) + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_HC_HALTED) != 0) /* XXX: Fix it: Currently we don't do anything to restart EHCI */ - { - 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 + return GRUB_USB_ERR_INTERNAL; + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_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_dprintf ("ehci", "setup_transfer: no AS/PS, status = 0x%x\n", - status); - return GRUB_USB_ERR_INTERNAL; + grub_error (GRUB_USB_ERR_BADDEVICE, + "FULL/LOW speed device on EHCI port!?!"); + return GRUB_USB_ERR_BADDEVICE; } /* Allocate memory for controller transfer data. */ @@ -1176,7 +1274,6 @@ 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; } @@ -1186,16 +1283,15 @@ 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_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); + 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); /* Allocate appropriate number of TDs and set */ for (i = 0; i < transfer->transcnt; i++) @@ -1213,7 +1309,6 @@ 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; } @@ -1233,7 +1328,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_compile_time (GRUB_EHCI_TERMINATE); + cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n", cdata,cdata->qh_virt); @@ -1246,16 +1341,14 @@ 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_compile_time (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32 (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_compile_time (0); - - sync_all_caches (e); + cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0); /* Finito */ transfer->controller_data = cdata; @@ -1279,9 +1372,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_compile_time + grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED)) & - grub_cpu_to_le32_compile_time (~GRUB_EHCI_STATUS_ACTIVE); + grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE); /* Print debug data here if necessary */ @@ -1305,8 +1398,6 @@ 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, @@ -1342,8 +1433,6 @@ 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. */ @@ -1377,8 +1466,6 @@ 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; } @@ -1390,9 +1477,7 @@ 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, token_ftd; - - sync_all_caches (e); + grub_uint32_t token; grub_dprintf ("ehci", "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n", @@ -1420,18 +1505,13 @@ 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 && ((token & GRUB_EHCI_STATUS_ACTIVE) == 0) - && ((token_ftd & GRUB_EHCI_STATUS_ACTIVE) == 0)) + if ((token & 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) @@ -1461,40 +1541,32 @@ 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 - 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))) + /* 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)) { 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 or SL) are running. What to do? */ - /* Try to Halt QH via de-scheduling QH. */ + /* EHCI and AL 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 ((grub_le_to_cpu32(e->qh_virt[i].qh_hptr) - & GRUB_EHCI_QHTDPTR_MASK) == qh_phys) + if ((e->qh_virt[i].qh_hptr & GRUB_EHCI_QHTDPTR_MASK) == qh_phys) break; } if (i == GRUB_EHCI_N_QH) @@ -1505,8 +1577,6 @@ 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. */ @@ -1550,19 +1620,29 @@ 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); - /* "Free" the QH - link it to itself */ + /* 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 */ 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; } @@ -1578,7 +1658,7 @@ grub_ehci_hubports (grub_usb_controller_t dev) return portinfo; } -static grub_usb_err_t +static grub_err_t grub_ehci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -1600,20 +1680,18 @@ 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_USB_ERR_TIMEOUT; + return grub_error (GRUB_ERR_IO, "portstatus: EHCI Timed out - disable"); 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_USB_ERR_NONE; + return GRUB_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 */ @@ -1625,8 +1703,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_USB_ERR_TIMEOUT; - grub_boot_time ("Port %d reset", port); + return grub_error (GRUB_ERR_IO, + "portstatus: EHCI Timed out - 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 */ @@ -1653,7 +1731,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_USB_ERR_NONE; + return GRUB_ERR_NONE; } static grub_usb_speed_t @@ -1664,6 +1742,11 @@ 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) { @@ -1724,6 +1807,12 @@ 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) { @@ -1777,7 +1866,7 @@ grub_ehci_restore_hw (void) } } - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static grub_err_t @@ -1788,19 +1877,16 @@ 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 */ - grub_ehci_halt (e); + if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE) + grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout"); /* Reset EHCI */ - grub_ehci_reset (e); + if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE) + grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout"); } - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static struct grub_usb_controller_dev usb_controller = { @@ -1811,23 +1897,15 @@ 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, - /* estimated max. count of TDs for one bulk transfer */ - .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4 + .detect_dev = grub_ehci_detect_dev }; GRUB_MOD_INIT (ehci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64); COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96); - - grub_stop_disk_firmware (); - - grub_boot_time ("Initing EHCI hardware"); - grub_ehci_pci_scan (); - grub_boot_time ("Registering EHCI driver"); + grub_ehci_inithw (); 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 new file mode 100644 index 000000000..38c5f01f1 --- /dev/null +++ b/grub-core/bus/usb/emu/usb.c @@ -0,0 +1,203 @@ +/* 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 f0be533d4..23cf63187 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -28,7 +28,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -47,7 +46,7 @@ struct grub_ohci_hcca grub_uint32_t donehead; grub_uint8_t reserved[116]; -} GRUB_PACKED; +} __attribute__((packed)); /* OHCI General Transfer Descriptor */ struct grub_ohci_td @@ -64,7 +63,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 */ -} GRUB_PACKED; +} __attribute__((packed)); /* OHCI Endpoint Descriptor. */ struct grub_ohci_ed @@ -73,7 +72,7 @@ struct grub_ohci_ed grub_uint32_t td_tail; grub_uint32_t td_head; grub_uint32_t next_ed; -} GRUB_PACKED; +} __attribute__((packed)); typedef volatile struct grub_ohci_td *grub_ohci_td_t; typedef volatile struct grub_ohci_ed *grub_ohci_ed_t; @@ -214,9 +213,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 -grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, - void *data __attribute__ ((unused))) +static int NESTED_FUNC_ATTR +grub_ohci_pci_iter (grub_pci_device_t dev, + grub_pci_id_t pciid) { grub_uint32_t interf; grub_uint32_t base; @@ -265,20 +264,11 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); base = grub_pci_read (addr); - 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)); +#if 0 + /* Stop if there is no IO space base address defined. */ + if (! (base & 1)) + return 0; +#endif grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n", class, subclass, interf); @@ -314,7 +304,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, 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_compile_time (1 << 14); /* skip */ + o->ed_ctrl[j].target = grub_cpu_to_le32 (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); @@ -329,7 +319,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, /* 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_compile_time (1 << 14); /* skip */ + o->ed_bulk[j].target = grub_cpu_to_le32 (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); @@ -482,13 +472,13 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, static void grub_ohci_inithw (void) { - grub_pci_iterate (grub_ohci_pci_iter, NULL); + grub_pci_iterate (grub_ohci_pci_iter); } static int -grub_ohci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) +grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) { struct grub_ohci *o; struct grub_usb_controller dev; @@ -496,7 +486,7 @@ grub_ohci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) for (o = ohci; o; o = o->next) { dev.data = o; - if (hook (&dev, hook_data)) + if (hook (&dev)) return 1; } @@ -750,10 +740,7 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, { cdata->td_head_virt = grub_ohci_alloc_td (o); if (!cdata->td_head_virt) - { - grub_free (cdata); - return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ - } + 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 @@ -1223,7 +1210,7 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev, return GRUB_USB_ERR_NONE; } -static grub_usb_err_t +static grub_err_t grub_ohci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -1243,11 +1230,11 @@ 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_USB_ERR_TIMEOUT; + return grub_error (GRUB_ERR_IO, "OHCI Timed out - disable"); grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } /* OHCI does one reset signal 10ms long but USB spec. @@ -1264,7 +1251,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_USB_ERR_TIMEOUT; + return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset"); /* End the reset signaling - reset the reset status change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, @@ -1282,7 +1269,7 @@ 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_USB_ERR_TIMEOUT; + return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable"); /* Reset bit Connect Status Change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, @@ -1294,7 +1281,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static grub_usb_speed_t @@ -1352,10 +1339,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_compile_time (1 << 14); /* skip */ + o->ed_bulk[i].target |= grub_cpu_to_le32 (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_compile_time (1 << 14); /* skip */ + o->ed_ctrl[i].target |= grub_cpu_to_le32 (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 @@ -1439,9 +1426,7 @@ 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, - /* estimated max. count of TDs for one bulk transfer */ - .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4 + .detect_dev = grub_ohci_detect_dev }; static struct grub_preboot *fini_hnd; @@ -1450,9 +1435,6 @@ 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 8e94c7dc0..55d1884cc 100644 --- a/grub-core/bus/usb/serial/common.c +++ b/grub-core/bus/usb/serial/common.c @@ -42,8 +42,7 @@ static int usbnum = 0; int grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, - struct grub_serial_driver *driver, int in_endp, - int out_endp) + struct grub_serial_driver *driver) { struct grub_serial_port *port; int j; @@ -52,7 +51,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, interf = usbdev->config[configno].interf[interfno].descif; - port = grub_zalloc (sizeof (*port)); + port = grub_malloc (sizeof (*port)); if (!port) { grub_print_error (); @@ -74,16 +73,12 @@ 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 - && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING - || in_endp == endp->endp_addr)) + if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) { /* Bulk IN endpoint. */ port->in_endp = endp; } - else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2 - && (out_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING - || out_endp == endp->endp_addr)) + else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) { /* Bulk OUT endpoint. */ port->out_endp = endp; @@ -124,7 +119,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, + err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp->endp_addr, 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 1a99cba17..15ea8fb89 100644 --- a/grub-core/bus/usb/serial/ftdi.c +++ b/grub-core/bus/usb/serial/ftdi.c @@ -91,13 +91,11 @@ real_config (struct grub_serial_port *port) grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, GRUB_FTDI_MODEM_CTRL, - port->config.rtscts ? GRUB_FTDI_MODEM_CTRL_DTRRTS : 0, - 0, 0, 0); + GRUB_FTDI_MODEM_CTRL_DTRRTS, 0, 0, 0); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, GRUB_FTDI_FLOW_CTRL, - port->config.rtscts ? GRUB_FTDI_FLOW_CTRL_DTRRTS : 0, - 0, 0, 0); + GRUB_FTDI_FLOW_CTRL_DTRRTS, 0, 0, 0); divisor = get_divisor (port->config.speed); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, @@ -130,7 +128,7 @@ ftdi_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); } static grub_err_t @@ -195,9 +193,7 @@ 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_USB_SERIAL_ENDPOINT_LAST_MATCHING, - GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); + &grub_ftdi_driver); } 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 d1945a2cb..5433763e5 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; -} GRUB_PACKED; +} __attribute__ ((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, port->config.rtscts ? 0x61 : 0, 0, 0); + 1, 0, 0x61, 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, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); } static grub_err_t @@ -208,9 +208,7 @@ 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_USB_SERIAL_ENDPOINT_LAST_MATCHING, - GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); + &grub_pl2303_driver); } 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 deleted file mode 100644 index e88ba130e..000000000 --- a/grub-core/bus/usb/serial/usbdebug_late.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 7c5811fd6..8f60850de 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -26,7 +26,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -45,22 +44,12 @@ 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 */ -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) - }; +#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) /* 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 \ @@ -105,7 +94,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]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* UHCI Transfer Descriptor. */ struct grub_uhci_td @@ -129,14 +118,14 @@ struct grub_uhci_td /* 3 additional 32 bits words reserved for the Host Controller Driver. */ grub_uint32_t data[3]; -} GRUB_PACKED; +} __attribute__ ((packed)); typedef volatile struct grub_uhci_td *grub_uhci_td_t; typedef volatile struct grub_uhci_qh *grub_uhci_qh_t; struct grub_uhci { - grub_port_t iobase; + int iobase; volatile grub_uint32_t *framelist_virt; grub_uint32_t framelist_phys; struct grub_pci_dma_chunk *framelist_chunk; @@ -189,12 +178,16 @@ 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 +static int NESTED_FUNC_ATTR grub_uhci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused)), - void *data __attribute__ ((unused))) + grub_pci_id_t pciid __attribute__((unused))) { grub_uint32_t class_code; grub_uint32_t class; @@ -217,31 +210,24 @@ 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 & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO) + if (! (base & 1)) 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) + GRUB_MACHINE_PCI_IO_BASE; + u->iobase = base & GRUB_UHCI_IOMASK; /* Reset PIRQ and SMI */ addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP); @@ -365,7 +351,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, static void grub_uhci_inithw (void) { - grub_pci_iterate (grub_uhci_pci_iter, NULL); + grub_pci_iterate (grub_uhci_pci_iter); } static grub_uhci_td_t @@ -405,7 +391,6 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, { 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; @@ -414,10 +399,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, /* Unlink the queue. */ tdprev = td; - if (!td->linkptr2) - td = 0; - else - td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); + td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); /* Free the TD. */ grub_free_td (u, tdprev); @@ -600,17 +582,10 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, *actual = 0; - if (cdata->qh->elinkptr & ~0x0f) - errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); - else - errtd = 0; + errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); - 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); - } + grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", + errtd->ctrl_status, errtd->buffer & (~15), errtd); /* Check if the transaction completed. */ if (cdata->qh->elinkptr & 1) @@ -625,7 +600,9 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, return GRUB_USB_ERR_NONE; } - if (errtd && !(errtd->ctrl_status & (1 << 23))) + grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); + + if (!(errtd->ctrl_status & (1 << 23))) { grub_usb_err_t err = GRUB_USB_ERR_NONE; @@ -694,7 +671,7 @@ grub_uhci_cancel_transfer (grub_usb_controller_t dev, } static int -grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) +grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev)) { struct grub_uhci *u; struct grub_usb_controller dev; @@ -702,14 +679,14 @@ grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) for (u = uhci; u; u = u->next) { dev.data = u; - if (hook (&dev, hook_data)) + if (hook (&dev)) return 1; } return 0; } -static grub_usb_err_t +static grub_err_t grub_uhci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -727,7 +704,8 @@ grub_uhci_portstatus (grub_usb_controller_t dev, else if (port == 1) reg = GRUB_UHCI_REG_PORTSC2; else - return GRUB_USB_ERR_INTERNAL; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "UHCI Root Hub port does not exist"); status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", "detect=0x%02x\n", status); @@ -740,11 +718,11 @@ 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_USB_ERR_TIMEOUT; + return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable"); status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", ">3detect=0x%02x\n", status); - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } /* Reset the port. */ @@ -775,7 +753,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_USB_ERR_TIMEOUT; + return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable"); /* Reset recovery time */ grub_millisleep (10); @@ -785,7 +763,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, grub_dprintf ("uhci", ">3detect=0x%02x\n", status); - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static grub_usb_speed_t @@ -809,7 +787,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 & GRUB_UHCI_DETECT_CHANGED) + if (status & (1 << 1)) { *changed = 1; /* Reset bit Connect Status Change */ @@ -819,9 +797,9 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) else *changed = 0; - if (! (status & GRUB_UHCI_DETECT_HAVE_DEVICE)) + if (! (status & 1)) return GRUB_USB_SPEED_NONE; - else if (status & GRUB_UHCI_DETECT_LOW_SPEED) + else if (status & (1 << 8)) return GRUB_USB_SPEED_LOW; else return GRUB_USB_SPEED_FULL; @@ -844,15 +822,11 @@ 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, - /* estimated max. count of TDs for one bulk transfer */ - .max_bulk_tds = N_TD * 3 / 4 + .detect_dev = grub_uhci_detect_dev }; 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 8da5e4c74..fb04e6572 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -26,44 +26,67 @@ GRUB_MOD_LICENSE ("GPLv3+"); +static grub_usb_controller_dev_t grub_usb_list; static struct grub_usb_attach_desc *attach_hooks; -#if 0 -/* Context for grub_usb_controller_iterate. */ -struct grub_usb_controller_iterate_ctx +void +grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) { - 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; + /* Iterate over all controllers found by the driver. */ + int iterate_hook (grub_usb_controller_t dev) + { + dev->dev = usb; - dev->dev = ctx->p; - if (ctx->hook (dev, ctx->hook_data)) - return 1; - return 0; + /* 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); } -int -grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook, - void *hook_data) +void +grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) { - struct grub_usb_controller_iterate_ctx ctx = { - .hook = hook, - .hook_data = hook_data - }; + 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)) +{ + grub_usb_controller_dev_t p; + + auto int iterate_hook (grub_usb_controller_t dev); + + int iterate_hook (grub_usb_controller_t dev) + { + dev->dev = p; + if (hook (dev)) + return 1; + return 0; + } /* Iterate over all controller drivers. */ - for (ctx.p = grub_usb_list; ctx.p; ctx.p = ctx.p->next) + for (p = grub_usb_list; p; p = p->next) { /* Iterate over the busses of the controllers. XXX: Actually, a hub driver should do this. */ - if (ctx.p->iterate (grub_usb_controller_iterate_iter, &ctx)) + if (p->iterate (iterate_hook)) return 1; } @@ -109,6 +132,31 @@ 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) { @@ -148,7 +196,6 @@ grub_usb_device_initialize (grub_usb_device_t dev) 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 @@ -175,35 +222,18 @@ grub_usb_device_initialize (grub_usb_device_t dev) /* Read all interfaces. */ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) { - 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; - } - + while (pos < config.totallen + && ((struct grub_usb_desc *)&data[pos])->type + != GRUB_USB_DESCRIPTOR_INTERFACE) + pos += ((struct grub_usb_desc *)&data[pos])->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) - { - 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; - } + while (pos < config.totallen + && ((struct grub_usb_desc *)&data[pos])->type + != GRUB_USB_DESCRIPTOR_ENDPOINT) + pos += ((struct grub_usb_desc *)&data[pos])->length; /* Point to the first endpoint. */ dev->config[i].interf[currif].descendp @@ -242,13 +272,8 @@ void grub_usb_device_attach (grub_usb_device_t dev) continue; for (desc = attach_hooks; desc; desc = desc->next) - 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 (interf->class == desc->class && desc->hook (dev, 0, i)) + dev->config[0].interf[i].attached = 1; if (dev->config[0].interf[i].attached) continue; @@ -257,66 +282,59 @@ 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 (grub_usb_register_attach_hook_class_iter, desc); + grub_usb_iterate (usb_iterate); } void diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index a06cce302..5fc5eba39 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -29,7 +29,6 @@ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; static int rescan = 0; -static int npending = 0; struct grub_usb_hub { @@ -37,34 +36,30 @@ 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 split_hubport, int split_hubaddr) + int port, int 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->split_hubport = split_hubport; - dev->split_hubaddr = split_hubaddr; + dev->port = port; + dev->hubaddr = hubaddr; err = grub_usb_device_initialize (dev); if (err) @@ -108,17 +103,13 @@ 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, split_hubport=%d, split_hubaddr=%d\n", - speed, split_hubport, split_hubaddr); + grub_dprintf ("usb", "speed=%d, port=%d, hubaddr=%d\n", + speed, port, 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; } @@ -148,15 +139,10 @@ 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++) @@ -187,7 +173,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, len, + = grub_usb_bulk_read_background (dev, endp->endp_addr, len, (char *) &dev->statuschange); break; } @@ -195,7 +181,7 @@ grub_usb_add_hub (grub_usb_device_t dev) rescan = 1; - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static void @@ -203,30 +189,48 @@ attach_root_port (struct grub_usb_hub *hub, int portno, grub_usb_speed_t speed) { grub_usb_device_t dev; - grub_usb_err_t err; + grub_err_t err; + int total, i; + grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; + int changed=0; - grub_boot_time ("After detect_dev"); +#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; /* 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. */ - /* 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); + dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); hub->controller->dev->pending_reset = 0; - npending--; if (! dev) return; @@ -235,20 +239,14 @@ 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"); } -/* Iterate over all controllers found by the driver. */ -static int -grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *data) +grub_usb_err_t +grub_usb_root_hub (grub_usb_controller_t controller) { - grub_usb_controller_dev_t usb = data; + int i; struct grub_usb_hub *hub; - - controller->dev = usb; - - grub_boot_time ("Registering USB root hub"); + int changed=0; hub = grub_malloc (sizeof (*hub)); if (!hub) @@ -268,123 +266,28 @@ grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *d /* Query the number of ports the root Hub has. */ hub->nports = controller->dev->hubports (controller); - 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) + hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports); + if (!hub->devices) { - grub_free (hub->devices); - grub_free (hub->ports); grub_free (hub->controller); grub_free (hub); - grub_print_error (); - return 0; + return GRUB_USB_ERR_INTERNAL; } - 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) + for (i = 0; i < hub->nports; i++) { - 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; + grub_usb_speed_t speed; + if (!controller->dev->pending_reset) + { + speed = controller->dev->detect_dev (hub->controller, i, + &changed); - 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); + if (speed != GRUB_USB_SPEED_NONE) + attach_root_port (hub, i, speed); + } } - 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"); + return GRUB_USB_ERR_NONE; } static void detach_device (grub_usb_device_t dev); @@ -416,78 +319,14 @@ 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_uint32_t changed; + grub_uint8_t changed; grub_size_t actual, len; + int j, total; if (!dev->hub_transfer) return; @@ -503,7 +342,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, len, + = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len, (char *) &dev->statuschange); if (err || actual == 0 || changed == 0) @@ -513,9 +352,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)) - || dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) + if (!(changed & (1 << i))) continue; /* Get the port status. */ @@ -568,19 +407,52 @@ poll_nonroot_hub (grub_usb_device_t dev) /* 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... */ - 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; + /* 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; } } @@ -592,14 +464,10 @@ 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) @@ -615,42 +483,9 @@ 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, - split_hubport, split_hubaddr); - if (dev->controller.dev->pending_reset) - { - dev->controller.dev->pending_reset = 0; - npending--; - } + next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); + dev->controller.dev->pending_reset = 0; if (! next_dev) continue; @@ -665,7 +500,7 @@ poll_nonroot_hub (grub_usb_device_t dev) } void -grub_usb_poll_devices (int wait_for_completion) +grub_usb_poll_devices (void) { struct grub_usb_hub *hub; int i; @@ -679,7 +514,7 @@ grub_usb_poll_devices (int wait_for_completion) 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) @@ -687,13 +522,10 @@ grub_usb_poll_devices (int wait_for_completion) /* Something went wrong, reset device was not * addressed properly, timeout happened */ hub->controller->dev->pending_reset = 0; - npending--; + speed = hub->controller->dev->detect_dev (hub->controller, + i, &changed); } } - if (!hub->controller->dev->pending_reset) - speed = hub->controller->dev->detect_dev (hub->controller, - i, &changed); - if (changed) { detach_device (hub->devices[i]); @@ -716,30 +548,15 @@ grub_usb_poll_devices (int wait_for_completion) if (dev && dev->descdev.class == 0x09) poll_nonroot_hub (dev); } - - 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))) + if (!rescan) break; - grub_millisleep (25); + grub_millisleep (50); } + } int -grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) +grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) { int i; @@ -747,7 +564,7 @@ grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) { if (grub_usb_devs[i]) { - if (hook (grub_usb_devs[i], hook_data)) + if (hook (grub_usb_devs[i])) return 1; } } diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index 85f081fff..167fae5a2 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -18,26 +18,12 @@ */ #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, @@ -102,8 +88,6 @@ 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); @@ -164,8 +148,6 @@ 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; @@ -207,20 +189,17 @@ grub_usb_control_msg (grub_usb_device_t dev, 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, - struct grub_usb_desc_endp *endpoint, - grub_size_t size0, char *data_in, + int endpoint, grub_size_t size0, char *data_in, grub_transfer_type_t type) { int i; @@ -231,7 +210,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->endp_addr]; + int toggle = dev->toggle[endpoint]; grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size, type); @@ -243,10 +222,21 @@ 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) { - grub_memcpy ((char *) data, data_in, size); - grub_arch_sync_dma_caches (data, size); + struct grub_usb_desc_endp *endpdesc; + endpdesc = grub_usb_get_endpdescriptor (dev, endpoint); + + if (endpdesc) + max = endpdesc->maxpacket; + else + max = 64; } + else + max = 64; /* Create a transfer. */ transfer = grub_malloc (sizeof (struct grub_usb_transfer)); @@ -256,12 +246,10 @@ 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->endp_addr; + transfer->endpoint = endpoint; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; transfer->dir = type; @@ -316,23 +304,18 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) dev->toggle[transfer->endpoint] = toggle; if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) - { - 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_memcpy (transfer->data, (void *) + grub_dma_get_virt (transfer->data_chunk), + transfer->size + 1); grub_free (transfer->transactions); - grub_dma_free (transfer->data_chunk); grub_free (transfer); + grub_dma_free (transfer->data_chunk); } static grub_usb_err_t grub_usb_bulk_readwrite (grub_usb_device_t dev, - struct grub_usb_desc_endp *endpoint, - grub_size_t size0, char *data_in, + int endpoint, grub_size_t size0, char *data_in, grub_transfer_type_t type, int timeout, grub_size_t *actual) { @@ -350,61 +333,31 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, return err; } -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_usb_err_t +grub_usb_bulk_write (grub_usb_device_t dev, + int endpoint, grub_size_t size, char *data) { - 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; + grub_size_t actual; + grub_usb_err_t err; - 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_bulk_readwrite (dev, endpoint, size, data, + GRUB_USB_TRANSFER_TYPE_OUT, 1000, &actual); + if (!err && actual != size) err = GRUB_USB_ERR_DATA; return err; } -grub_usb_err_t -grub_usb_bulk_write (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_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) + int endpoint, grub_size_t size, char *data) { - return grub_usb_bulk_readwrite_packetize (dev, endpoint, - GRUB_USB_TRANSFER_TYPE_IN, - size, 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; } grub_usb_err_t @@ -425,8 +378,7 @@ 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, - struct grub_usb_desc_endp *endpoint, - grub_size_t size, void *data) + int endpoint, grub_size_t size, void *data) { grub_usb_err_t err; grub_usb_transfer_t transfer; @@ -453,8 +405,7 @@ grub_usb_cancel_transfer (grub_usb_transfer_t transfer) grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, - struct grub_usb_desc_endp *endpoint, - grub_size_t size, char *data, + int 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 5a1499aa0..c6be5e1f5 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -61,6 +61,18 @@ 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; @@ -119,8 +131,6 @@ 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) { @@ -131,61 +141,50 @@ iszero (grub_uint8_t *reg, int size) return 1; } -/* 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; -} - +#if defined (__i386__) || defined (__x86_64__) grub_err_t grub_acpi_create_ebda (void) { - struct grub_acpi_create_ebda_ctx ctx = { - .highestlow = 0 - }; - int ebda_kb_len = 0; + int ebda_kb_len; + int ebda_len; 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); - 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 = *(grub_uint16_t *) ebda; + if (! ebda || ebda_kb_len > 16) ebda_kb_len = 0; - ctx.ebda_len = (ebda_kb_len + 1) << 10; + ebda_len = (ebda_kb_len + 1) << 10; /* FIXME: use low-memory mm allocation once it's available. */ - grub_mmap_iterate (find_hook, &ctx); - targetebda = (grub_uint8_t *) (grub_addr_t) ctx.highestlow; + grub_mmap_iterate (find_hook); + targetebda = (grub_uint8_t *) (grub_addr_t) highestlow; grub_dprintf ("acpi", "creating ebda @%llx\n", - (unsigned long long) ctx.highestlow); - if (! ctx.highestlow) + (unsigned long long) highestlow); + if (! 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, ctx.ebda_len, + mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len, GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -208,7 +207,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, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (target, "RSD PTR ", 8) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) target)->revision != 0 @@ -218,7 +217,7 @@ grub_acpi_create_ebda (void) grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target); v2inebda = target; target += v2->length; - target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16); + target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); v2 = 0; break; } @@ -229,7 +228,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, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (target, "RSD PTR ", 8) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0) { @@ -237,7 +236,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 *) ALIGN_UP((grub_addr_t) target, 16); + target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); v1 = 0; break; } @@ -256,7 +255,7 @@ grub_acpi_create_ebda (void) grub_memcpy (target, v2, v2->length); v2inebda = target; target += v2->length; - target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16); + target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); v2 = 0; break; } @@ -273,7 +272,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 *) ALIGN_UP((grub_addr_t) target, 16); + target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); v1 = 0; break; } @@ -290,14 +289,14 @@ grub_acpi_create_ebda (void) for (target = targetebda; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10); target += 0x10) - if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (target, "RSD PTR ", 8) == 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)) = ((grub_addr_t) targetebda) >> 4; + (*((grub_uint16_t *) 0x40e)) = ((long)targetebda) >> 4; grub_dprintf ("acpi", "EBDA switched\n"); return GRUB_ERR_NONE; @@ -356,13 +355,13 @@ setup_common_tables (void) numoftables++; rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr; - playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; + playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * 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) + sizeof (grub_uint32_t) * numoftables; + rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables; rsdt->revision = 1; grub_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid)); grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable)); @@ -385,7 +384,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), GRUB_RSDP_SIGNATURE, + grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", sizeof (rsdpv1_new->signature)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); rsdpv1_new->revision = 0; @@ -410,13 +409,13 @@ setv2table (void) /* Create XSDT. */ xsdt = (struct grub_acpi_table_header *) playground_ptr; - playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; + playground_ptr += sizeof (struct grub_acpi_table_header) + 8 * 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) + sizeof (grub_uint64_t) * numoftables; + xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables; xsdt->revision = 1; grub_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid)); grub_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable)); @@ -429,7 +428,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), GRUB_RSDP_SIGNATURE, + grub_memcpy (&(rsdpv2_new->rsdpv1.signature), "RSD PTR ", sizeof (rsdpv2_new->rsdpv1.signature)); grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid, sizeof (rsdpv2_new->rsdpv1.oemid)); @@ -485,8 +484,6 @@ 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; @@ -593,9 +590,6 @@ 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; @@ -635,7 +629,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], GRUB_FILE_TYPE_ACPI_TABLE); + file = grub_file_open (args[i]); if (! file) { free_tables (); @@ -704,11 +698,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) + sizeof (grub_uint32_t) * numoftables; + playground_size += sizeof (struct grub_acpi_table_header) + 4 * numoftables; /* RSDPv1. */ playground_size += sizeof (struct grub_acpi_rsdp_v10); /* XSDT. */ - playground_size += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; + playground_size += sizeof (struct grub_acpi_table_header) + 8 * numoftables; /* RSDPv2. */ playground_size += sizeof (struct grub_acpi_rsdp_v20); @@ -761,10 +755,10 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID; struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID; - efi_call_2 (grub_efi_system_table->boot_services->install_configuration_table, - &acpi20, grub_acpi_get_rsdpv2 ()); - efi_call_2 (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 diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c index 9cc7f18e3..3db224d4d 100644 --- a/grub-core/commands/acpihalt.c +++ b/grub-core/commands/acpihalt.c @@ -22,12 +22,9 @@ #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; @@ -44,7 +41,6 @@ typedef uint8_t grub_uint8_t; #endif #ifndef GRUB_DSDT_TEST -#include #include #include #include @@ -137,49 +133,6 @@ 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) { @@ -193,28 +146,19 @@ 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_term (ptr, end); + ptr += add = skip_data_ref_object (ptr, end); if (!add) return 0; - ptr += add = skip_term (ptr, end); + ptr += add = skip_data_ref_object (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; @@ -225,15 +169,13 @@ 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 *ptr, grub_uint8_t *end, - grub_uint8_t *scope, int scope_len) +get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) { - grub_uint8_t *prev = table; + grub_uint8_t *ptr, *prev = table; + int sleep_type = -1; - if (!ptr) - ptr = table + sizeof (struct grub_acpi_table_header); + ptr = table + sizeof (struct grub_acpi_table_header); while (ptr < end && prev < ptr) { int add; @@ -248,7 +190,6 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, 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: { @@ -261,8 +202,7 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, } case GRUB_ACPI_OPCODE_NAME: ptr++; - if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) && - (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0)) + if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0) { int ll; grub_uint8_t *ptr2 = ptr; @@ -280,11 +220,14 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, switch (*ptr2) { case GRUB_ACPI_OPCODE_ZERO: - return 0; + sleep_type = 0; + break; case GRUB_ACPI_OPCODE_ONE: - return 1; + sleep_type = 1; + break; case GRUB_ACPI_OPCODE_BYTE_CONST: - return ptr2[1]; + sleep_type = ptr2[1]; + break; default: grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); return -1; @@ -297,37 +240,7 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, 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: { @@ -341,7 +254,8 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, } } - return -2; + grub_dprintf ("acpi", "TYP = %d\n", sleep_type); + return sleep_type; } #ifdef GRUB_DSDT_TEST @@ -353,7 +267,7 @@ main (int argc, char **argv) unsigned char *buf; if (argc < 2) printf ("Usage: %s FILE\n", argv[0]); - f = grub_util_fopen (argv[1], "rb"); + f = fopen (argv[1], "rb"); if (!f) { printf ("Couldn't open file\n"); @@ -365,19 +279,19 @@ main (int argc, char **argv) buf = malloc (len); if (!buf) { - printf (_("error: %s.\n"), _("out of memory")); + printf ("Couldn't malloc buffer\n"); fclose (f); return 2; } if (fread (buf, 1, len, f) != len) { - printf (_("cannot read `%s': %s"), argv[1], strerror (errno)); + printf ("Read failed\n"); free (buf); fclose (f); return 2; } - printf ("Sleep type = %d\n", get_sleep_type (buf, NULL, buf + len, NULL, 0)); + printf ("Sleep type = %d\n", get_sleep_type (buf, buf + len)); free (buf); fclose (f); return 0; @@ -390,10 +304,8 @@ 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; - grub_uint32_t port = 0; - int sleep_type = -1; + struct grub_acpi_table_header *rsdt; + grub_uint32_t *entry_ptr; rsdp2 = grub_acpi_get_rsdpv2 (); if (rsdp2) @@ -412,40 +324,35 @@ 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; - grub_uint8_t *buf = (grub_uint8_t *) dsdt; + int sleep_type = -1; port = fadt->pm1a; grub_dprintf ("acpi", "PM1a port=%x\n", port); if (grub_memcmp (dsdt->signature, "DSDT", - 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; + sizeof (dsdt->signature)) != 0) + break; - grub_dprintf ("acpi", "SSDT = %p\n", ssdt); + sleep_type = get_sleep_type ((grub_uint8_t *) dsdt, + (grub_uint8_t *) dsdt + dsdt->length); - sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0); + 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); } } - 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 27ed0a248..5d4b0cd09 100644 --- a/grub-core/commands/arc/lsdev.c +++ b/grub-core/commands/arc/lsdev.c @@ -24,22 +24,18 @@ 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))) { - grub_arc_iterate_devs (grub_cmd_lsdev_iter, 0, 0); + 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); return 0; } diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c index 944449b77..164a6fea3 100644 --- a/grub-core/commands/blocklist.c +++ b/grub-core/commands/blocklist.c @@ -28,101 +28,64 @@ 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 void -read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length, - 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; - 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; - - 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; - } -} - 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]; - struct blocklist_ctx ctx = { - .start_sector = 0, - .num_sectors = 0, - .num_entries = 0, - .part_start = 0 - }; + 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); + } if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - file = grub_file_open (args[0], GRUB_FILE_TYPE_PRINT_BLOCKLIST - | GRUB_FILE_TYPE_NO_DECOMPRESS); + grub_file_filter_disable_compression (); + file = grub_file_open (args[0]); if (! file) return grub_errno; @@ -130,16 +93,15 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_DEVICE, "this command is available only for disk devices"); - ctx.part_start = grub_partition_get_start (file->device->disk->partition); + 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 (ctx.num_sectors > 0) - print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx); + if (num_sectors > 0) + print_blocklist (start_sector, num_sectors, 0, 0); grub_file_close (file); diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index bbca81e94..91ec87d80 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -146,7 +146,8 @@ grub_loader_boot (void) return grub_error (GRUB_ERR_NO_KERNEL, N_("you need to load the kernel first")); - grub_machine_fini (grub_loader_flags); + if (grub_loader_flags & GRUB_LOADER_FLAG_NORETURN) + grub_machine_fini (); for (cur = preboots_head; cur; cur = cur->next) { @@ -182,14 +183,22 @@ 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 deleted file mode 100644 index dcc078c2a..000000000 --- a/grub-core/commands/boottime.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 d34a34696..ead6ff82c 100644 --- a/grub-core/commands/cacheinfo.c +++ b/grub-core/commands/cacheinfo.c @@ -23,8 +23,6 @@ #include #include -GRUB_MOD_LICENSE ("GPLv3+"); - static grub_err_t grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index ba5f0061a..cd2d76099 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -24,7 +24,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -40,15 +39,9 @@ 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; - unsigned char buf[GRUB_DISK_SECTOR_SIZE]; + 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; @@ -56,7 +49,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], GRUB_FILE_TYPE_CAT); + file = grub_file_open (args[0]); if (! file) return grub_errno; @@ -67,65 +60,21 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) for (i = 0; i < size; i++) { - utbuf[utcount++] = buf[i]; + unsigned char c = buf[i]; - if (is_0d && buf[i] != '\n') + 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 { grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); - grub_printf ("<%x>", (int) '\r'); + grub_printf ("<%x>", (int) c); 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 @@ -133,21 +82,6 @@ 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 e9c3b25d3..cc23ee67e 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -45,8 +45,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], args[1]); - file1 = grub_file_open (args[0], GRUB_FILE_TYPE_CMP); - file2 = grub_file_open (args[1], GRUB_FILE_TYPE_CMP); + file1 = grub_file_open (args[0]); + file2 = grub_file_open (args[1]); if (! file1 || ! file2) goto cleanup; diff --git a/grub-core/commands/configfile.c b/grub-core/commands/configfile.c index f2d2abb5f..99c0a2479 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 but take only menu entries.") + N_("Load another config file without changing context but take only menu entries.") ); cmd_dot = diff --git a/grub-core/commands/date.c b/grub-core/commands/date.c index 5cb4fafd4..8e1f41f14 100644 --- a/grub-core/commands/date.c +++ b/grub-core/commands/date.c @@ -59,8 +59,7 @@ grub_cmd_date (grub_command_t cmd __attribute__ ((unused)), for (; argc; argc--, args++) { - const char *p; - char c; + char *p, c; int m1, ofs, n, cur_mask; p = args[0]; diff --git a/grub-core/kern/efi/acpi.c b/grub-core/commands/efi/acpi.c similarity index 80% rename from grub-core/kern/efi/acpi.c rename to grub-core/commands/efi/acpi.c index 74f8cd1a9..93a560d9c 100644 --- a/grub-core/kern/efi/acpi.c +++ b/grub-core/commands/efi/acpi.c @@ -26,14 +26,14 @@ struct grub_acpi_rsdp_v10 * grub_machine_acpi_get_rsdpv1 (void) { unsigned i; - static grub_efi_packed_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; + 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_packed_guid_t *guid = + grub_efi_guid_t *guid = &grub_efi_system_table->configuration_table[i].vendor_guid; - if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_packed_guid_t))) + 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; } @@ -44,14 +44,14 @@ struct grub_acpi_rsdp_v20 * grub_machine_acpi_get_rsdpv2 (void) { unsigned i; - static grub_efi_packed_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID; + 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_packed_guid_t *guid = + grub_efi_guid_t *guid = &grub_efi_system_table->configuration_table[i].vendor_guid; - if (! grub_memcmp (guid, &acpi20_guid, sizeof (grub_efi_packed_guid_t))) + 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; } diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c deleted file mode 100644 index 7a137a72a..000000000 --- a/grub-core/commands/efi/efifwsetup.c +++ /dev/null @@ -1,90 +0,0 @@ -/* 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_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; - grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; - - old_os_indications = grub_efi_get_variable ("OsIndications", &global, - &oi_size); - - if (old_os_indications != NULL && oi_size == sizeof (os_indications)) - os_indications |= *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; - grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; - - os_indications_supported = grub_efi_get_variable ("OsIndicationsSupported", - &global, &oi_size); - - if (!os_indications_supported) - return 0; - - if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) - return 1; - - return 0; -} - -GRUB_MOD_INIT (efifwsetup) -{ - if (efifwsetup_is_supported ()) - 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/fixvideo.c b/grub-core/commands/efi/fixvideo.c index d9d54a2e8..3ed40b386 100644 --- a/grub-core/commands/efi/fixvideo.c +++ b/grub-core/commands/efi/fixvideo.c @@ -23,7 +23,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -41,9 +40,8 @@ static struct grub_video_patch {0, 0, 0, 0, 0} }; -static int -scan_card (grub_pci_device_t dev, grub_pci_id_t pciid, - void *data __attribute__ ((unused))) +static int NESTED_FUNC_ATTR +scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_pci_address_t addr; @@ -95,7 +93,7 @@ grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { - grub_pci_iterate (scan_card, NULL); + grub_pci_iterate (scan_card); return 0; } diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c index d41d521a4..214adc3d2 100644 --- a/grub-core/commands/efi/loadbios.c +++ b/grub-core/commands/efi/loadbios.c @@ -105,7 +105,7 @@ fake_bios_data (int use_rom) smbios = 0; for (i = 0; i < grub_efi_system_table->num_table_entries; i++) { - grub_efi_packed_guid_t *guid = + grub_efi_guid_t *guid = &grub_efi_system_table->configuration_table[i].vendor_guid; if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t))) @@ -169,7 +169,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)), if (argc > 1) { - file = grub_file_open (argv[1], GRUB_FILE_TYPE_VBE_DUMP); + file = grub_file_open (argv[1]); if (! file) return grub_errno; @@ -183,7 +183,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } - file = grub_file_open (argv[0], GRUB_FILE_TYPE_VBE_DUMP); + file = grub_file_open (argv[0]); if (! file) return grub_errno; diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c deleted file mode 100644 index d1ce99af4..000000000 --- a/grub-core/commands/efi/lsefi.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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+"); - -struct known_protocol -{ - grub_efi_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_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_efi_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 = efi_call_3 (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 (" %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", - protocols[j]->data1, - protocols[j]->data2, - protocols[j]->data3, - (unsigned) protocols[j]->data4[0], - (unsigned) protocols[j]->data4[1], - (unsigned) protocols[j]->data4[2], - (unsigned) protocols[j]->data4[3], - (unsigned) protocols[j]->data4[4], - (unsigned) protocols[j]->data4[5], - (unsigned) protocols[j]->data4[6], - (unsigned) protocols[j]->data4[7]); - } - - } - - 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 c85ff7f36..215b45bff 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; @@ -74,8 +74,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), "ACPI-nvs", "MMIO ", "IO-ports", - "PAL-code", - "persist ", + "PAL-code" }; if (desc->type < ARRAY_SIZE (types_str)) grub_printf ("%s ", types_str[desc->type]); @@ -88,29 +87,21 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), desc->physical_start + (desc->num_pages << 12) - 1, desc->num_pages); - 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); + size = desc->num_pages; + size <<= (12 - 10); + if (size < 1024) + grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size); else - grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60); + { + size /= 1024; + if (size < 1024) + grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size); + else + { + size /= 1024; + grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size); + } + } attr = desc->attribute; if (attr & GRUB_EFI_MEMORY_RUNTIME) @@ -131,12 +122,6 @@ 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 d29188efa..b2359253a 100644 --- a/grub-core/commands/efi/lsefisystab.c +++ b/grub-core/commands/efi/lsefisystab.c @@ -37,22 +37,10 @@ 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_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_LZMA_CUSTOM_DECOMPRESS_GUID, "LZMA CUSTOM DECOMPRESS"}, - { GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID, "MEMORY TYPE INFO"}, - { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, { GRUB_EFI_SAL_TABLE_GUID, "SAL"}, { GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"}, - { 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"}, + { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, + { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"} }; static grub_err_t @@ -64,7 +52,6 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), grub_efi_configuration_table_t *t; unsigned int i; - grub_printf ("Address: %p\n", st); grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n", st->hdr.signature, st->hdr.revision); { @@ -73,8 +60,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), grub_printf ("Vendor: "); for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++); - /* Allocate extra 3 bytes to simplify math. */ - vendor = grub_calloc (4, vendor_utf16 - st->firmware_vendor + 1); + vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1); if (!vendor) return grub_errno; *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, @@ -85,7 +71,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), grub_printf (", Version=%x\n", st->firmware_revision); - grub_printf ("%lld tables:\n", (long long) st->num_table_entries); + grub_printf ("%ld tables:\n", st->num_table_entries); t = st->configuration_table; for (i = 0; i < st->num_table_entries; i++) { diff --git a/grub-core/commands/efi/lssal.c b/grub-core/commands/efi/lssal.c index 5084ddd8b..fa8005b88 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, i; + grub_uint32_t len, l; grub_printf ("SAL rev: %02x, signature: %x, len:%x\n", t->sal_rev, t->signature, t->total_table_len); @@ -44,9 +44,7 @@ disp_sal (void *table) desc = t->entries; len = t->total_table_len - sizeof (struct grub_efi_sal_system_table); - if (t->total_table_len <= sizeof (struct grub_efi_sal_system_table)) - return; - for (i = 0; i < t->entry_count; i++) + while (len > 0) { switch (*(grub_uint8_t *) desc) { @@ -125,8 +123,6 @@ disp_sal (void *table) return; } desc = (grub_uint8_t *)desc + l; - if (len <= l) - return; len -= l; } } @@ -139,12 +135,12 @@ grub_cmd_lssal (struct grub_command *cmd __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_packed_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; + grub_efi_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; for (i = 0; i < st->num_table_entries; i++) { if (grub_memcmp (&guid, &t->vendor_guid, - sizeof (grub_efi_packed_guid_t)) == 0) + sizeof (grub_efi_guid_t)) == 0) { disp_sal (t->vendor_table); return GRUB_ERR_NONE; diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c deleted file mode 100644 index 764098cfc..000000000 --- a/grub-core/commands/efi/shim_lock.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 . - * - * EFI shim lock verifier. - */ - -#include -#include -#include -#include -#include -#include - -GRUB_MOD_LICENSE ("GPLv3+"); - -#define GRUB_EFI_SHIM_LOCK_GUID \ - { 0x605dab50, 0xe046, 0x4300, \ - { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \ - } - -struct grub_efi_shim_lock_protocol -{ - grub_efi_status_t - (*verify) (void *buffer, grub_uint32_t size); -}; -typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t; - -static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; -static grub_efi_shim_lock_protocol_t *sl; - -/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */ -static const char * const disabled_mods[] = {"iorw", "memrw", "wrmsr", NULL}; - -static grub_err_t -shim_lock_init (grub_file_t io, enum grub_file_type type, - void **context __attribute__ ((unused)), - enum grub_verify_flags *flags) -{ - const char *b, *e; - int i; - - *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; - - if (!sl) - return GRUB_ERR_NONE; - - switch (type & GRUB_FILE_TYPE_MASK) - { - case GRUB_FILE_TYPE_GRUB_MODULE: - /* Establish GRUB module name. */ - b = grub_strrchr (io->name, '/'); - e = grub_strrchr (io->name, '.'); - - b = b ? (b + 1) : io->name; - e = e ? e : io->name + grub_strlen (io->name); - e = (e > b) ? e : io->name + grub_strlen (io->name); - - for (i = 0; disabled_mods[i]; i++) - if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e))) - { - grub_error (GRUB_ERR_ACCESS_DENIED, - N_("module cannot be loaded in UEFI secure boot mode: %s"), - io->name); - return GRUB_ERR_ACCESS_DENIED; - } - - /* Fall through. */ - - case GRUB_FILE_TYPE_ACPI_TABLE: - case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: - *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; - - return GRUB_ERR_NONE; - - 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: - for (i = 0; disabled_mods[i]; i++) - if (grub_dl_get (disabled_mods[i])) - { - grub_error (GRUB_ERR_ACCESS_DENIED, - N_("cannot boot due to dangerous module in memory: %s"), - disabled_mods[i]); - return GRUB_ERR_ACCESS_DENIED; - } - - *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; - - /* Fall through. */ - - default: - return GRUB_ERR_NONE; - } -} - -static grub_err_t -shim_lock_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size) -{ - 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 = - { - .name = "shim_lock", - .init = shim_lock_init, - .write = shim_lock_write - }; - -GRUB_MOD_INIT(shim_lock) -{ - sl = grub_efi_locate_protocol (&shim_lock_guid, 0); - grub_verifier_register (&shim_lock); - - if (!sl) - return; - - grub_dl_set_persistent (mod); -} - -GRUB_MOD_FINI(shim_lock) -{ - grub_verifier_unregister (&shim_lock); -} diff --git a/grub-core/commands/efi/smbios.c b/grub-core/commands/efi/smbios.c deleted file mode 100644 index 75202d5aa..000000000 --- a/grub-core/commands/efi/smbios.c +++ /dev/null @@ -1,61 +0,0 @@ -/* 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 -#include - -struct grub_smbios_eps * -grub_machine_smbios_get_eps (void) -{ - unsigned i; - static grub_efi_packed_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID; - - for (i = 0; i < grub_efi_system_table->num_table_entries; i++) - { - grub_efi_packed_guid_t *guid = - &grub_efi_system_table->configuration_table[i].vendor_guid; - - if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_packed_guid_t))) - return (struct grub_smbios_eps *) - grub_efi_system_table->configuration_table[i].vendor_table; - } - - return 0; -} - -struct grub_smbios_eps3 * -grub_machine_smbios_get_eps3 (void) -{ - unsigned i; - static grub_efi_packed_guid_t smbios3_guid = GRUB_EFI_SMBIOS3_TABLE_GUID; - - for (i = 0; i < grub_efi_system_table->num_table_entries; i++) - { - grub_efi_packed_guid_t *guid = - &grub_efi_system_table->configuration_table[i].vendor_guid; - - if (! grub_memcmp (guid, &smbios3_guid, sizeof (grub_efi_packed_guid_t))) - return (struct grub_smbios_eps3 *) - grub_efi_system_table->configuration_table[i].vendor_table; - } - - return 0; -} diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c deleted file mode 100644 index b03b6b296..000000000 --- a/grub-core/commands/efi/tpm.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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 - -typedef TCG_PCR_EVENT grub_tpm_event_t; - -static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; -static grub_efi_guid_t tpm2_guid = EFI_TPM2_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 = efi_call_5 (tpm->status_check, tpm, &caps, &flags, &eventlog, - &lastevent); - - if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag - || !caps.TPMPresentFlag) - return tpm1_present = 0; - - return tpm1_present = 1; -} - -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 = efi_call_2 (tpm->get_capability, tpm, &caps); - - if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag) - return tpm2_present = 0; - - return tpm2_present = 1; -} - -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; - 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; - return 1; - } - - return 0; -} - -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_memcpy (event->Event, description, event->EventSize); - - algorithm = TCG_ALG_SHA; - status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size, - algorithm, event, &eventnum, &lastevent); - grub_free (event); - - switch (status) - { - case GRUB_EFI_SUCCESS: - return 0; - 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_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); - } -} - -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_memcpy (event->Event, description, grub_strlen (description) + 1); - - status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf, - (grub_uint64_t) size, event); - grub_free (event); - - switch (status) - { - case GRUB_EFI_SUCCESS: - return 0; - 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_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); - } -} - -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; - - if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) - return 0; - - 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); -} diff --git a/grub-core/commands/eval.c b/grub-core/commands/eval.c deleted file mode 100644 index f826a4f22..000000000 --- a/grub-core/commands/eval.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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/file.c b/grub-core/commands/file.c deleted file mode 100644 index 2574e6685..000000000 --- a/grub-core/commands/file.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * 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_RISCV_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->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_arm_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_arm64_kernel_header lh; - - if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) - break; - - if (lh.magic == - grub_cpu_to_le32_compile_time (GRUB_LINUX_ARM64_MAGIC_SIGNATURE)) - { - 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_RISCV_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_RISCV_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_RISCV_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 deleted file mode 100644 index 0861c458d..000000000 --- a/grub-core/commands/file32.c +++ /dev/null @@ -1,5 +0,0 @@ -#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 deleted file mode 100644 index 90890d481..000000000 --- a/grub-core/commands/file64.c +++ /dev/null @@ -1,5 +0,0 @@ -#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 deleted file mode 100644 index c17d26ce6..000000000 --- a/grub-core/commands/fileXX.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 444e24874..1a203dc59 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 (grub_uint32_t lba, grub_uint8_t *cl, grub_uint8_t *ch, +lba_to_chs (int lba, grub_uint8_t *cl, grub_uint8_t *ch, grub_uint8_t *dh) { - grub_uint32_t cylinder, head, sector; - grub_uint32_t sectors = 63, heads = 255, cylinders = 1024; + int cylinder, head, sector; + int 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_compile_time (GRUB_PC_PARTITION_SIGNATURE)) + if (mbr.signature != grub_cpu_to_le16 (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_compile_time (1); + mbr.entries[0].start = grub_cpu_to_le32 (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_compile_time (GRUB_PC_PARTITION_SIGNATURE); + mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE); if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr)) { @@ -235,8 +235,6 @@ 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/hashsum.c b/grub-core/commands/hashsum.c index 456ba908b..ba33ea294 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -63,23 +63,17 @@ hextoval (char c) static grub_err_t hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) { - 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_uint8_t context[hash->contextsize]; + grub_uint8_t readbuf[4096]; + grub_memset (context, 0, sizeof (context)); hash->init (context); while (1) { grub_ssize_t r; - r = grub_file_read (file, readbuf, BUF_SIZE); + r = grub_file_read (file, readbuf, sizeof (readbuf)); if (r < 0) - goto fail; + return grub_errno; if (r == 0) break; hash->write (context, readbuf, r); @@ -87,15 +81,7 @@ 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 @@ -104,16 +90,13 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, { grub_file_t hashlist, file; char *buf = NULL; - grub_uint8_t expected[GRUB_CRYPTO_MAX_MDLEN]; - grub_uint8_t actual[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t expected[hash->mdlen]; + grub_uint8_t actual[hash->mdlen]; grub_err_t err; unsigned i; unsigned unread = 0, mismatch = 0; - 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); + hashlist = grub_file_open (hashfilename); if (!hashlist) return grub_errno; @@ -141,15 +124,17 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, filename = grub_xasprintf ("%s/%s", prefix, p); if (!filename) return grub_errno; - file = grub_file_open (filename, GRUB_FILE_TYPE_TO_HASH - | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS - : GRUB_FILE_TYPE_NONE)); + if (!uncompress) + grub_file_filter_disable_compression (); + file = grub_file_open (filename); grub_free (filename); } else - file = grub_file_open (p, GRUB_FILE_TYPE_TO_HASH - | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS - : GRUB_FILE_TYPE_NONE)); + { + if (!uncompress) + grub_file_filter_disable_compression (); + file = grub_file_open (p); + } if (!file) { grub_file_close (hashlist); @@ -220,9 +205,6 @@ 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; @@ -236,13 +218,13 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt, for (i = 0; i < (unsigned) argc; i++) { - GRUB_PROPERLY_ALIGNED_ARRAY (result, GRUB_CRYPTO_MAX_MDLEN); + GRUB_PROPERLY_ALIGNED_ARRAY (result, hash->mdlen); grub_file_t file; grub_err_t err; unsigned j; - file = grub_file_open (args[i], GRUB_FILE_TYPE_TO_HASH - | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS - : GRUB_FILE_TYPE_NONE)); + if (!uncompress) + grub_file_filter_disable_compression (); + file = grub_file_open (args[i]); if (!file) { if (!keep) diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index d3fa9661e..3fb08912d 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -328,9 +328,7 @@ 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"); } diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index f0be89baa..d64c28915 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -99,13 +99,12 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, else { int i; - grub_command_t cmd_iter, cmd, cmd_next; + grub_command_t cmd_iter, cmd; for (i = 0; i < argc; i++) { currarg = args[i]; - - FOR_COMMANDS_SAFE (cmd_iter, cmd_next) + FOR_COMMANDS(cmd_iter) { if (!(cmd_iter->prio & GRUB_COMMAND_FLAG_ACTIVE)) continue; diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c index eaa12465b..4c884b3a1 100644 --- a/grub-core/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -90,7 +90,7 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) { grub_file_t file; - file = grub_file_open (args[0], GRUB_FILE_TYPE_HEXCAT); + file = grub_file_open (args[0]); if (! file) return 0; diff --git a/grub-core/commands/i386/cmosdump.c b/grub-core/commands/i386/cmosdump.c deleted file mode 100644 index 626485ccb..000000000 --- a/grub-core/commands/i386/cmosdump.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 9f6b56a2f..d2a184026 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) { - const char *rest; + 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 = 0, bit = 0; + int byte, bit; 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 = 0, bit = 0; + int byte, bit; grub_err_t err; grub_uint8_t value; @@ -81,25 +81,7 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), return grub_cmos_write (byte, value & (~(1 << bit))); } -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; +static grub_command_t cmd, cmd_clean; GRUB_MOD_INIT(cmostest) @@ -109,16 +91,11 @@ GRUB_MOD_INIT(cmostest) N_("Test bit at BYTE:BIT in CMOS.")); cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, N_("BYTE:BIT"), - N_("Clear bit at BYTE:BIT in CMOS.")); - cmd_set = grub_register_command ("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.")); + N_("Clean 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 deleted file mode 100644 index e97ea6bed..000000000 --- a/grub-core/commands/i386/coreboot/cb_timestamps.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 deleted file mode 100644 index 102291f42..000000000 --- a/grub-core/commands/i386/coreboot/cbls.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 42b984154..3b895cb93 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -29,43 +29,29 @@ 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} }; -enum - { - MODE_LM = 0, - MODE_PAE = 1 - }; +#define bit_LM (1 << 29) -enum - { - bit_PAE = (1 << 6), - }; -enum - { - bit_LM = (1 << 29) - }; - -unsigned char grub_cpuid_has_longmode = 0, grub_cpuid_has_pae = 0; +unsigned char grub_cpuid_has_longmode = 0; static grub_err_t -grub_cmd_cpuid (grub_extcmd_context_t ctxt, +grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - 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 + return grub_cpuid_has_longmode ? GRUB_ERR_NONE /* TRANSLATORS: it's a standalone boolean value, opposite of "true". */ : grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); @@ -78,7 +64,6 @@ 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; @@ -93,24 +78,18 @@ GRUB_MOD_INIT(cpuid) goto done; /* Check the highest input value for eax. */ - grub_cpuid (0, eax, ebx, ecx, edx); + cpuid (0, eax, ebx, ecx, edx); /* We only look at the first four characters. */ max_level = eax; if (max_level == 0) goto done; - 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); + cpuid (0x80000000, eax, ebx, ecx, edx); ext_level = eax; if (ext_level < 0x80000000) goto done; - grub_cpuid (0x80000001, eax, ebx, ecx, edx); + cpuid (0x80000001, eax, ebx, ecx, edx); grub_cpuid_has_longmode = !!(edx & bit_LM); done: #endif diff --git a/grub-core/kern/i386/pc/acpi.c b/grub-core/commands/i386/pc/acpi.c similarity index 84% rename from grub-core/kern/i386/pc/acpi.c rename to grub-core/commands/i386/pc/acpi.c index 297f5d05f..88e4f55cf 100644 --- a/grub-core/kern/i386/pc/acpi.c +++ b/grub-core/commands/i386/pc/acpi.c @@ -29,19 +29,18 @@ grub_machine_acpi_get_rsdpv1 (void) grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ebda_len = * (grub_uint16_t *) ebda; - if (! ebda_len) /* FIXME do we really need this check? */ - goto scan_bios; + if (! ebda_len) + return 0; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) - if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (ptr, "RSD PTR ", 8) == 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, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (ptr, "RSD PTR ", 8) == 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; @@ -57,10 +56,10 @@ grub_machine_acpi_get_rsdpv2 (void) grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); ebda_len = * (grub_uint16_t *) ebda; - if (! ebda_len) /* FIXME do we really need this check? */ - goto scan_bios; + if (! ebda_len) + return 0; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) - if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (ptr, "RSD PTR ", 8) == 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 @@ -68,11 +67,10 @@ 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, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 + if (grub_memcmp (ptr, "RSD PTR ", 8) == 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/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 7f7f2d41c..7fbf8de87 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -74,7 +74,7 @@ typedef struct drivemap_node grub_uint8_t redirto; } drivemap_node_t; -typedef struct GRUB_PACKED int13map_node +typedef struct __attribute__ ((packed)) int13map_node { grub_uint8_t disknum; grub_uint8_t mapto; diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index a980e4688..10a018181 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -28,12 +28,80 @@ #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) @@ -44,6 +112,39 @@ 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) @@ -59,11 +160,11 @@ play (unsigned tempo, struct note *note) switch (note->pitch) { case T_REST: - grub_speaker_beep_off (); + beep_off (); break; default: - grub_speaker_beep_on (note->pitch); + beep_on (note->pitch); break; } @@ -93,7 +194,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), grub_uint32_t tempo; grub_file_t file; - file = grub_file_open (args[0], GRUB_FILE_TYPE_AUDIO); + file = grub_file_open (args[0]); if (! file) return grub_errno; @@ -107,14 +208,6 @@ 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); @@ -132,20 +225,13 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), } else { - const char *end; + 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]); @@ -177,7 +263,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), } } - grub_speaker_beep_off (); + beep_off (); return 0; } diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 26d9acd3d..17f648d78 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -286,49 +286,48 @@ 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; @@ -352,13 +351,15 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args) { unsigned i; - for (i = 0; i < ARRAY_SIZE(simple_flag_offsets); i++) + for (i = 0; i < sizeof (simple_flag_offsets) + / sizeof (simple_flag_offsets[0]); i++) grub_sendkey_set_simple_flag (simple_flag_offsets[i], grub_sendkey_parse_op(state[i])); } /* Set noled. */ - noled = (state[ARRAY_SIZE(simple_flag_offsets)].set); + noled = (state[sizeof (simple_flag_offsets) + / sizeof (simple_flag_offsets[0])].set); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/i386/pc/smbios.c b/grub-core/commands/i386/pc/smbios.c deleted file mode 100644 index 069d66367..000000000 --- a/grub-core/commands/i386/pc/smbios.c +++ /dev/null @@ -1,52 +0,0 @@ -/* 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 deleted file mode 100644 index 46c4346da..000000000 --- a/grub-core/commands/i386/rdmsr.c +++ /dev/null @@ -1,102 +0,0 @@ -/* 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_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr; - grub_uint64_t value; - const char *ptr; - char buf[sizeof("1122334455667788")]; - - /* - * The CPUID instruction should be used to determine whether MSRs - * are supported. (CPUID.01H:EDX[5] = 1) - */ - if (! grub_cpu_is_cpuid_supported ()) - return grub_error (GRUB_ERR_BUG, N_("unsupported instruction")); - - grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]); - - if (max_cpuid < 1) - return grub_error (GRUB_ERR_BUG, N_("unsupported instruction")); - - grub_cpuid (1, a, b, c, features); - - if (!(features & (1 << 5))) - return grub_error (GRUB_ERR_BUG, N_("unsupported instruction")); - - 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_msr_read (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 deleted file mode 100644 index fa76f5aed..000000000 --- a/grub-core/commands/i386/wrmsr.c +++ /dev/null @@ -1,93 +0,0 @@ -/* 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 - -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_uint32_t manufacturer[3], max_cpuid, a, b, c, features, addr; - grub_uint64_t value; - const char *ptr; - - /* - * The CPUID instruction should be used to determine whether MSRs - * are supported. (CPUID.01H:EDX[5] = 1) - */ - if (!grub_cpu_is_cpuid_supported ()) - return grub_error (GRUB_ERR_BUG, N_("unsupported instruction")); - - grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]); - - if (max_cpuid < 1) - return grub_error (GRUB_ERR_BUG, N_("unsupported instruction")); - - grub_cpuid (1, a, b, c, features); - - if (!(features & (1 << 5))) - return grub_error (GRUB_ERR_BUG, N_("unsupported instruction")); - - 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_msr_write (addr, value); - - return GRUB_ERR_NONE; -} - -GRUB_MOD_INIT(wrmsr) -{ - cmd_write = grub_register_command ("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/keylayouts.c b/grub-core/commands/keylayouts.c index c05d6128a..6b5141c29 100644 --- a/grub-core/commands/keylayouts.c +++ b/grub-core/commands/keylayouts.c @@ -40,7 +40,7 @@ static struct grub_keyboard_layout layout_us = { /* 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', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[', + /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[', /* According to usage table 0x31 should be mapped to '/' but testing with real keyboard shows that 0x32 is remapped to '/'. Map 0x31 to 0. @@ -82,8 +82,8 @@ static struct grub_keyboard_layout layout_us = { /* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', /* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')', - /* 0x28 */ '\n' | GRUB_TERM_SHIFT, GRUB_TERM_ESC | GRUB_TERM_SHIFT, - /* 0x2a */ GRUB_TERM_BACKSPACE | GRUB_TERM_SHIFT, GRUB_TERM_TAB | GRUB_TERM_SHIFT, + /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT, + /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | 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 '/'. @@ -132,9 +132,6 @@ 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)) @@ -173,10 +170,8 @@ 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) { @@ -220,7 +215,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), else filename = argv[0]; - file = grub_file_open (filename, GRUB_FILE_TYPE_KEYBOARD_LAYOUT); + file = grub_file_open (filename); if (! file) goto fail; @@ -247,7 +242,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), goto fail; } - if (version != grub_cpu_to_le32_compile_time (GRUB_KEYBOARD_LAYOUTS_VERSION)) + if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version"); goto fail; @@ -295,13 +290,21 @@ 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 ff3f58781..0925c6a0f 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -35,6 +35,24 @@ 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 cc5971f4d..5293accab 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -32,19 +32,9 @@ #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) { @@ -53,25 +43,27 @@ 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, GRUB_FILE_TYPE_CONFIG); + file = grub_file_open (filename); if (! file) - { - grub_free (suffix); - return grub_errno; - } + return grub_errno; menu = grub_env_get_menu (); if (! menu) { menu = grub_zalloc (sizeof (*menu)); if (! menu) - { - grub_free (suffix); - return grub_errno; - } + return grub_errno; grub_env_set_menu (menu); } @@ -84,7 +76,6 @@ legacy_file (const char *filename) if (!buf && grub_errno) { grub_file_close (file); - grub_free (suffix); return grub_errno; } @@ -105,22 +96,13 @@ 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, sz); + suffix = grub_realloc (suffix, grub_strlen (suffix) + + grub_strlen (newsuffix) + 1); if (!suffix) { grub_free (t); - - fail_0: grub_free (entrysrc); grub_free (parsed); grub_free (newsuffix); @@ -152,7 +134,7 @@ legacy_file (const char *filename) if (parsed && !entryname) { - grub_normal_parse_line (parsed, legacy_file_getline, NULL); + grub_normal_parse_line (parsed, getline); grub_print_error (); grub_free (parsed); parsed = NULL; @@ -164,22 +146,13 @@ 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, sz); + entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) + + grub_strlen (parsed) + 1); if (!entrysrc) { grub_free (t); - - fail_1: grub_free (parsed); grub_free (suffix); return grub_errno; @@ -199,8 +172,6 @@ legacy_file (const char *filename) if (!args) { grub_file_close (file); - grub_free (suffix); - grub_free (entrysrc); return grub_errno; } args[0] = entryname; @@ -209,7 +180,7 @@ legacy_file (const char *filename) grub_free (args); } - grub_normal_parse_line (suffix, legacy_file_getline, NULL); + grub_normal_parse_line (suffix, getline); grub_print_error (); grub_free (suffix); grub_free (entrysrc); @@ -272,7 +243,6 @@ 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++) { @@ -333,9 +303,7 @@ 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_calloc (argc - 1, sizeof (cutargs[0])); - if (!cutargs) - return grub_errno; + cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); cutargc = argc - 1; grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); cutargs[0] = args[0]; @@ -345,17 +313,13 @@ 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; - goto out; + return GRUB_ERR_NONE; } } grub_errno = GRUB_ERR_NONE; @@ -370,7 +334,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, argc, args)) { kernel_type = MULTIBOOT; - goto out; + return GRUB_ERR_NONE; } } grub_errno = GRUB_ERR_NONE; @@ -393,7 +357,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->id >= 0x80 && dev->disk->id <= 0x90) + && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) { struct grub_partition *part = dev->disk->partition; bsd_device = dev->disk->id - 0x80 - hdbias; @@ -407,8 +371,6 @@ 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. */ @@ -435,7 +397,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = KFREEBSD; - goto out; + return GRUB_ERR_NONE; } } grub_errno = GRUB_ERR_NONE; @@ -444,8 +406,6 @@ 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; @@ -455,12 +415,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), { char rbuf[3] = "-r"; bsdargc = cutargc + 2; - bsdargs = grub_calloc (bsdargc, sizeof (bsdargs[0])); - if (!bsdargs) - { - err = grub_errno; - goto out; - } + bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); bsdargs[argc] = rbuf; bsdargs[argc + 1] = bsddevname; @@ -476,8 +431,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, bsdargc, bsdargs)) { kernel_type = KNETBSD; - found = 1; - goto free_bsdargs; + return GRUB_ERR_NONE; } } grub_errno = GRUB_ERR_NONE; @@ -490,28 +444,20 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, bsdargc, bsdargs)) { kernel_type = KOPENBSD; - found = 1; - goto free_bsdargs; + return GRUB_ERR_NONE; } } grub_errno = GRUB_ERR_NONE; } - -free_bsdargs: if (bsdargs != cutargs) grub_free (bsdargs); - if (found) - goto out; } } } while (0); - err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", - args[0]); -out: - grub_free (cutargs); - return err; + return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", + args[0]); } static grub_err_t @@ -522,21 +468,12 @@ 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'"), -#ifdef GRUB_MACHINE_PCBIOS - "initrd16" -#else - "initrd" -#endif - ); + "initrd16"); - return cmd->func (cmd, argc ? 1 : 0, args); + return cmd->func (cmd, argc, args); } if (kernel_type == MULTIBOOT) { @@ -572,17 +509,15 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused char **newargs; grub_err_t err; char nounzipbuf[10] = "--nounzip"; - - 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])); + 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"); err = cmd->func (cmd, argc + 1, newargs); grub_free (newargs); @@ -610,6 +545,8 @@ 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) @@ -617,13 +554,8 @@ 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_uint8_t ctx[GRUB_MD_MD5->contextsize]; 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); @@ -631,7 +563,7 @@ 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); - grub_memcpy (alt_result, digest, MD5_HASHLEN); + memcpy (alt_result, digest, MD5_HASHLEN); GRUB_MD_MD5->init (ctx); GRUB_MD_MD5->write (ctx, entered, enteredlen); @@ -647,7 +579,7 @@ check_password_md5_real (const char *entered, for (i = 0; i < 1000; i++) { - grub_memcpy (alt_result, digest, 16); + memcpy (alt_result, digest, 16); GRUB_MD_MD5->init (ctx); if ((i & 1) != 0) @@ -669,9 +601,7 @@ check_password_md5_real (const char *entered, GRUB_MD_MD5->final (ctx); } - ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); - grub_free (ctx); - return ret; + return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); } static grub_err_t @@ -794,37 +724,11 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), NULL); } -int -grub_legacy_check_md5_password (int argc, char **args, - char *entered) -{ - struct legacy_md5_password *pw = NULL; - int ret; - - if (args[0][0] != '-' || args[0][1] != '-') - { - char correct[GRUB_AUTH_MAX_PASSLEN]; - - grub_memset (correct, 0, sizeof (correct)); - grub_strncpy (correct, args[0], sizeof (correct)); - - 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) { + struct legacy_md5_password *pw = NULL; char entered[GRUB_AUTH_MAX_PASSLEN]; if (argc == 0) @@ -833,8 +737,24 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) return GRUB_ACCESS_DENIED; - if (!grub_legacy_check_md5_password (argc, args, - entered)) + if (args[0][0] != '-' || args[0][1] != '-') + { + char correct[GRUB_AUTH_MAX_PASSLEN]; + + 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; + } + + pw = parse_legacy_md5 (argc, args); + + if (!pw) + return GRUB_ACCESS_DENIED; + + if (!check_password_md5_real (entered, pw)) return GRUB_ACCESS_DENIED; return GRUB_ERR_NONE; diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 3fd664aac..18ebb7eab 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -35,48 +35,45 @@ 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, - enum grub_file_type type) +open_envblk_file (char *filename) { grub_file_t file; - char *buf = 0; if (! filename) { const char *prefix; - int len; prefix = grub_env_get ("prefix"); - if (! 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 { 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); } - file = grub_file_open (filename, type); - - grub_free (buf); - return file; + grub_file_filter_disable_compression (); + return grub_file_open (filename); } static grub_envblk_t @@ -117,59 +114,23 @@ 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, char **args) +grub_cmd_load_env (grub_extcmd_context_t ctxt, + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; - grub_env_whitelist_t whitelist; - whitelist.len = argc; - whitelist.list = args; + 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; + } - /* 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)); + file = open_envblk_file ((state[0].set) ? state[0].arg : 0); if (! file) return grub_errno; @@ -177,8 +138,7 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args) if (! envblk) goto fail; - /* argc > 0 indicates caller provided a whitelist of variables to read. */ - grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var); + grub_envblk_iterate (envblk, set_var); grub_envblk_close (envblk); fail: @@ -186,15 +146,6 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args) 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)), @@ -204,10 +155,15 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt, grub_file_t file; grub_envblk_t envblk; - 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)); + /* 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); if (! file) return grub_errno; @@ -215,7 +171,7 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt, if (! envblk) goto fail; - grub_envblk_iterate (envblk, NULL, print_var); + grub_envblk_iterate (envblk, print_var); grub_envblk_close (envblk); fail: @@ -260,19 +216,10 @@ 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) { - 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) + /* Check if any pair of blocks overlap. */ + if (p->sector == q->sector) { /* This might be actually valid, but it is unbelievable that any filesystem makes such a silly allocation. */ @@ -296,18 +243,9 @@ 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) { - if (p->length > blockbuf_len) - { - grub_free (blockbuf); - blockbuf_len = 2 * p->length; - blockbuf = grub_malloc (blockbuf_len); - if (!blockbuf) - return grub_errno; - } + char blockbuf[GRUB_DISK_SECTOR_SIZE]; if (grub_disk_read (disk, p->sector - part_start, p->offset, p->length, blockbuf)) @@ -345,54 +283,49 @@ 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 void -save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length, - void *data) -{ - struct grub_cmd_save_env_ctx *ctx = data; - struct blocklist *block; - - 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 (ctx->tail) - ctx->tail->next = block; - ctx->tail = block; - if (! ctx->head) - ctx->head = block; -} - 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 grub_cmd_save_env_ctx ctx = { - .head = 0, - .tail = 0 - }; + 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; + } if (! argc) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified"); - file = open_envblk_file ((state[0].set) ? state[0].arg : 0, - GRUB_FILE_TYPE_SAVEENV - | GRUB_FILE_TYPE_SKIP_SIGNATURE); + file = open_envblk_file ((state[0].set) ? state[0].arg : 0); if (! file) return grub_errno; @@ -402,14 +335,13 @@ 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 = save_env_read_hook; - file->read_hook_data = &ctx; + file->read_hook = read_hook; envblk = read_envblk_file (file); file->read_hook = 0; if (! envblk) goto fail; - if (check_blocklists (envblk, ctx.head, file)) + if (check_blocklists (envblk, head, file)) goto fail; while (argc) @@ -425,19 +357,17 @@ 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, ctx.head, file); + write_blocklists (envblk, head, file); fail: if (envblk) grub_envblk_close (envblk); - free_blocklists (ctx.head); + free_blocklists (head); grub_file_close (file); return grub_errno; } @@ -447,8 +377,7 @@ 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] [-s|--skip-sig] [variable_name_to_whitelist] [...]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), 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 5b7491aa4..913bb6546 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -43,24 +43,23 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -/* 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 const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; static grub_err_t grub_ls_list_devices (int longlist) { - grub_device_iterate (grub_ls_print_devices, &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_xputs ("\n"); #if 0 @@ -83,93 +82,6 @@ grub_ls_list_devices (int longlist) return 0; } -/* Context for grub_ls_list_files. */ -struct grub_ls_list_files_ctx -{ - char *dirname; - int all; - int human; -}; - -/* Helper for grub_ls_list_files. */ -static int -print_files (const char *filename, const struct grub_dirhook_info *info, - void *data) -{ - struct grub_ls_list_files_ctx *ctx = data; - - if (ctx->all || filename[0] != '.') - grub_printf ("%s%s ", filename, info->dir ? "/" : ""); - - return 0; -} - -/* Helper for grub_ls_list_files. */ -static int -print_files_long (const char *filename, const struct grub_dirhook_info *info, - void *data) -{ - struct grub_ls_list_files_ctx *ctx = data; - - if ((! ctx->all) && (filename[0] == '.')) - return 0; - - if (! info->dir) - { - grub_file_t file; - char *pathname; - - 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) - { - grub_errno = 0; - grub_free (pathname); - return 0; - } - - 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); - grub_free (pathname); - } - 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); - } - grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); - - return 0; -} - static grub_err_t grub_ls_list_files (char *dirname, int longlist, int all, int human) { @@ -178,6 +90,107 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) 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) @@ -201,29 +214,14 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) 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) { - struct grub_ls_list_files_ctx ctx = { - .dirname = dirname, - .all = all, - .human = human - }; - if (longlist) - (fs->fs_dir) (dev, path, print_files_long, &ctx); + (fs->dir) (dev, path, print_files_long); else - (fs->fs_dir) (dev, path, print_files, &ctx); + (fs->dir) (dev, path, print_files); if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && path[grub_strlen (path) - 1] != '/') @@ -234,8 +232,8 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) struct grub_dirhook_info info; grub_errno = 0; - file = grub_file_open (dirname, GRUB_FILE_TYPE_GET_SIZE - | GRUB_FILE_TYPE_NO_DECOMPRESS); + grub_file_filter_disable_compression (); + file = grub_file_open (dirname); if (! file) goto fail; @@ -249,9 +247,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) all = 1; grub_memset (&info, 0, sizeof (info)); if (longlist) - print_files_long (p, &info, &ctx); + print_files_long (p, &info); else - print_files (p, &info, &ctx); + print_files (p, &info); grub_free (dirname); } diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index 082491405..07c3f0d55 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -44,8 +44,7 @@ static void disp_acpi_table (struct grub_acpi_table_header *t) { print_field (t->signature); - 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"); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); print_field (t->oemid); print_field (t->oemtable); grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); @@ -67,87 +66,39 @@ 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: @@ -156,18 +107,17 @@ 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"); } } @@ -232,7 +182,7 @@ static void disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) { print_field (rsdp->signature); - grub_printf ("chksum:%02x (%s), OEM-ID: ", rsdp->checksum, grub_byte_checksum (rsdp, sizeof (*rsdp)) == 0 ? "valid" : "invalid"); + grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum); print_field (rsdp->oemid); grub_printf ("rev=%d\n", rsdp->revision); grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr); @@ -242,13 +192,8 @@ static void disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) { disp_acpi_rsdpv1 (&rsdp->rsdpv1); - 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", + grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, 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 816ee47d1..bd32c338e 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -21,11 +21,9 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); -#ifndef GRUB_MACHINE_EMU static const char *names[] = { [GRUB_MEMORY_AVAILABLE] = N_("available RAM"), @@ -37,35 +35,30 @@ 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_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") + [GRUB_MEMORY_CODE] = N_("RAM holding firmware code"), + [GRUB_MEMORY_HOLE] = N_("Address range not associated with RAM") }; -/* 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 (lsmmap_hook, NULL); + grub_machine_mmap_iterate (hook); #endif return 0; diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index 65213a372..9f836298f 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -22,7 +22,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -127,9 +126,8 @@ static const struct grub_arg_option options[] = static int iospace; -static int -grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, - void *data __attribute__ ((unused))) +static int NESTED_FUNC_ATTR +grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_uint32_t class; const char *sclass; @@ -220,7 +218,7 @@ grub_cmd_lspci (grub_extcmd_context_t ctxt, char **args __attribute__ ((unused))) { iospace = ctxt->state[0].set; - grub_pci_iterate (grub_lspci_iter, NULL); + grub_pci_iterate (grub_lspci_iter); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/macbless.c b/grub-core/commands/macbless.c deleted file mode 100644 index 85cefd0f7..000000000 --- a/grub-core/commands/macbless.c +++ /dev/null @@ -1,235 +0,0 @@ -/* 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/menuentry.c b/grub-core/commands/menuentry.c index 9164df744..58d4dadf6 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -52,8 +52,8 @@ static struct int key; } hotkey_aliases[] = { - {"backspace", GRUB_TERM_BACKSPACE}, - {"tab", GRUB_TERM_TAB}, + {"backspace", '\b'}, + {"tab", '\t'}, {"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_calloc (argc + 1, sizeof (char *)); + menu_args = grub_malloc (sizeof (char*) * (argc + 1)); if (! menu_args) goto fail; diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 6bbce3128..344ea7c18 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -43,7 +43,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], GRUB_FILE_TYPE_CAT); + file = grub_file_open (argv[0]); if (! file) return grub_errno; @@ -101,18 +101,12 @@ grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified"); -#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); + addr = (grub_uint8_t *) grub_strtoul (argv[0], 0, 0); if (grub_errno) return grub_errno; if (argc > 1) - size = (grub_size_t) grub_strtoaddr (argv[1], 0, 0); + size = (grub_size_t) grub_strtoul (argv[1], 0, 0); while (size--) { @@ -137,9 +131,6 @@ 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_is_persistent (mod)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload persistent module"); - if (grub_dl_unref (mod) <= 0) grub_dl_unload (mod); diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c deleted file mode 100644 index 7c8f97f6a..000000000 --- a/grub-core/commands/nativedisk.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * 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 051e31320..fadf87327 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -59,13 +59,7 @@ 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_calloc (nargs + 1, sizeof (struct grub_parttool_argdesc)); - if (!cur->args) - { - grub_free (cur); - curhandle--; - return -1; - } + grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc)); grub_memcpy (cur->args, args, (nargs + 1) * sizeof (struct grub_parttool_argdesc)); @@ -100,50 +94,6 @@ 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) @@ -154,6 +104,48 @@ 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); @@ -185,7 +177,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } /* Load modules. */ - if (! grub_no_modules) + if (! grub_no_autoload) { const char *prefix; prefix = grub_env_get ("prefix"); @@ -199,7 +191,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file; - file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST); + file = grub_file_open (filename); if (file) { char *buf = 0; @@ -249,21 +241,13 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } if (argc == 1) - { - err = show_help (dev); - grub_device_close (dev); - return err; - } + return show_help (); for (i = 1; i < argc; i++) if (grub_strcmp (args[i], "help") == 0) - { - err = show_help (dev); - grub_device_close (dev); - return err; - } + return show_help (); - parsed = (int *) grub_calloc (argc, sizeof (int)); + parsed = (int *) grub_zalloc (argc * sizeof (int)); for (i = 1; i < argc; i++) if (! parsed[i]) @@ -288,15 +272,11 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), break; } if (! cur) - { - grub_free (parsed); - grub_device_close (dev); - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), args[i]); - } ptool = cur; pargs = (struct grub_parttool_args *) - grub_calloc (ptool->nargs, sizeof (struct grub_parttool_args)); + grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args)); for (j = i; j < argc; j++) if (! parsed[j]) { diff --git a/grub-core/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c index ab845d25e..0dd1aef3d 100644 --- a/grub-core/commands/password_pbkdf2.c +++ b/grub-core/commands/password_pbkdf2.c @@ -45,7 +45,6 @@ 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) @@ -56,17 +55,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_auth_authenticate (user); - ret = GRUB_ERR_NONE; + grub_free (buf); + return grub_crypto_gcry_error (err); } - grub_free (buf); - return ret; + if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0) + return GRUB_ACCESS_DENIED; + + grub_auth_authenticate (user); + + return GRUB_ERR_NONE; } static inline int @@ -86,7 +85,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_err_t err; - const char *ptr, *ptr2; + char *ptr, *ptr2; grub_uint8_t *ptro; struct pbkdf2_password *pass; @@ -105,10 +104,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), pass->c = grub_strtoul (ptr, &ptr, 0); if (grub_errno) - { - grub_free (pass); - return grub_errno; - } + return grub_errno; if (*ptr != '.') { grub_free (pass); diff --git a/grub-core/commands/pcidump.c b/grub-core/commands/pcidump.c deleted file mode 100644 index f72628fce..000000000 --- a/grub-core/commands/pcidump.c +++ /dev/null @@ -1,174 +0,0 @@ -/* 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 deleted file mode 100644 index bbf6871fe..000000000 --- a/grub-core/commands/pgp.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* - * 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 %08x 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_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 573bdf603..eeece876d 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -32,7 +31,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -47,7 +45,6 @@ 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} }; @@ -86,7 +83,6 @@ 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) @@ -98,53 +94,6 @@ 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) - return grub_errno; - if (grub_strcmp(dev->disk->partition->partmap->name, "gpt") == 0) - { - struct grub_gpt_partentry entry; - grub_gpt_part_guid_t *guid; - - if (grub_disk_read(disk, p->offset, p->index, sizeof(entry), &entry)) - return grub_errno; - guid = &entry.guid; - grub_snprintf (val, sizeof(val), - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - grub_le_to_cpu32 (guid->data1), - grub_le_to_cpu16 (guid->data2), - grub_le_to_cpu16 (guid->data3), - guid->data4[0], guid->data4[1], guid->data4[2], - guid->data4[3], guid->data4[4], guid->data4[5], - guid->data4[6], guid->data4[7]); - } - 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); @@ -156,16 +105,15 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) 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->fs_uuid) + if (! fs->uuid) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("%s does not support UUIDs"), fs->name); - err = fs->fs_uuid (dev, &uuid); + err = fs->uuid (dev, &uuid); if (err) return err; if (! uuid) @@ -177,17 +125,16 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) else grub_printf ("%s", uuid); grub_free (uuid); - grub_device_close (dev); return GRUB_ERR_NONE; } if (state[5].set) { char *label; - if (! fs->fs_label) + if (! fs->label) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("filesystem `%s' does not support labels"), fs->name); - err = fs->fs_label (dev, &label); + err = fs->label (dev, &label); if (err) return err; if (! label) @@ -200,10 +147,8 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) 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/regexp.c b/grub-core/commands/regexp.c index 612003f94..b0706d069 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -46,31 +46,28 @@ 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; - const char * q; + 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) { @@ -78,7 +75,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 - err = setvar (str, varnames[i], &matches[1]); + setvar (varnames[i], &matches[1]); } else { @@ -90,7 +87,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 - err = setvar (str, p + 1, &matches[j]); + setvar (p + 1, &matches[j]); } if (err != GRUB_ERR_NONE) @@ -116,7 +113,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args) if (ret) goto fail; - matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches)); + matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1)); if (! matches) goto fail; diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index ed090b3af..5e9b7e381 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -42,29 +42,23 @@ struct cache_entry static struct cache_entry *cache; -/* Context for FUNC_NAME. */ -struct search_ctx +void +FUNC_NAME (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints) { - const char *key; - const char *var; - int no_floppy; - char **hints; - unsigned nhints; - int count; - int is_cache; -}; + int count = 0; + int is_cache = 0; + grub_fs_autoload_hook_t saved_autoload; -/* Helper for FUNC_NAME. */ -static int -iterate_device (const char *name, void *data) -{ - struct search_ctx *ctx = data; - int found = 0; + auto int iterate_device (const char *name); + int iterate_device (const char *name) + { + int found = 0; - /* Skip floppy drives when requested. */ - if (ctx->no_floppy && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') - return 1; + /* Skip floppy drives when requested. */ + if (no_floppy && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') + return 0; #ifdef DO_SEARCH_FS_UUID #define compare_fn grub_strcasecmp @@ -73,226 +67,208 @@ iterate_device (const char *name, void *data) #endif #ifdef DO_SEARCH_FILE - { - char *buf; - grub_file_t file; + { + char *buf; + grub_file_t file; - buf = grub_xasprintf ("(%s)%s", name, ctx->key); - if (! buf) - return 1; + buf = grub_xasprintf ("(%s)%s", name, key); + if (! buf) + return 1; - 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); - } + grub_file_filter_disable_compression (); + file = grub_file_open (buf); + 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 fs_uuid +#define read_fn uuid #else -#define read_fn fs_label +#define read_fn 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, ctx->key) == 0) - found = 1; + if (grub_errno == GRUB_ERR_NONE && quid) + { + if (compare_fn (quid, key) == 0) + found = 1; - grub_free (quid); - } - } + grub_free (quid); + } + } - grub_device_close (dev); - } - } + grub_device_close (dev); + } + } #endif - 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 (!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 (found) - { - ctx->count++; - if (ctx->var) - grub_env_set (ctx->var, name); - else - grub_printf (" %s", name); - } + if (found) + { + count++; + if (var) + grub_env_set (var, name); + else + grub_printf (" %s", name); + } - grub_errno = GRUB_ERR_NONE; - return (found && ctx->var); -} + grub_errno = GRUB_ERR_NONE; + return (found && var); + } -/* 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; + 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; - 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, ctx); - grub_free (devname); + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 1; + ret = iterate_device (devname); + grub_free (devname); - return ret; -} + return ret; + } -/* Helper for FUNC_NAME. */ -static void -try (struct search_ctx *ctx) -{ - unsigned i; - struct cache_entry **prev; - struct cache_entry *cache_ent; + auto void try (void); + void try (void) + { + 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, 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) + 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; return; - } - } - grub_device_iterate (iterate_device, ctx); -} + } + 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; + } + } -void -FUNC_NAME (const char *key, const char *var, int no_floppy, - char **hints, unsigned nhints) -{ - struct search_ctx ctx = { - .key = key, - .var = var, - .no_floppy = no_floppy, - .hints = hints, - .nhints = nhints, - .count = 0, - .is_cache = 0 - }; - grub_fs_autoload_hook_t saved_autoload; + 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); + } /* First try without autoloading if we're setting variable. */ if (var) { saved_autoload = grub_fs_autoload_hook; grub_fs_autoload_hook = 0; - try (&ctx); + try (); /* Restore autoload hook. */ grub_fs_autoload_hook = saved_autoload; /* Retry with autoload if nothing found. */ - if (grub_errno == GRUB_ERR_NONE && ctx.count == 0) - try (&ctx); + if (grub_errno == GRUB_ERR_NONE && count == 0) + try (); } else - try (&ctx); + try (); - if (grub_errno == GRUB_ERR_NONE && ctx.count == 0) + if (grub_errno == GRUB_ERR_NONE && 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 47fc8eb99..3f75fecdf 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -122,7 +122,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_calloc (nhints, sizeof (hints[0])); + hints = grub_malloc (sizeof (hints[0]) * nhints); if (!hints) return grub_errno; j = 0; @@ -175,10 +175,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) var = "root"; } else - { - grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); - goto out; - } + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); if (state[SEARCH_LABEL].set) grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, @@ -190,10 +187,8 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, hints, nhints); else - grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); + return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); -out: - grub_free (hints); return grub_errno; } diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index e966af080..fcfec4058 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -83,9 +83,8 @@ static int regsize; static grub_uint16_t regaddr; static const char *varname; -static int -grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, - void *data __attribute__ ((unused))) +static int NESTED_FUNC_ATTR +grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_uint32_t regval = 0; grub_pci_address_t addr; @@ -129,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, if (!write_mask) { - grub_printf (_("Register %x of %x:%02x.%x is %x\n"), regaddr, + grub_printf (_("Register %x of %d:%d.%d is %x\n"), regaddr, grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), @@ -169,7 +168,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, &ptr, 16) & 0xffff); + pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; @@ -182,7 +181,8 @@ 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, &ptr, 16) & 0xffff) << 16; + pciid_check_value |= (grub_strtoul (ptr, (char **) &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, &ptr, 16); + bus = grub_strtoul (ptr, (char **) &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, &ptr, 16); + device = grub_strtoul (ptr, (char **) &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, &ptr, 16); + function = grub_strtoul (ptr, (char **) &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, &ptr, 16); + regaddr = grub_strtoul (ptr, (char **) &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, &ptr, 16); + regaddr += grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno) return grub_errno; } @@ -301,14 +301,14 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (*ptr == '=') { ptr++; - regwrite = grub_strtoul (ptr, &ptr, 16); + regwrite = grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno) return grub_errno; write_mask = 0xffffffff; if (*ptr == ':') { ptr++; - write_mask = grub_strtoul (ptr, &ptr, 16); + write_mask = grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno) return grub_errno; write_mask = 0xffffffff; @@ -320,7 +320,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, NULL); + grub_pci_iterate (grub_setpci_iter); return GRUB_ERR_NONE; } @@ -330,7 +330,7 @@ GRUB_MOD_INIT(setpci) { cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0, N_("[-s POSITION] [-d DEVICE] [-v VAR] " - "REGISTER[=VALUE[:MASK]]"), + "[REGISTER][=VALUE[:MASK]]"), N_("Manipulate PCI devices."), options); } diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index a1370b710..98e6280a5 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 struct grub_term_coordinate *pos; +static grub_uint16_t *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_key_is_interrupt (grub_getkey_noblock ())) + if (grub_getkey_noblock () == GRUB_TERM_ESC) return 1; return 0; @@ -78,8 +78,6 @@ 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 deleted file mode 100644 index 1a9086ddd..000000000 --- a/grub-core/commands/smbios.c +++ /dev/null @@ -1,398 +0,0 @@ -/* 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 deleted file mode 100644 index 7be28fada..000000000 --- a/grub-core/commands/syslinuxcfg.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 3002186d2..425a41126 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -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,14 +126,6 @@ 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"), diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c index 62d3fb398..3a0e0e069 100644 --- a/grub-core/commands/test.c +++ b/grub-core/commands/test.c @@ -31,132 +31,121 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* A simple implementation for signed numbers. */ static int -grub_strtosl (char *arg, const char ** const end, int base) +grub_strtosl (char *arg, char **end, int base) { if (arg[0] == '-') return -grub_strtoul (arg + 1, end, base); return grub_strtoul (arg, end, base); } -/* Context for test_parse. */ -struct test_parse_ctx -{ - int invert; - int or, and; - int file_exists; - struct grub_dirhook_info file_info; - char *filename; -}; - -/* 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; -} - -/* 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; - - if ((info->case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename) - : grub_strcmp (cur_filename, ctx->filename)) == 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; - } - - 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++; - - /* 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; - } - - /* 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; - - /* 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); - - 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) { - struct test_parse_ctx ctx = { - .and = 1, - .or = 0, - .invert = 0 - }; + int ret = 0, discard = 0, invert = 0; + int file_exists; + struct grub_dirhook_info file_info; + + auto void update_val (int val); + auto void get_fileinfo (char *pathname); + + /* Take care of discarding and inverting. */ + void update_val (int val) + { + if (! discard) + ret = invert ? ! val : val; + invert = discard = 0; + } + + /* 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, filename) + : grub_strcmp (cur_filename, filename)) == 0) + { + file_info = *info; + file_exists = 1; + return 1; + } + return 0; + } + + 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; + } + + 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; + + /* 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) + { + file_exists = 1; + grub_memset (&file_info, 0, sizeof (file_info)); + /* Root is always a directory. */ + file_info.dir = 1; + + /* 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); + } /* Here we have the real parsing. */ while (*argn < argc) @@ -168,16 +157,14 @@ 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, - &ctx); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], "!=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0, - &ctx); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0); (*argn) += 3; continue; } @@ -185,32 +172,28 @@ 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, - &ctx); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], "<=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0, - &ctx); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], ">") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0, - &ctx); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], ">=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0, - &ctx); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0); (*argn) += 3; continue; } @@ -219,7 +202,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), &ctx); + == grub_strtosl (args[*argn + 2], 0, 0)); (*argn) += 3; continue; } @@ -227,7 +210,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), &ctx); + >= grub_strtosl (args[*argn + 2], 0, 0)); (*argn) += 3; continue; } @@ -235,7 +218,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), &ctx); + > grub_strtosl (args[*argn + 2], 0, 0)); (*argn) += 3; continue; } @@ -243,7 +226,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), &ctx); + <= grub_strtosl (args[*argn + 2], 0, 0)); (*argn) += 3; continue; } @@ -251,7 +234,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), &ctx); + < grub_strtosl (args[*argn + 2], 0, 0)); (*argn) += 3; continue; } @@ -259,7 +242,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), &ctx); + != grub_strtosl (args[*argn + 2], 0, 0)); (*argn) += 3; continue; } @@ -282,10 +265,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), &ctx); + > grub_strtoul (args[*argn + 2] + i, 0, 0)); else update_val (grub_strtoul (args[*argn] + i, 0, 0) - < grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx); + < grub_strtoul (args[*argn + 2] + i, 0, 0)); (*argn) += 3; continue; } @@ -300,24 +283,22 @@ test_parse (char **args, int *argn, int argc) int bias = 0; /* Fetch fileinfo. */ - get_fileinfo (args[*argn], &ctx); - file1 = ctx.file_info; - file1exists = ctx.file_exists; - get_fileinfo (args[*argn + 2], &ctx); + get_fileinfo (args[*argn]); + file1 = file_info; + file1exists = file_exists; + get_fileinfo (args[*argn + 2]); 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 && ! ctx.file_exists) - || (file1.mtimeset && ctx.file_info.mtimeset - && file1.mtime + bias > ctx.file_info.mtime), - &ctx); + update_val ((file1exists && ! file_exists) + || (file1.mtimeset && file_info.mtimeset + && file1.mtime + bias > file_info.mtime)); else - update_val ((! file1exists && ctx.file_exists) - || (file1.mtimeset && ctx.file_info.mtimeset - && file1.mtime + bias < ctx.file_info.mtime), - &ctx); + update_val ((! file1exists && file_exists) + || (file1.mtimeset && file_info.mtimeset + && file1.mtime + bias < file_info.mtime)); (*argn) += 3; continue; } @@ -329,53 +310,53 @@ test_parse (char **args, int *argn, int argc) /* File tests. */ if (grub_strcmp (args[*argn], "-d") == 0) { - get_fileinfo (args[*argn + 1], &ctx); - update_val (ctx.file_exists && ctx.file_info.dir, &ctx); + get_fileinfo (args[*argn + 1]); + update_val (file_exists && file_info.dir); (*argn) += 2; - continue; + return ret; } if (grub_strcmp (args[*argn], "-e") == 0) { - get_fileinfo (args[*argn + 1], &ctx); - update_val (ctx.file_exists, &ctx); + get_fileinfo (args[*argn + 1]); + update_val (file_exists); (*argn) += 2; - continue; + return ret; } if (grub_strcmp (args[*argn], "-f") == 0) { - get_fileinfo (args[*argn + 1], &ctx); + get_fileinfo (args[*argn + 1]); /* FIXME: check for other types. */ - update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx); + update_val (file_exists && ! file_info.dir); (*argn) += 2; - continue; + return ret; } if (grub_strcmp (args[*argn], "-s") == 0) { grub_file_t file; - 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); + grub_file_filter_disable_compression (); + file = grub_file_open (args[*argn + 1]); + update_val (file && (grub_file_size (file) != 0)); if (file) grub_file_close (file); grub_errno = GRUB_ERR_NONE; (*argn) += 2; - continue; + return ret; } /* String tests. */ if (grub_strcmp (args[*argn], "-n") == 0) { - update_val (args[*argn + 1][0], &ctx); + update_val (args[*argn + 1][0]); (*argn) += 2; continue; } if (grub_strcmp (args[*argn], "-z") == 0) { - update_val (! args[*argn + 1][0], &ctx); + update_val (! args[*argn + 1][0]); (*argn) += 2; continue; } @@ -387,40 +368,42 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn], ")") == 0) { (*argn)++; - return ctx.or || ctx.and; + return ret; } /* Recursively invoke if parenthesis. */ if (grub_strcmp (args[*argn], "(") == 0) { (*argn)++; - update_val (test_parse (args, argn, argc), &ctx); + update_val (test_parse (args, argn, argc)); continue; } if (grub_strcmp (args[*argn], "!") == 0) { - ctx.invert = ! ctx.invert; + invert = ! 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) { - ctx.or = ctx.or || ctx.and; - ctx.and = 1; + /* If current value is 1 second value is to be discarded. */ + discard = ret; (*argn)++; continue; } /* No test found. Interpret if as just a string. */ - update_val (args[*argn][0], &ctx); + update_val (args[*argn][0]); (*argn)++; } - return ctx.or || ctx.and; + return ret; } static grub_err_t diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c index ff01a0516..a1bf775b8 100644 --- a/grub-core/commands/testload.c +++ b/grub-core/commands/testload.c @@ -31,20 +31,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); -/* Helper for grub_cmd_testload. */ -static void -read_progress (grub_disk_addr_t sector __attribute__ ((unused)), - unsigned offset __attribute__ ((unused)), - unsigned len, - void *data __attribute__ ((unused))) -{ - for (; len >= GRUB_DISK_SECTOR_SIZE; len -= GRUB_DISK_SECTOR_SIZE) - grub_xputs ("."); - if (len) - grub_xputs ("."); - grub_refresh (); -} - static grub_err_t grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -53,11 +39,20 @@ 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], GRUB_FILE_TYPE_TESTLOAD); + file = grub_file_open (argv[0]); if (! file) return grub_errno; @@ -73,7 +68,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), goto fail; grub_printf ("Reading %s sequentially", argv[0]); - file->read_hook = read_progress; + file->read_hook = read_func; 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 deleted file mode 100644 index c13a9b8d8..000000000 --- a/grub-core/commands/testspeed.c +++ /dev/null @@ -1,115 +0,0 @@ -/* 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 deleted file mode 100644 index 2052c36ea..000000000 --- a/grub-core/commands/tpm.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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; - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_tpm_verify_write (void *context, void *buf, grub_size_t size) -{ - return grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); -} - -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); - return status; -} - -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) -{ - grub_verifier_register (&grub_tpm_verifier); -} - -GRUB_MOD_FINI (tpm) -{ - grub_verifier_unregister (&grub_tpm_verifier); -} diff --git a/grub-core/commands/tr.c b/grub-core/commands/tr.c deleted file mode 100644 index ef72841a2..000000000 --- a/grub-core/commands/tr.c +++ /dev/null @@ -1,126 +0,0 @@ -/* 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 2c6d93fe6..72475901d 100644 --- a/grub-core/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -63,11 +63,6 @@ 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) @@ -113,10 +108,6 @@ 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) { @@ -138,7 +129,7 @@ usb_print_str (const char *description, grub_usb_device_t dev, int idx) } static int -usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused))) +usb_iterate (grub_usb_device_t dev) { struct grub_usb_desc_device *descdev; int i; @@ -205,10 +196,10 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_usb_poll_devices (1); + grub_usb_poll_devices (); grub_printf ("USB devices:\n\n"); - grub_usb_iterate (usb_iterate, NULL); + grub_usb_iterate (usb_iterate); return 0; } diff --git a/grub-core/commands/verifiers.c b/grub-core/commands/verifiers.c deleted file mode 100644 index aae4d84bb..000000000 --- a/grub-core/commands/verifiers.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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; -} - -GRUB_MOD_INIT(verifiers) -{ - grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open); -} - -GRUB_MOD_FINI(verifiers) -{ - grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY); -} diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 016a4d818..4a1157615 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -27,28 +27,23 @@ GRUB_MOD_LICENSE ("GPLv3+"); -struct hook_ctx -{ - unsigned height, width, depth; - struct grub_video_mode_info *current_mode; -}; +static unsigned height, width, depth; +static struct grub_video_mode_info *current_mode; static int -hook (const struct grub_video_mode_info *info, void *hook_arg) +hook (const struct grub_video_mode_info *info) { - struct hook_ctx *ctx = hook_arg; - - if (ctx->height && ctx->width && (info->width != ctx->width || info->height != ctx->height)) + if (height && width && (info->width != width || info->height != height)) return 0; - if (ctx->depth && info->bpp != ctx->depth) + if (depth && info->bpp != depth) return 0; if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) grub_printf (" "); else { - if (ctx->current_mode && info->mode_number == ctx->current_mode->mode_number) + if (current_mode && info->mode_number == current_mode->mode_number) grub_printf ("*"); else grub_printf (" "); @@ -73,9 +68,9 @@ hook (const struct grub_video_mode_info *info, void *hook_arg) info->blue_field_pos, info->reserved_field_pos); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) - /* TRANSLATORS: In "paletted color" mode you write the index of the color - in the palette. Synonyms include "packed pixel". */ - grub_xputs (_("Paletted ")); + /* TRANSLATORS: In "packed pixel" mode you write the index of the color + in the palette. Synonyms include "paletted color". */ + grub_xputs (_("Packed pixel ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) grub_xputs (_("YUV ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) @@ -131,14 +126,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), { grub_video_adapter_t adapter; grub_video_driver_id_t id; - struct hook_ctx ctx; - ctx.height = ctx.width = ctx.depth = 0; + height = width = depth = 0; if (argc) { - const char *ptr; + char *ptr; ptr = args[0]; - ctx.width = grub_strtoul (ptr, &ptr, 0); + width = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; if (*ptr != 'x') @@ -146,13 +140,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), N_("invalid video mode specification `%s'"), args[0]); ptr++; - ctx.height = grub_strtoul (ptr, &ptr, 0); + height = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; if (*ptr == 'x') { ptr++; - ctx.depth = grub_strtoul (ptr, &ptr, 0); + depth = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; } @@ -181,12 +175,12 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), continue; } - ctx.current_mode = NULL; + current_mode = NULL; if (adapter->id == id) { if (grub_video_get_info (&info) == GRUB_ERR_NONE) - ctx.current_mode = &info; + current_mode = &info; else /* Don't worry about errors. */ grub_errno = GRUB_ERR_NONE; @@ -204,14 +198,14 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), if (adapter->print_adapter_specific_info) adapter->print_adapter_specific_info (); - adapter->iterate (hook, &ctx); + adapter->iterate (hook); if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE) print_edid (&edid_info); else grub_errno = GRUB_ERR_NONE; - ctx.current_mode = NULL; + current_mode = NULL; if (adapter->id != id) { diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index b6c181b52..2e4b3a23c 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -49,6 +49,7 @@ 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]; @@ -70,10 +71,10 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_font_t fixed; struct grub_font_glyph *glyph; - if (grub_video_create_render_target (&text_layer, width, height, - GRUB_VIDEO_MODE_TYPE_RGB - | GRUB_VIDEO_MODE_TYPE_ALPHA) - || !text_layer) + grub_video_create_render_target (&text_layer, width, height, + GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA); + if (!text_layer) goto fail; grub_video_set_active_render_target (text_layer); @@ -154,38 +155,26 @@ 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 cc3290311..2b73d9ad8 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -23,7 +23,6 @@ #include #include #include -#include #include @@ -49,7 +48,6 @@ merge (char **dest, char **ps) int i; int j; char **p; - grub_size_t sz; if (! dest) return ps; @@ -62,12 +60,7 @@ merge (char **dest, char **ps) for (j = 0; ps[j]; j++) ; - if (grub_add (i, j, &sz) || - grub_add (sz, 1, &sz) || - grub_mul (sz, sizeof (char *), &sz)) - return dest; - - p = grub_realloc (dest, sz); + p = grub_realloc (dest, sizeof (char*) * (i + j + 1)); if (! p) { grub_free (dest); @@ -122,15 +115,8 @@ make_regex (const char *start, const char *end, regex_t *regexp) char ch; int i = 0; unsigned len = end - start; - char *buffer; - grub_size_t sz; + char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */ - /* 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; @@ -224,133 +210,60 @@ 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; - if (grub_device_iterate (match_devices_iter, &ctx)) - goto fail; + auto int match (const char *name); + int match (const char *name) + { + char **t; + char *buffer; - return ctx.devs; + /* skip partitions if asked to. */ + if (noparts && grub_strchr(name, ',')) + return 0; - fail: - - for (i = 0; ctx.devs && ctx.devs[i]; i++) - grub_free (ctx.devs[i]); - - 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); + buffer = grub_xasprintf ("(%s)", name); + if (! buffer) return 1; - } - ctx->files = t; - ctx->files[ctx->nfile++] = buffer; - ctx->files[ctx->nfile] = 0; + 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)) + goto fail; + + return devs; + + fail: + + for (i = 0; devs && devs[i]; i++) + grub_free (devs[i]); + + grub_free (devs); + return 0; } @@ -358,107 +271,58 @@ 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 (); - ctx.dir = make_dir (prefix, suffix, end); - if (! ctx.dir) + dir = make_dir (prefix, suffix, end); + if (! dir) goto fail; - device_name = grub_file_get_device_name (ctx.dir); - dev = grub_device_open (device_name); - if (! dev) - goto fail; - - fs = grub_fs_probe (dev); - if (! fs) - goto fail; - - if (ctx.dir[0] == '(') - { - path = grub_strchr (ctx.dir, ')'); - if (!path) - goto fail; - path++; - } - else - path = ctx.dir; - - if (fs->fs_dir (dev, path, match_files_iter, &ctx)) - goto fail; - - grub_free (ctx.dir); - grub_device_close (dev); - grub_free (device_name); - grub_error_pop (); - return ctx.files; - - fail: - - grub_free (ctx.dir); - - for (i = 0; ctx.files && ctx.files[i]; i++) - grub_free (ctx.files[i]); - - grub_free (ctx.files); - - if (dev) - grub_device_close (dev); - - grub_free (device_name); - - grub_error_pop (); - 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; - const char *device_name, *path; - device_name = grub_file_get_device_name (dir); dev = grub_device_open (device_name); if (! dev) @@ -478,14 +342,82 @@ check_file (const char *dir, const char *basename) else path = dir; - fs->fs_dir (dev, path[0] ? path : "/", check_file_iter, &ctx); + if (fs->dir (dev, path, match)) + goto fail; + + grub_free (dir); + grub_device_close (dev); + grub_free (device_name); + grub_error_pop (); + return files; + + fail: + + grub_free (dir); + + for (i = 0; files && files[i]; i++) + grub_free (files[i]); + + grub_free (files); + + if (dev) + grub_device_close (dev); + + grub_free (device_name); + + grub_error_pop (); + return 0; +} + +static int +check_file (const char *dir, const char *basename) +{ + 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) + goto fail; + + fs = grub_fs_probe (dev); + if (! fs) + goto fail; + + if (dir[0] == '(') + { + path = grub_strchr (dir, ')'); + if (!path) + goto fail; + path++; + } + else + path = dir; + + fs->dir (dev, path[0] ? path : "/", match); if (grub_errno == 0 && basename[0] == 0) - ctx.found = 1; + found = 1; fail: grub_errno = 0; - return ctx.found; + return found; } static void diff --git a/grub-core/commands/xen/lsxen.c b/grub-core/commands/xen/lsxen.c deleted file mode 100644 index 97713102c..000000000 --- a/grub-core/commands/xen/lsxen.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 ae4b3a415..8161d570e 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; - void *ctx; + grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; int low = 0; if (argc < 1) @@ -65,14 +65,11 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16)); - 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_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", @@ -94,8 +91,6 @@ 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 249163ff0..ebcc35221 100644 --- a/grub-core/disk/AFSplitter.c +++ b/grub-core/disk/AFSplitter.c @@ -21,12 +21,9 @@ */ #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); @@ -40,8 +37,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[GRUB_CRYPTO_MAX_MDLEN]; - grub_uint8_t temp[sizeof (IV) + GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t final[hash->mdlen]; + grub_uint8_t temp[sizeof (IV) + hash->mdlen]; /* hash block the whole data set with different IVs to produce * more than just a single data block @@ -75,9 +72,6 @@ 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 0e6d56c24..4ab2d18db 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 transferred; + grub_uint32_t transfered; grub_uint64_t command_table_base; grub_uint32_t unused[4]; }; @@ -75,27 +75,11 @@ 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; @@ -147,13 +131,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 grub_ahci_readwrite_real (struct grub_ahci_device *dev, struct grub_disk_ata_pass_through_parms *parms, - int spinup, int reset); + int spinup); enum @@ -179,531 +162,8 @@ enum static struct grub_ahci_device *grub_ahci_devices; static int numdevs; -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, 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) +init_port (struct grub_ahci_device *dev) { struct grub_pci_dma_chunk *command_list; struct grub_pci_dma_chunk *command_table; @@ -794,13 +254,193 @@ reinit_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 (reinit_port (*pdev)) + if (init_port (*pdev)) { struct grub_ahci_device *odev; odev = *pdev; @@ -814,8 +454,8 @@ grub_ahci_restore_hw (void) static int -grub_ahci_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) +grub_ahci_iterate (int (*hook) (int id, int bus), + grub_disk_pull_t pull) { struct grub_ahci_device *dev; @@ -823,7 +463,7 @@ grub_ahci_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, return 0; FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num, hook_data)) + if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num)) return 1; return 0; @@ -863,60 +503,10 @@ static const int register_map[11] = { 3 /* Features */, 9 /* LBA48 mid */, 10 /* LBA48 high */ }; -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, 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, int reset) + int spinup) { struct grub_pci_dma_chunk *bufc; grub_uint64_t endtime; @@ -926,15 +516,25 @@ 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 (!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); + 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; + } + } dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; @@ -948,45 +548,32 @@ 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"); - if (parms->size) - bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); - else - bufc = grub_memalign_dma32 (1024, 512); + bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); - grub_dprintf ("ahci", "AHCI tfd = %x, CL=%p\n", - dev->hba->ports[dev->port].task_file_data, - dev->command_list); + dev->hba->ports[dev->port].command |= 8; + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); /* 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) - | ((parms->size ? 1 : 0) << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) + | (1 << 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); - 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].transfered = 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++) @@ -1005,56 +592,41 @@ 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 - 1); + dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) + | GRUB_AHCI_INTERRUPT_ON_COMPLETE; 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, - (grub_size_t) ((char *) &dev->command_table[0].prdt[0] - - (char *) &dev->command_table[0])); + (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 scheduled\n"); + grub_dprintf ("ahci", "AHCI command schedulded\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].sata_active = 1; - dev->hba->ports[dev->port].command_issue = 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 ? 20000 : 20000); + endtime = grub_get_time_ms () + (spinup ? 10000 : 1000); while ((dev->hba->ports[dev->port].command_issue & 1)) - if (grub_get_time_ms () > endtime || - (dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK)) + if (grub_get_time_ms () > endtime) { - grub_dprintf ("ahci", "AHCI status <%x %x %x %x>\n", + grub_dprintf ("ahci", "AHCI status <%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); - 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); + err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out"); break; } @@ -1062,7 +634,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].transferred, + dev->command_list[0].transfered, 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]); @@ -1099,7 +671,7 @@ grub_ahci_readwrite (grub_ata_t disk, struct grub_disk_ata_pass_through_parms *parms, int spinup) { - return grub_ahci_readwrite_real (disk->data, parms, spinup, 0); + return grub_ahci_readwrite_real (disk->data, parms, spinup); } static grub_err_t @@ -1121,7 +693,6 @@ 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; @@ -1141,7 +712,13 @@ static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ahci) { - grub_stop_disk_firmware (); + /* 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; + } /* AHCI initialization. */ grub_ahci_initialize (); diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index c94039a3d..10cbc8759 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -80,44 +80,26 @@ 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_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_arcdisk_iterate (int (*hook_in) (const char *name), grub_disk_pull_t pull) { - struct grub_arcdisk_iterate_ctx ctx = { hook, hook_data }; - + 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); + } if (pull != GRUB_DISK_PULL_NONE) return 0; - return grub_arc_iterate_devs (grub_arcdisk_iterate_iter, &ctx, 1); + return grub_arc_iterate_devs (hook, 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) @@ -157,7 +139,9 @@ reopen (const char *name, int writable) static grub_err_t grub_arcdisk_open (const char *name, grub_disk_t disk) { - char *fullname; + char *fullname, *optr; + const char *iptr; + int state = 0; grub_err_t err; grub_arc_err_t r; struct grub_arc_fileinfo info; @@ -165,7 +149,35 @@ 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_arc_alt_name_to_norm (name, RAW_SUFFIX); + 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)); disk->data = fullname; grub_dprintf ("arcdisk", "opening %s\n", fullname); @@ -296,11 +308,11 @@ static struct grub_disk_dev grub_arcdisk_dev = { .name = "arcdisk", .id = GRUB_DISK_DEVICE_ARCDISK_ID, - .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, + .iterate = grub_arcdisk_iterate, + .open = grub_arcdisk_open, + .close = grub_arcdisk_close, + .read = grub_arcdisk_read, + .write = grub_arcdisk_write, .next = 0 }; diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 685f33a19..c0d378c1a 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -108,9 +108,6 @@ 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); info32 = (grub_uint32_t *) info64; info16 = (grub_uint16_t *) info64; @@ -132,7 +129,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); @@ -216,12 +213,6 @@ 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 %d 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) @@ -294,6 +285,7 @@ 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; @@ -309,6 +301,10 @@ 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; @@ -321,10 +317,8 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, } } - if (addressing != GRUB_ATA_CHS) - batch = 256; - else - batch = 1; + if (batch > (ata->maxbuffer >> ata->log_sector_size)) + batch = (ata->maxbuffer >> ata->log_sector_size); while (nsectors < size) { @@ -372,7 +366,7 @@ grub_ata_real_open (int id, int bus) struct grub_ata *ata; grub_ata_dev_t p; - ata = grub_zalloc (sizeof (*ata)); + ata = grub_malloc (sizeof (*ata)); if (!ata) return NULL; for (p = grub_ata_dev_list; p; p = p->next) @@ -388,8 +382,6 @@ 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; } @@ -400,50 +392,40 @@ 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_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_ata_iterate (int (*hook_in) (const char *name), grub_disk_pull_t pull) { - struct grub_ata_iterate_ctx ctx = { hook, hook_data }; + 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; + } + grub_ata_dev_t p; for (p = grub_ata_dev_list; p; p = p->next) - if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull)) + if (p->iterate && p->iterate (hook, pull)) return 1; return 0; } @@ -470,10 +452,6 @@ 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); @@ -510,11 +488,11 @@ static struct grub_disk_dev grub_atadisk_dev = { .name = "ATA", .id = GRUB_DISK_DEVICE_ATA_ID, - .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, + .iterate = grub_ata_iterate, + .open = grub_ata_open, + .close = grub_ata_close, + .read = grub_ata_read, + .write = grub_ata_write, .next = 0 }; @@ -583,47 +561,37 @@ 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_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_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns), grub_disk_pull_t pull) { - struct grub_atapi_iterate_ctx ctx = { hook, hook_data }; + 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; + } + grub_ata_dev_t p; for (p = grub_ata_dev_list; p; p = p->next) - if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull)) + if (p->iterate && p->iterate (hook, pull)) return 1; return 0; } diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 13af84dd1..1ac906d90 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,2019 Free Software Foundation, Inc. + * Copyright (C) 2003,2007,2010,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 @@ -22,13 +22,15 @@ #include #include #include -#include -#include -#include -#include #ifdef GRUB_UTIL +#include +#include +#include +#include #include +#include +#include #endif GRUB_MOD_LICENSE ("GPLv3+"); @@ -52,7 +54,7 @@ static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev) } static grub_cryptodisk_t cryptodisk_list = NULL; -static grub_uint8_t last_cryptodisk_id = 0; +static grub_uint8_t n = 0; static void gf_mul_x (grub_uint8_t *g) @@ -98,7 +100,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 / GRUB_CHAR_BIT - 1] >> (i % GRUB_CHAR_BIT))) & 1) + if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1) grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES); gf_mul_x_be (t); } @@ -110,24 +112,19 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, void *iv) { grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; - grub_size_t blocksize; + grub_uint8_t ivt[cipher->cipher->blocksize]; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - 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) + if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += blocksize, outptr += blocksize) + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) { - grub_memcpy (ivt, inptr, blocksize); + grub_memcpy (ivt, inptr, cipher->cipher->blocksize); cipher->cipher->decrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (outptr, outptr, iv, blocksize); - grub_crypto_xor (iv, ivt, outptr, blocksize); + grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); + grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); } return GPG_ERR_NO_ERROR; } @@ -138,24 +135,19 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher, void *iv) { grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; - grub_size_t blocksize; - if (!cipher->cipher->encrypt) + grub_uint8_t ivt[cipher->cipher->blocksize]; + if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - 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)) + if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += blocksize, outptr += blocksize) + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) { - grub_memcpy (ivt, inptr, blocksize); - grub_crypto_xor (outptr, outptr, iv, blocksize); + grub_memcpy (ivt, inptr, cipher->cipher->blocksize); + grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); cipher->cipher->encrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (iv, ivt, outptr, blocksize); + grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); } return GPG_ERR_NO_ERROR; } @@ -229,9 +221,6 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, 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) @@ -242,7 +231,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, grub_size_t sz = ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) / sizeof (grub_uint32_t)); - grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]; + grub_uint32_t iv[sz]; if (dev->rekey) { @@ -256,7 +245,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, } } - grub_memset (iv, 0, sizeof (iv)); + grub_memset (iv, 0, sz * sizeof (iv[0])); switch (dev->mode_iv) { case GRUB_CRYPTODISK_MODE_IV_NULL: @@ -264,11 +253,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: { grub_uint64_t tmp; - void *ctx; + grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8]; - ctx = grub_zalloc (dev->iv_hash->contextsize); - if (!ctx) - return GPG_ERR_OUT_OF_MEMORY; + grub_memset (ctx, 0, sizeof (ctx)); tmp = grub_cpu_to_le64 (sector << dev->log_sector_size); dev->iv_hash->init (ctx); @@ -277,12 +264,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, 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); - /* FALLTHROUGH */ case GRUB_CRYPTODISK_MODE_IV_PLAIN: iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); break; @@ -380,13 +365,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, break; case GRUB_CRYPTODISK_MODE_ECB: if (do_encrypt) - err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size)); else - err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); - if (err) - return err; + grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size)); break; default: return GPG_ERR_NOT_IMPLEMENTED; @@ -404,167 +387,6 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, return grub_cryptodisk_endecrypt (dev, data, len, sector, 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: %d", - 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: %d", - 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: %d", - 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, "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); - /* 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 grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize) { @@ -581,16 +403,12 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke 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[GRUB_CRYPTO_MAX_MDLEN]; - if (essiv_keysize > GRUB_CRYPTO_MAX_MDLEN) - return GPG_ERR_INV_ARG; + grub_uint8_t hashed_key[essiv_keysize]; grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); err = grub_crypto_cipher_set_key (dev->essiv_cipher, @@ -630,8 +448,8 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke } static int -grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) +grub_cryptodisk_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { grub_cryptodisk_t i; @@ -642,7 +460,7 @@ grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, { char buf[30]; grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id); - if (hook (buf, hook_data)) + if (hook (buf)) return 1; } @@ -681,11 +499,11 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) #ifdef GRUB_UTIL if (dev->cheat) { - 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)) + if (dev->cheat_fd == -1) + dev->cheat_fd = open (dev->cheat, O_RDONLY); + if (dev->cheat_fd == -1) return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"), - dev->cheat, grub_util_fd_strerror ()); + dev->cheat, strerror (errno)); } #endif @@ -700,7 +518,6 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) disk->data = dev; disk->total_sectors = dev->total_length; - disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; disk->id = dev->id; dev->ref++; return GRUB_ERR_NONE; @@ -719,8 +536,8 @@ grub_cryptodisk_close (grub_disk_t disk) #ifdef GRUB_UTIL if (dev->cheat) { - grub_util_fd_close (dev->cheat_fd); - dev->cheat_fd = GRUB_UTIL_FD_INVALID; + close (dev->cheat_fd); + dev->cheat_fd = -1; } #endif grub_disk_close (dev->source_disk); @@ -738,15 +555,14 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, #ifdef GRUB_UTIL if (dev->cheat) { - 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 ()); + err = grub_util_fd_seek (dev->cheat_fd, dev->cheat, + sector << disk->log_sector_size); + if (err) + return err; 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, grub_util_fd_strerror ()); + dev->cheat, strerror (errno)); return GRUB_ERR_NONE; } #endif @@ -757,8 +573,9 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, size, sector, dev->offset); err = grub_disk_read (dev->source_disk, - grub_disk_from_native_sector (disk, sector + dev->offset), - 0, size << disk->log_sector_size, buf); + (sector << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + dev->offset, 0, + size << disk->log_sector_size, buf); if (err) { grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err); @@ -782,15 +599,14 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, #ifdef GRUB_UTIL if (dev->cheat) { - 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 ()); + err = grub_util_fd_seek (dev->cheat_fd, dev->cheat, + sector << disk->log_sector_size); + if (err) + return err; 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, grub_util_fd_strerror ()); + dev->cheat, strerror (errno)); return GRUB_ERR_NONE; } #endif @@ -814,14 +630,10 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, return grub_crypto_gcry_error (gcry_err); } - /* Since ->write was called so disk.mod is loaded but be paranoid */ - sector = sector + dev->offset; - 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"); + 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); grub_free (tmp); return err; } @@ -875,10 +687,9 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name, return grub_errno; } - newdev->id = last_cryptodisk_id++; + newdev->id = n++; 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; @@ -901,9 +712,7 @@ 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) - if ((disk->partition && grub_partition_get_start (disk->partition) == dev->partition_start) || - (!disk->partition && dev->partition_start == 0)) - return dev; + return dev; return NULL; } @@ -921,11 +730,10 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, return grub_errno; } - newdev->cheat_fd = GRUB_UTIL_FD_INVALID; + newdev->cheat_fd = -1; newdev->source_id = source->id; newdev->source_dev_id = source->dev->id; - newdev->partition_start = grub_partition_get_start (source->partition); - newdev->id = last_cryptodisk_id++; + newdev->id = n++; newdev->next = cryptodisk_list; cryptodisk_list = newdev; @@ -933,34 +741,31 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, } void -grub_util_cryptodisk_get_abstraction (grub_disk_t disk, - void (*cb) (const char *val, void *data), - void *data) +grub_util_cryptodisk_print_abstraction (grub_disk_t disk) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - cb ("cryptodisk", data); - cb (dev->modname, data); + grub_printf ("cryptodisk %s ", dev->modname); if (dev->cipher) - cb (dev->cipher->cipher->modname, data); + grub_printf ("%s ", dev->cipher->cipher->modname); if (dev->secondary_cipher) - cb (dev->secondary_cipher->cipher->modname, data); + grub_printf ("%s ", dev->secondary_cipher->cipher->modname); if (dev->essiv_cipher) - cb (dev->essiv_cipher->cipher->modname, data); + grub_printf ("%s ", dev->essiv_cipher->cipher->modname); if (dev->hash) - cb (dev->hash->modname, data); + grub_printf ("%s ", dev->hash->modname); if (dev->essiv_hash) - cb (dev->essiv_hash->modname, data); + grub_printf ("%s ", dev->essiv_hash->modname); if (dev->iv_hash) - cb (dev->iv_hash->modname, data); + grub_printf ("%s ", dev->iv_hash->modname); } -const char * -grub_util_cryptodisk_get_uuid (grub_disk_t disk) +void +grub_util_cryptodisk_print_uuid (grub_disk_t disk) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - return dev->uuid; + grub_printf ("%s ", dev->uuid); } #endif @@ -1061,8 +866,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat) #endif static int -grub_cryptodisk_scan_device (const char *name, - void *data __attribute__ ((unused))) +grub_cryptodisk_scan_device (const char *name) { grub_err_t err; grub_disk_t source; @@ -1070,10 +874,7 @@ grub_cryptodisk_scan_device (const char *name, /* Try to open disk. */ source = grub_disk_open (name); if (!source) - { - grub_print_error (); - return 0; - } + return grub_errno; err = grub_cryptodisk_scan_device_real (name, source); @@ -1107,7 +908,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) check_boot = state[2].set; search_uuid = args[0]; - grub_device_iterate (&grub_cryptodisk_scan_device, NULL); + grub_device_iterate (&grub_cryptodisk_scan_device); search_uuid = NULL; if (!have_it) @@ -1118,7 +919,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) { search_uuid = NULL; check_boot = state[2].set; - grub_device_iterate (&grub_cryptodisk_scan_device, NULL); + grub_device_iterate (&grub_cryptodisk_scan_device); search_uuid = NULL; return GRUB_ERR_NONE; } @@ -1127,44 +928,24 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) 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; - 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); + disk = grub_disk_open (args[0]); if (!disk) - { - if (disklast) - *disklast = ')'; - return grub_errno; - } + 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); - if (disklast) - *disklast = ')'; return GRUB_ERR_NONE; } - err = grub_cryptodisk_scan_device_real (diskname, disk); + err = grub_cryptodisk_scan_device_real (args[0], disk); grub_disk_close (disk); - if (disklast) - *disklast = ')'; return err; } @@ -1173,126 +954,17 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) static struct grub_disk_dev grub_cryptodisk_dev = { .name = "cryptodisk", .id = GRUB_DISK_DEVICE_CRYPTODISK_ID, - .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, + .iterate = grub_cryptodisk_iterate, + .open = grub_cryptodisk_open, + .close = grub_cryptodisk_close, + .read = grub_cryptodisk_read, + .write = grub_cryptodisk_write, #ifdef GRUB_UTIL - .disk_memberlist = grub_cryptodisk_memberlist, + .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; - char *ptr, *ret; - - *sz = 0; - - for (i = cryptodisk_list; i != NULL; i = i->next) - if (grub_strcmp (i->modname, "luks") == 0) - { - size += sizeof ("luks_mount "); - size += grub_strlen (i->uuid); - size += grub_strlen (i->cipher->cipher->name); - size += 54; - if (i->essiv_hash) - size += grub_strlen (i->essiv_hash->name); - size += i->keysize * 2; - } - - ret = grub_malloc (size + 1); - if (!ret) - return 0; - - ptr = ret; - - for (i = cryptodisk_list; i != NULL; i = i->next) - if (grub_strcmp (i->modname, "luks") == 0) - { - unsigned j; - const char *iptr; - ptr = grub_stpcpy (ptr, "luks_mount "); - ptr = grub_stpcpy (ptr, i->uuid); - *ptr++ = ' '; - grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset); - while (*ptr) - 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; -} - -struct grub_procfs_entry luks_script = -{ - .name = "luks_script", - .get_contents = luks_script_get -}; - static grub_extcmd_t cmd; GRUB_MOD_INIT (cryptodisk) @@ -1301,13 +973,10 @@ GRUB_MOD_INIT (cryptodisk) cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, N_("SOURCE|-u UUID|-a|-b"), N_("Mount a crypto device."), options); - grub_procfs_register ("luks_script", &luks_script); } GRUB_MOD_FINI (cryptodisk) { 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 86557f923..6e9745e35 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -71,12 +71,10 @@ 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; @@ -119,72 +117,68 @@ 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_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; -} - 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; @@ -202,15 +196,23 @@ scan_disk (const char *name, int accept_diskfilter) scan_depth--; return 0; } - scan_disk_partition_iter (disk, 0, (void *) name); - grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name); + if (hook (disk, 0)) + { + scan_depth--; + return 1; + } + if (grub_partition_iterate (disk, hook)) + { + scan_depth--; + return 1; + } grub_disk_close (disk); scan_depth--; return 0; } static int -scan_disk_hook (const char *name, void *data __attribute__ ((unused))) +scan_disk_hook (const char *name) { return scan_disk (name, 0); } @@ -222,45 +224,33 @@ 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->disk_iterate) + && p->iterate) { - if ((p->disk_iterate) (scan_disk_hook, NULL, pull)) + if ((p->iterate) (scan_disk_hook, pull)) return; if (arname && is_lv_readable (find_lv (arname), 1)) return; } - scan_depth = 0; - need_rescan = 1; - while (need_rescan && scan_depth++ < 100) + for (vg = array_list; vg; vg = vg->next) { - 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 (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; + } } - - if (need_rescan) - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "DISKFILTER scan depth exceeded"); } static int -grub_diskfilter_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) +grub_diskfilter_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { struct grub_diskfilter_vg *array; int islcnt = 0; @@ -281,7 +271,7 @@ grub_diskfilter_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, for (lv = array->lvs; lv; lv = lv->next) if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt) { - if (hook (lv->fullname, hook_data)) + if (hook (lv->fullname)) return 1; } } @@ -311,9 +301,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->disk_iterate) + && p->iterate) { - (p->disk_iterate) (scan_disk_hook, NULL, pull); + (p->iterate) (scan_disk_hook, pull); while (pv && pv->disk) pv = pv->next; } @@ -355,9 +345,7 @@ grub_diskfilter_memberlist (grub_disk_t disk) } void -grub_diskfilter_get_partmap (grub_disk_t disk, - void (*cb) (const char *pm, void *data), - void *data) +grub_diskfilter_print_partmap (grub_disk_t disk) { struct grub_diskfilter_lv *lv = disk->data; struct grub_diskfilter_pv *pv; @@ -379,7 +367,7 @@ grub_diskfilter_get_partmap (grub_disk_t disk, continue; } for (s = 0; pv->partmaps[s]; s++) - cb (pv->partmaps[s], data); + grub_printf ("%s ", pv->partmaps[s]); } } @@ -392,12 +380,16 @@ grub_diskfilter_getname (struct grub_disk *disk) } #endif -static inline char -hex2ascii (int c) +static inline int +ascii2hex (char c) { - if (c >= 10) - return 'a' + c - 10; - return c + '0'; + 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; } static struct grub_diskfilter_lv * @@ -406,12 +398,30 @@ 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) - || (lv->idname && grub_strcmp (lv->idname, name) == 0)) + if (lv->fullname && grub_strcmp (lv->fullname, name) == 0 && is_lv_readable (lv, 0)) return lv; } @@ -423,7 +433,9 @@ grub_diskfilter_open (const char *name, grub_disk_t disk) { struct grub_diskfilter_lv *lv; - if (!is_valid_diskfilter_name (name)) + 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) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown DISKFILTER device %s", name); @@ -448,7 +460,6 @@ 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; } @@ -485,96 +496,6 @@ 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) @@ -586,7 +507,6 @@ 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: { @@ -911,8 +831,7 @@ grub_diskfilter_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "diskfilter writes are not supported"); + return GRUB_ERR_NOT_IMPLEMENTED_YET; } struct grub_diskfilter_vg * @@ -941,23 +860,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) for (lv = vg->lvs; lv; lv = lv->next) { - grub_err_t err; - - /* 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; - } - - err = validate_lv(lv); - if (err) - return err; lv->number = lv_num++; if (lv->fullname) @@ -969,8 +871,7 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) for (p = vgp->lvs; p; p = p->next) { int cur_num; - char *num; - const char *end; + char *num, *end; if (!p->fullname) continue; if (grub_strncmp (p->fullname, lv->fullname, len) != 0) @@ -999,6 +900,12 @@ 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; @@ -1008,13 +915,12 @@ 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, - const char *name, grub_uint64_t disk_size, + 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; grub_uint64_t totsize; struct grub_diskfilter_pv *pv; grub_err_t err; @@ -1031,11 +937,6 @@ 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); } @@ -1045,11 +946,10 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, case 4: case 5: case 6: - totsize = (nmemb - ((unsigned) level / 3U)) * disk_size; + totsize = (nmemb - level / 3) * disk_size; break; default: - grub_free (uuid); return NULL; } @@ -1063,7 +963,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, array->lvs->segments->extent_count = totsize; } - if (array->lvs && array->lvs->segments + if (array->lvs->segments && array->lvs->segments->raid_member_size > disk_size) array->lvs->segments->raid_member_size = disk_size; @@ -1072,10 +972,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, } array = grub_zalloc (sizeof (*array)); if (!array) - { - grub_free (uuid); - return NULL; - } + return NULL; array->uuid = uuid; array->uuid_len = uuidlen; if (name) @@ -1090,37 +987,14 @@ 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; - 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; - - array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen); - 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->name = array->name; + array->lvs->fullname = array->name; array->lvs->size = totsize; @@ -1135,7 +1009,7 @@ 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_calloc (nmemb, sizeof (array->lvs->segments->nodes[0])); + = grub_zalloc (nmemb * sizeof (array->lvs->segments->nodes[0])); array->lvs->segments->stripe_size = stripe_size; for (i = 0; i < nmemb; i++) { @@ -1156,26 +1030,13 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, return array; fail: - 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); - } + 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; } @@ -1188,15 +1049,10 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, { struct grub_diskfilter_pv *pv; - 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_get_size (disk), + grub_dprintf ("diskfilter", "Inserting %s into %s (%s)\n", disk->name, array->name, diskfilter->name); #ifdef GRUB_UTIL - 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_get_size (disk), + grub_util_info ("Inserting %s into %s (%s)\n", disk->name, array->name, diskfilter->name); array->driver = diskfilter; #endif @@ -1227,7 +1083,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 = xcalloc (s, sizeof (pv->partmaps[0])); + pv->partmaps = xmalloc (s * sizeof (pv->partmaps[0])); s = 0; for (p = disk->partition; p; p = p->parent) pv->partmaps[s++] = xstrdup (p->partmap->name); @@ -1240,7 +1096,14 @@ 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; + { + lv->became_readable_at = ++inscnt; + if (is_lv_readable (lv, 1)) + { + scan_disk (lv->fullname, 1); + lv->scanned = 1; + } + } break; } @@ -1267,9 +1130,6 @@ 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); } @@ -1278,9 +1138,10 @@ free_array (void) { unsigned i; vg->lvs = lv->next; - grub_free (lv->fullname); - grub_free (lv->name); - grub_free (lv->idname); + if (lv->name != lv->fullname) + grub_free (lv->fullname); + if (lv->name != vg->name) + grub_free (lv->name); for (i = 0; i < lv->segment_count; i++) grub_free (lv->segments[i].nodes); grub_free (lv->segments); @@ -1326,14 +1187,14 @@ static struct grub_disk_dev grub_diskfilter_dev = { .name = "diskfilter", .id = GRUB_DISK_DEVICE_DISKFILTER_ID, - .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, + .iterate = grub_diskfilter_iterate, + .open = grub_diskfilter_open, + .close = grub_diskfilter_close, + .read = grub_diskfilter_read, + .write = grub_diskfilter_write, #ifdef GRUB_UTIL - .disk_memberlist = grub_diskfilter_memberlist, - .disk_raidname = grub_diskfilter_getname, + .memberlist = grub_diskfilter_memberlist, + .raidname = grub_diskfilter_getname, #endif .next = 0 }; diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c index 060279124..7b03e9036 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 */ -} GRUB_PACKED; +} __attribute__ ((packed)); static struct grub_diskfilter_vg * grub_dmraid_nv_detect (grub_disk_t disk, @@ -98,9 +98,8 @@ 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) @@ -126,17 +125,11 @@ grub_dmraid_nv_detect (grub_disk_t disk, 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; - if (total_volumes == 0) - /* Not RAID. */ - return NULL; - disk_size = capacity / total_volumes; + disk_size = sb.capacity / sb.array.total_volumes; break; case NV_LEVEL_1: @@ -146,10 +139,8 @@ grub_dmraid_nv_detect (grub_disk_t disk, case NV_LEVEL_5: level = 5; - if (total_volumes == 0 || total_volumes == 1) - /* Not RAID. */ - return NULL; - disk_size = capacity / (total_volumes - 1); + layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; + disk_size = sb.capacity / (sb.array.total_volumes - 1); break; default: @@ -172,9 +163,8 @@ grub_dmraid_nv_detect (grub_disk_t disk, return grub_diskfilter_make_raid (sizeof (sb.array.signature), uuid, sb.array.total_volumes, - "nv", disk_size, - sb.array.stripe_block_size, - GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC, + NULL, disk_size, + sb.array.stripe_block_size, layout, level); } diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 9e20af70e..d9d788c41 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -43,6 +43,47 @@ 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) { @@ -69,7 +110,7 @@ make_devices (void) if (! dp) continue; - ldp = grub_efi_find_last_device_path (dp); + ldp = find_last_device_path (dp); if (! ldp) /* This is empty. Why? */ continue; @@ -80,26 +121,11 @@ 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; } @@ -124,17 +150,15 @@ find_parent_device (struct grub_efidisk_data *devices, grub_efi_device_path_t *dp, *ldp; struct grub_efidisk_data *parent; - dp = grub_efi_duplicate_device_path (d->device_path); + dp = duplicate_device_path (d->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 = sizeof (*ldp); + ldp->length[0] = sizeof (*ldp); + ldp->length[1] = 0; for (parent = devices; parent; parent = parent->next) { @@ -151,31 +175,39 @@ find_parent_device (struct grub_efidisk_data *devices, } static int -is_child (struct grub_efidisk_data *child, - struct grub_efidisk_data *parent) +iterate_child_devices (struct grub_efidisk_data *devices, + struct grub_efidisk_data *d, + int (*hook) (struct grub_efidisk_data *child)) { - grub_efi_device_path_t *dp, *ldp; - int ret; + struct grub_efidisk_data *p; - dp = grub_efi_duplicate_device_path (child->device_path); - if (! dp) - return 0; + for (p = devices; p; p = p->next) + { + grub_efi_device_path_t *dp, *ldp; - ldp = grub_efi_find_last_device_path (dp); - if (! ldp) - return 0; + dp = duplicate_device_path (p->device_path); + if (! dp) + return 0; - ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - ldp->length = sizeof (*ldp); + 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; - ret = (grub_efi_compare_device_paths (dp, parent->device_path) == 0); - grub_free (dp); - return ret; + if (grub_efi_compare_device_paths (dp, d->device_path) == 0) + if (hook (p)) + { + grub_free (dp); + return 1; + } + + grub_free (dp); + } + + return 0; } -#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) @@ -187,8 +219,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) { int ret; - ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path), - grub_efi_find_last_device_path (d->device_path)); + ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), + find_last_device_path (d->device_path)); if (ret == 0) ret = grub_efi_compare_device_paths ((*p)->device_path, d->device_path); @@ -230,7 +262,7 @@ name_devices (struct grub_efidisk_data *devices) { case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE: is_hard_drive = 1; - /* Intentionally fall through. */ + /* Fall through by intention. */ case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: { struct grub_efidisk_data *parent, *parent2; @@ -307,43 +339,18 @@ 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; - /* 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; - const struct grub_efi_guid 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) + if (m->logical_partition) { + /* Only one partition in a non-media device. Assume that this + is a floppy drive. */ #ifdef DEBUG_NAMES - grub_printf ("adding a floppy: "); + grub_printf ("adding a floppy by guessing: "); grub_efi_print_device_path (d->device_path); #endif add_device (&fd_devices, d); @@ -397,7 +404,7 @@ enumerate_disks (void) } static int -grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, +grub_efidisk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { struct grub_efidisk_data *d; @@ -411,7 +418,7 @@ grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, { grub_snprintf (buf, sizeof (buf), "hd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf, hook_data)) + if (hook (buf)) return 1; } break; @@ -420,7 +427,7 @@ grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, { grub_snprintf (buf, sizeof (buf), "fd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf, hook_data)) + if (hook (buf)) return 1; } @@ -428,7 +435,7 @@ grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, { grub_snprintf (buf, sizeof (buf), "cd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf, hook_data)) + if (hook (buf)) return 1; } break; @@ -504,22 +511,13 @@ 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 << GRUB_CHAR_BIT) | name[0]); + disk->id = ((num << 8) | 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, 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); - + grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", + m, (unsigned long long) m->last_block, m->block_size); 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); @@ -540,65 +538,27 @@ 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; - - /* Set alignment to 1 if 0 specified */ - io_align = bio->media->io_align ? bio->media->io_align : 1; - 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 = efi_call_5 ((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 = 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) + 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) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx from `%s'"), (unsigned long long) sector, @@ -611,17 +571,23 @@ 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 = 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) + 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) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx to `%s'"), (unsigned long long) sector, disk->name); @@ -633,35 +599,30 @@ static struct grub_disk_dev grub_efidisk_dev = { .name = "efidisk", .id = GRUB_DISK_DEVICE_EFIDISK_ID, - .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, + .iterate = grub_efidisk_iterate, + .open = grub_efidisk_open, + .close = grub_efidisk_close, + .read = grub_efidisk_read, + .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) @@ -694,31 +655,32 @@ grub_efidisk_get_device_handle (grub_disk_t disk) { struct grub_efidisk_data *devices; grub_efi_handle_t handle = 0; - struct grub_efidisk_data *c; + auto int find_partition (struct grub_efidisk_data *c); - devices = make_devices (); - FOR_CHILDREN (c, devices) + int find_partition (struct grub_efidisk_data *c) { - grub_efi_hard_drive_device_path_t *hd; + grub_efi_hard_drive_device_path_t hd; - hd = (grub_efi_hard_drive_device_path_t *) c->last_device_path; + grub_memcpy (&hd, c->last_device_path, sizeof (hd)); 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 << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS))) + && (grub_partition_get_start (disk->partition) + == hd.partition_start) && (grub_partition_get_len (disk->partition) - == (hd->partition_size << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)))) + == hd.partition_size)) { handle = c->handle; - break; + return 1; } + + return 0; } + devices = make_devices (); + iterate_child_devices (devices, d, find_partition); free_devices (devices); if (handle != 0) @@ -774,35 +736,6 @@ 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) { @@ -813,48 +746,50 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (! dp) return 0; - ldp = grub_efi_find_last_device_path (dp); + ldp = 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_CDROM_DEVICE_PATH_SUBTYPE - || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) + == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { - struct grub_efidisk_get_device_name_ctx ctx; + char *partition_name = NULL; char *dev_name; - grub_efi_device_path_t *dup_dp; + grub_efi_device_path_t *dup_dp, *dup_ldp; + grub_efi_hard_drive_device_path_t hd; grub_disk_t parent = 0; - /* It is necessary to duplicate the device path so that GRUB - can overwrite it. */ - dup_dp = grub_efi_duplicate_device_path (dp); - if (! dup_dp) - return 0; + auto int find_partition (grub_disk_t disk, const grub_partition_t part); - while (1) + /* Find the identical partition. */ + int find_partition (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t part) { - grub_efi_device_path_t *dup_ldp; - dup_ldp = grub_efi_find_last_device_path (dup_dp); - if (! dup_ldp) - break; + 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; + } - 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)) - { - grub_free (dup_dp); return 0; } + /* It is necessary to duplicate the device path so that GRUB + can overwrite it. */ + dup_dp = 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; + + if (!get_diskname_from_path (dup_dp, device_name)) + return 0; parent = grub_disk_open (device_name); grub_free (dup_dp); @@ -862,41 +797,34 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) return 0; /* Find a partition which matches the hard drive device path. */ - 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_get_size (parent)) + grub_memcpy (&hd, ldp, sizeof (hd)); + if (hd.partition_start == 0 + && hd.partition_size == grub_disk_get_size (parent)) { dev_name = grub_strdup (parent->name); } else { - grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, - &ctx); + grub_partition_iterate (parent, find_partition); - if (! ctx.partition_name) + if (! 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 grub_strdup (device_name); + return 0; } - dev_name = grub_xasprintf ("%s,%s", parent->name, - ctx.partition_name); - grub_free (ctx.partition_name); + dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name); + grub_free (partition_name); } grub_disk_close (parent); return dev_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); + else + { + /* This should be an 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 e9d23299a..f9315df0d 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]; -} GRUB_PACKED; +} __attribute__ ((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]; -} GRUB_PACKED; +} __attribute__ ((packed)); enum { @@ -144,35 +144,42 @@ geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) const struct { char magic[4]; grub_uint64_t zone; - } GRUB_PACKED tohash + } __attribute__ ((packed)) tohash = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) }; - GRUB_PROPERLY_ALIGNED_ARRAY (key, GRUB_CRYPTO_MAX_MDLEN); - - if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) - return GPG_ERR_INV_ARG; + grub_uint64_t key[(dev->hash->mdlen + 7) / 8]; 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 gcry_err; + return grub_crypto_gcry_error (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; +} + static inline gcry_err_code_t make_uuid (const struct grub_geli_phdr *header, char *uuid) { - grub_uint8_t uuidbin[GRUB_CRYPTODISK_MAX_UUID_LENGTH]; + grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen]; 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); @@ -180,7 +187,7 @@ make_uuid (const struct grub_geli_phdr *header, return err; optr = uuid; - for (iptr = uuidbin; iptr < &uuidbin[GRUB_MD_SHA256->mdlen]; iptr++) + for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++) { grub_snprintf (optr, 3, "%02x", *iptr); optr += 2; @@ -191,13 +198,19 @@ 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) { - grub_util_fd_t fd; + int fd = open (dev, O_RDONLY); grub_uint64_t s; unsigned log_secsize; grub_uint8_t hdr[512]; @@ -205,37 +218,29 @@ grub_util_get_geli_uuid (const char *dev) char *uuid; gcry_err_code_t err; - fd = grub_util_fd_open (dev, GRUB_UTIL_FD_O_RDONLY); - - if (!GRUB_UTIL_FD_IS_VALID (fd)) + if (fd < 0) return NULL; s = grub_util_get_fd_size (fd, dev, &log_secsize); s >>= log_secsize; - if (grub_util_fd_seek (fd, (s << log_secsize) - 512) < 0) - grub_util_error ("%s", _("couldn't read ELI metadata")); + grub_util_fd_seek (fd, dev, (s << log_secsize) - 512); 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) > 7 + || grub_le_to_cpu32 (header->version) > 5 || grub_le_to_cpu32 (header->version) < 1) grub_util_error ("%s", _("wrong ELI magic or version")); err = make_uuid ((void *) &hdr, uuid); if (err) - { - grub_free (uuid); - return NULL; - } + return NULL; return uuid; } @@ -251,13 +256,10 @@ 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_CRYPTODISK_MAX_UUID_LENGTH]; + char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; grub_disk_addr_t sector; grub_err_t err; - if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH) - return NULL; - sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) return NULL; @@ -269,7 +271,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) > 7 + || grub_le_to_cpu32 (header.version) > 5 || grub_le_to_cpu32 (header.version) < 1) { grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]); @@ -336,29 +338,19 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, { secondary_cipher = grub_crypto_cipher_open (ciph); if (!secondary_cipher) - { - grub_crypto_cipher_close (cipher); - return NULL; - } - + 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) - { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (secondary_cipher); - return NULL; - } + return NULL; newdev->cipher = cipher; newdev->secondary_cipher = secondary_cipher; newdev->offset = 0; @@ -389,7 +381,9 @@ 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; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); @@ -401,11 +395,10 @@ static grub_err_t recover_key (grub_disk_t source, grub_cryptodisk_t dev) { grub_size_t keysize; - 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]; + 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] = ""; unsigned i; gcry_err_code_t gcry_err; @@ -414,12 +407,6 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) grub_disk_addr_t sector; grub_err_t err; - 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_get_size (source); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) return grub_error (GRUB_ERR_BUG, "not a geli"); @@ -429,7 +416,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) if (err) return err; - keysize = grub_le_to_cpu16 (header.keylen) / GRUB_CHAR_BIT; + keysize = grub_le_to_cpu16 (header.keylen) / 8; grub_memset (zero, 0, sizeof (zero)); grub_puts_ (N_("Attempting to decrypt master key...")); @@ -481,12 +468,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) } gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, - dev->hash->mdlen, "\1", 1, digest); + sizeof (geomkey), "\1", 1, digest); if (gcry_err) return grub_crypto_gcry_error (gcry_err); gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, - dev->hash->mdlen, "\0", 1, verify_key); + sizeof (geomkey), "\0", 1, verify_key); if (gcry_err) return grub_crypto_gcry_error (gcry_err); @@ -496,7 +483,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[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t key_hmac[dev->hash->mdlen]; /* Check if keyslot is enabled. */ if (! (header.keys_used & (1 << i))) @@ -517,7 +504,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, - dev->hash->mdlen, + sizeof (verify_key), &candidate_key, (sizeof (candidate_key) - sizeof (candidate_key.hmac)), @@ -529,19 +516,6 @@ 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) { @@ -558,13 +532,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; - - grub_memcpy (dev->rekey_key, geli_cipher_key, - sizeof (geli_cipher_key)); + /* 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)); dev->rekey_derived_size = real_keysize; dev->last_rekey = -1; COMPILE_TIME_ASSERT (sizeof (dev->rekey_key) - >= sizeof (geli_cipher_key)); + >= sizeof (candidate_key.iv_key)); } dev->iv_prefix_len = sizeof (candidate_key.iv_key); diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index c151d225d..5ee0d2e56 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -20,24 +20,20 @@ /* 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 (grub_disk_dev_iterate_hook_t hook, void *hook_data, +grub_host_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { if (pull != GRUB_DISK_PULL_NONE) return 0; - if (hook ("host", hook_data)) + if (hook ("host")) return 1; return 0; } @@ -49,7 +45,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 = 0; + disk->id = (unsigned long) "host"; disk->data = 0; @@ -84,11 +80,11 @@ static struct grub_disk_dev grub_host_dev = /* The only important line in this file :-) */ .name = "host", .id = GRUB_DISK_DEVICE_HOST_ID, - .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, + .iterate = grub_host_iterate, + .open = grub_host_open, + .close = grub_host_close, + .read = grub_host_read, + .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 8ca250c77..7ca89e3f7 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -272,22 +272,21 @@ grub_biosdisk_get_drive (const char *name) } static int -grub_biosdisk_call_hook (grub_disk_dev_iterate_hook_t hook, void *hook_data, - int drive) +grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) { char name[10]; if (cd_drive && drive == cd_drive) - return hook ("cd", hook_data); + return hook ("cd"); grub_snprintf (name, sizeof (name), (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); - return hook (name, hook_data); + return hook (name); } static int -grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) +grub_biosdisk_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull __attribute__ ((unused))) { int num_floppies; int drive; @@ -305,7 +304,7 @@ grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, break; } - if (grub_biosdisk_call_hook (hook, hook_data, drive)) + if (grub_biosdisk_call_hook (hook, drive)) return 1; } return 0; @@ -313,14 +312,14 @@ grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, case GRUB_DISK_PULL_REMOVABLE: if (cd_drive) { - if (grub_biosdisk_call_hook (hook, hook_data, cd_drive)) + if (grub_biosdisk_call_hook (hook, 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, hook_data, drive)) + if (grub_biosdisk_call_hook (hook, drive)) return 1; return 0; default: @@ -382,8 +381,7 @@ 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 = ((grub_uint64_t) drp->cylinders) - * drp->heads * drp->sectors; + total_sectors = 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 @@ -420,24 +418,11 @@ 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 = ((grub_uint64_t) data->cylinders) - * data->heads * data->sectors; + total_sectors = 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; @@ -462,14 +447,6 @@ 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; @@ -570,6 +547,10 @@ get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector) 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; } @@ -637,11 +618,11 @@ static struct grub_disk_dev grub_biosdisk_dev = { .name = "biosdisk", .id = GRUB_DISK_DEVICE_BIOSDISK_ID, - .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, + .iterate = grub_biosdisk_iterate, + .open = grub_biosdisk_open, + .close = grub_biosdisk_close, + .read = grub_biosdisk_read, + .write = grub_biosdisk_write, .next = 0 }; diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index bcf3a06f4..ad30852ec 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -33,32 +33,25 @@ struct grub_nand_data }; static int -grub_nand_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, +grub_nand_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { - static int have_nand = -1; + 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; + } if (pull != GRUB_DISK_PULL_NONE) return 0; - 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; + return grub_devalias_iterate (dev_iterate); } static grub_err_t @@ -113,11 +106,6 @@ 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"; @@ -215,19 +203,18 @@ grub_nand_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "nand write is not supported"); + return GRUB_ERR_NOT_IMPLEMENTED_YET; } static struct grub_disk_dev grub_nand_dev = { .name = "nand", .id = GRUB_DISK_DEVICE_NAND_ID, - .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, + .iterate = grub_nand_iterate, + .open = grub_nand_open, + .close = grub_nand_close, + .read = grub_nand_read, + .write = grub_nand_write, .next = 0 }; diff --git a/grub-core/disk/ieee1275/obdisk.c b/grub-core/disk/ieee1275/obdisk.c deleted file mode 100644 index ec413c3fd..000000000 --- a/grub-core/disk/ieee1275/obdisk.c +++ /dev/null @@ -1,1076 +0,0 @@ -/* 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 - -#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 = grub_malloc (grub_strlen (name) + 1); - char *p, c; - - 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; - - if (path == NULL) - return NULL; - - encoding = grub_malloc (sizeof (IEEE1275_DEV) + count_commas (path) + - grub_strlen (path) + 1); - - 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); - - real_canon = grub_malloc (real_unit_str_len); - - 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) -{ - 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. - */ - dev->raw_name = grub_malloc (grub_strlen (cname) + sizeof (":nolabel")); - - if (dev->raw_name == NULL) - goto failed; - - grub_snprintf (dev->raw_name, grub_strlen (cname) + sizeof (":nolabel"), - "%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) - { - for (dev->log_sector_size = 0; - (1U << dev->log_sector_size) < dev->block_size; - dev->log_sector_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 03674cb47..b0aa7ec7b 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -31,22 +31,12 @@ 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]; @@ -78,67 +68,18 @@ 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; - p = grub_zalloc (sizeof (*p)); + p = grub_malloc(sizeof (*p)); if (!p) return NULL; p->devpath = devpath; - - p->grub_devpath = grub_malloc (sizeof ("ieee1275/") - + 2 * grub_strlen (p->devpath)); - - if (!p->grub_devpath) - { - grub_free (p); - return NULL; - } - - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) - { - p->open_path = grub_malloc (grub_strlen (p->devpath) + 3); - 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) { @@ -150,10 +91,7 @@ ofdisk_hash_add (char *devpath, char *curcan) if (!curcan) { - p->shortest = p->devpath; - p->grub_shortest = p->grub_devpath; - if (check_string_removable (devpath)) - p->is_removable = 1; + p->shortest = devpath; return p; } @@ -163,215 +101,124 @@ 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 = p->devpath; - pcan->grub_shortest = p->grub_devpath; - } + pcan->shortest = devpath; } return p; } -static void -dev_iterate_real (const char *name, const char *path) -{ - 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) - { - grub_errno = GRUB_ERR_NONE; - grub_free (name_dup); - grub_free (can); - return; - } - 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; - - 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; - } - - buf = grub_malloc (grub_strlen (alias->path) + 32); - if (!buf) - 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; - - buf = grub_malloc (grub_strlen (alias->path) + - sizeof ("/disk@7766554433221100")); - 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; - } - - { - struct grub_ieee1275_devalias child; - - FOR_IEEE1275_DEVCHILDREN(alias->path, child) - dev_iterate (&child); - } -} - static void scan (void) { - struct grub_ieee1275_devalias alias; - FOR_IEEE1275_DEVALIASES(alias) + auto int dev_iterate_real (const char *name, const char *path); + + int dev_iterate_real (const char *name, const char *path) { - if (grub_strcmp (alias.type, "block") != 0) - continue; - dev_iterate_real (alias.name, alias.path); + 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) + { + grub_errno = GRUB_ERR_NONE; + grub_free (name_dup); + grub_free (can); + return 0; + } + op = ofdisk_hash_add (name_dup, can); + } + return 0; } - FOR_IEEE1275_DEVCHILDREN("/", alias) - dev_iterate (&alias); + 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); + } + + 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; + + 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); } static int -grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, +grub_ofdisk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { unsigned i; @@ -414,11 +261,24 @@ grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, } } - if (!ent->is_boot && ent->is_removable) + if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) continue; - if (hook (ent->grub_shortest, hook_data)) - return 1; + { + 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; + } } } return 0; @@ -459,8 +319,6 @@ 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, @@ -501,31 +359,14 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) op = ofdisk_hash_find (devpath); if (!op) op = ofdisk_hash_add (devpath, NULL); - if (!op) - { - grub_free (devpath); - return grub_errno; - } - disk->id = (unsigned long) op; - 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) - { - for (disk->log_sector_size = 0; - (1U << disk->log_sector_size) < block_size; - disk->log_sector_size++); - } else - disk->log_sector_size = 9; + grub_free (devpath); + if (!op) + return grub_errno; + disk->id = (unsigned long) op; + disk->data = op->devpath; } - grub_free (devpath); return 0; } @@ -555,13 +396,26 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) last_ihandle = 0; last_devpath = NULL; - grub_ieee1275_open (disk->data, &last_ihandle); + 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); if (! last_ihandle) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); last_devpath = disk->data; } - pos = sector << disk->log_sector_size; + pos = sector << GRUB_DISK_SECTOR_BITS; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) @@ -580,9 +434,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 << disk->log_sector_size, + grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, &actual); - if (actual != (grub_ssize_t) (size << disk->log_sector_size)) + if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " "from `%s'"), (unsigned long long) sector, @@ -600,9 +454,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 << disk->log_sector_size, + grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, &actual); - if (actual != (grub_ssize_t) (size << disk->log_sector_size)) + if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " "to `%s'"), (unsigned long long) sector, @@ -615,52 +469,18 @@ static struct grub_disk_dev grub_ofdisk_dev = { .name = "ofdisk", .id = GRUB_DISK_DEVICE_OFDISK_ID, - .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, + .iterate = grub_ofdisk_iterate, + .open = grub_ofdisk_open, + .close = grub_ofdisk_close, + .read = grub_ofdisk_read, + .write = grub_ofdisk_write, .next = 0 }; -static void -insert_bootpath (void) +void +grub_ofdisk_init (void) { - char *bootpath; - grub_ssize_t bootpath_size; - char *type; - - 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; - } - - bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64); - 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); + grub_disk_dev_register (&grub_ofdisk_dev); } void @@ -673,69 +493,3 @@ 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/ldm.c b/grub-core/disk/ldm.c index 58f8a53e1..0e4761b5a 100644 --- a/grub-core/disk/ldm.c +++ b/grub-core/disk/ldm.c @@ -22,10 +22,8 @@ #include #include #include -#include #include #include -#include #ifdef GRUB_UTIL #include @@ -50,7 +48,7 @@ struct grub_ldm_vblk { grub_uint8_t type; grub_uint32_t unused2; grub_uint8_t dynamic[104]; -} GRUB_PACKED; +} __attribute__ ((packed)); #define LDM_VBLK_MAGIC "VBLK" enum @@ -84,7 +82,7 @@ struct grub_ldm_label grub_uint64_t pv_size; grub_uint64_t config_start; grub_uint64_t config_size; -} GRUB_PACKED; +} __attribute__ ((packed)); #define LDM_MAGIC "PRIVHEAD" @@ -105,72 +103,37 @@ read_int (grub_uint8_t *in, grub_size_t s) return ret; } -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_gpt_part_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 const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM; 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; - err = grub_gpt_partition_map_iterate (dsk, gpt_ldm_sector_iter, §or); + 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); if (err) { grub_errno = GRUB_ERR_NONE; @@ -290,7 +253,6 @@ 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) @@ -325,8 +287,8 @@ make_vg (grub_disk_t disk, lv->segments->type = GRUB_DISKFILTER_MIRROR; lv->segments->node_count = 0; lv->segments->node_alloc = 8; - lv->segments->nodes = grub_calloc (lv->segments->node_alloc, - sizeof (*lv->segments->nodes)); + lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes) + * lv->segments->node_alloc); if (!lv->segments->nodes) goto fail2; ptr = vblk[i].dynamic; @@ -352,13 +314,7 @@ make_vg (grub_disk_t disk, grub_free (lv); goto fail2; } - if (grub_add (*ptr, 1, &sz)) - { - grub_free (lv->internal_id); - grub_free (lv); - goto fail2; - } - lv->name = grub_malloc (sz); + lv->name = grub_malloc (*ptr + 1); if (!lv->name) { grub_free (lv->internal_id); @@ -551,8 +507,8 @@ make_vg (grub_disk_t disk, { comp->segment_alloc = 8; comp->segment_count = 0; - comp->segments = grub_calloc (comp->segment_alloc, - sizeof (*comp->segments)); + comp->segments = grub_malloc (sizeof (*comp->segments) + * comp->segment_alloc); if (!comp->segments) goto fail2; } @@ -598,8 +554,8 @@ make_vg (grub_disk_t disk, } comp->segments->node_count = read_int (ptr + 1, *ptr); comp->segments->node_alloc = comp->segments->node_count; - comp->segments->nodes = grub_calloc (comp->segments->node_alloc, - sizeof (*comp->segments->nodes)); + comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes) + * comp->segments->node_alloc); if (!lv->segments->nodes) goto fail2; } @@ -607,13 +563,10 @@ make_vg (grub_disk_t disk, if (lv->segments->node_alloc == lv->segments->node_count) { void *t; - grub_size_t sz; - - if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) || - grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz)) - goto fail2; - - t = grub_realloc (lv->segments->nodes, sz); + lv->segments->node_alloc *= 2; + t = grub_realloc (lv->segments->nodes, + sizeof (*lv->segments->nodes) + * lv->segments->node_alloc); if (!t) goto fail2; lv->segments->nodes = t; @@ -718,29 +671,26 @@ make_vg (grub_disk_t disk, if (comp->segment_alloc == 1) { - unsigned node_index; + unsigned index; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } - node_index = read_int (ptr + 1, *ptr); - if (node_index < comp->segments->node_count) - comp->segments->nodes[node_index] = part; + index = read_int (ptr + 1, *ptr); + if (index < comp->segments->node_count) + comp->segments->nodes[index] = part; } else { if (comp->segment_alloc == comp->segment_count) { void *t; - 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); + comp->segment_alloc *= 2; + t = grub_realloc (comp->segments, + comp->segment_alloc + * sizeof (*comp->segments)); if (!t) goto fail2; comp->segments = t; @@ -806,20 +756,17 @@ 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 (!has_ldm || disk->partition) + if (disk->partition) continue; sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) @@ -920,7 +867,6 @@ 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; @@ -930,13 +876,11 @@ 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 (!has_ldm || disk->partition) + if (disk->partition) continue; sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) @@ -977,7 +921,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 currently supports only PC-BIOS embedding"); + "LDM curently 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); @@ -1026,12 +970,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_calloc (*nsectors, sizeof (**sectors)); + *sectors = grub_malloc (*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 cdf9123fa..f3b19eff7 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -32,11 +32,9 @@ struct grub_loopback char *devname; grub_file_t file; struct grub_loopback *next; - unsigned long id; }; static struct grub_loopback *loopback_list; -static unsigned long last_id = 0; static const struct grub_arg_option options[] = { @@ -92,8 +90,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) if (argc < 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - file = grub_file_open (args[1], GRUB_FILE_TYPE_LOOPBACK - | GRUB_FILE_TYPE_NO_DECOMPRESS); + file = grub_file_open (args[1]); if (! file) return grub_errno; @@ -123,7 +120,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) } newdev->file = file; - newdev->id = last_id++; /* Add the new entry to the list. */ newdev->next = loopback_list; @@ -139,15 +135,15 @@ fail: static int -grub_loopback_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, - grub_disk_pull_t pull) +grub_loopback_iterate (int (*hook) (const char *name), + 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, hook_data)) + if (hook (d->devname)) return 1; } return 0; @@ -171,11 +167,7 @@ grub_loopback_open (const char *name, grub_disk_t disk) / GRUB_DISK_SECTOR_SIZE); else disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; - /* Avoid reading more than 512M. */ - disk->max_agglomerate = 1 << (29 - GRUB_DISK_SECTOR_BITS - - GRUB_DISK_CACHE_BITS); - - disk->id = dev->id; + disk->id = (unsigned long) dev; disk->data = dev; @@ -214,18 +206,17 @@ grub_loopback_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "loopback write is not supported"); + return GRUB_ERR_NOT_IMPLEMENTED_YET; } static struct grub_disk_dev grub_loopback_dev = { .name = "loopback", .id = GRUB_DISK_DEVICE_LOOPBACK_ID, - .disk_iterate = grub_loopback_iterate, - .disk_open = grub_loopback_open, - .disk_read = grub_loopback_read, - .disk_write = grub_loopback_write, + .iterate = grub_loopback_iterate, + .open = grub_loopback_open, + .read = grub_loopback_read, + .write = grub_loopback_write, .next = 0 }; diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 59702067a..44f3cacb7 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,2019 Free Software Foundation, Inc. + * Copyright (C) 2003,2007,2010,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 @@ -56,7 +56,7 @@ struct grub_luks_phdr grub_uint32_t keyMaterialOffset; grub_uint32_t stripes; } keyblock[8]; -} GRUB_PACKED; +} __attribute__ ((packed)); typedef struct grub_luks_phdr *grub_luks_phdr_t; @@ -75,7 +75,15 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, 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) @@ -95,7 +103,6 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, || grub_be_to_cpu16 (header.version) != 1) return NULL; - grub_memset (uuid, 0, sizeof (uuid)); optr = uuid; for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)]; iptr++) @@ -119,33 +126,173 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec)); hashspec[sizeof (header.hashSpec)] = 0; - newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); - if (!newdev) + ciph = grub_crypto_lookup_cipher_by_name (ciphername); + if (!ciph) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + ciphername); return NULL; - newdev->offset = grub_be_to_cpu32 (header.payloadOffset); - newdev->source_disk = NULL; - newdev->log_sector_size = 9; - newdev->total_length = grub_disk_get_size (disk) - newdev->offset; - grub_memcpy (newdev->uuid, uuid, sizeof (uuid)); - newdev->modname = "luks"; + } + + /* 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; + } /* Configure the hash used for the AF splitter and HMAC. */ - newdev->hash = grub_crypto_lookup_md_by_name (hashspec); - if (!newdev->hash) + hash = grub_crypto_lookup_md_by_name (hashspec); + if (!hash) { - grub_free (newdev); + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_crypto_cipher_close (secondary_cipher); grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", hashspec); return NULL; } - err = grub_cryptodisk_setcipher (newdev, ciphername, ciphermode); - if (err) - { - grub_free (newdev); - 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)); return newdev; } @@ -171,15 +318,13 @@ 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_calloc (keysize, max_stripes); + split_key = grub_malloc (keysize * max_stripes); if (!split_key) return grub_errno; @@ -201,8 +346,8 @@ luks_recover_key (grub_disk_t source, for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) { gcry_err_code_t gcry_err; - grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; - grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t candidate_key[keysize]; + grub_uint8_t digest[keysize]; /* Check if keyslot is enabled. */ if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) @@ -306,7 +451,6 @@ luks_recover_key (grub_disk_t source, return GRUB_ERR_NONE; } - grub_free (split_key); return GRUB_ACCESS_DENIED; } diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c deleted file mode 100644 index 31d7166fc..000000000 --- a/grub-core/disk/luks2.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * 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 - -GRUB_MOD_LICENSE ("GPLv3+"); - -#define LUKS_MAGIC_1ST "LUKS\xBA\xBE" -#define LUKS_MAGIC_2ND "SKUL\xBA\xBE" - -#define MAX_PASSPHRASE 256 - -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 -{ - 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 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 -{ - /* 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", type); - - 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", type); - - 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", type); - - 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 i) -{ - grub_json_t keyslots, keyslot, digests, digest, segments, segment; - grub_size_t j, size; - grub_uint64_t idx; - - /* Get nth keyslot */ - if (grub_json_getvalue (&keyslots, root, "keyslots") || - grub_json_getchild (&keyslot, &keyslots, i) || - grub_json_getuint64 (&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 %"PRIuGRUB_SIZE, i); - - /* 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 (j = 0; j < size; j++) - { - if (grub_json_getchild (&digest, &digests, i) || - grub_json_getchild (&digest, &digest, 0) || - luks2_parse_digest (d, &digest)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i); - - if ((d->keyslots & (1 << idx))) - break; - } - if (j == size) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE); - - /* 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 (j = 0; j < size; j++) - { - if (grub_json_getchild (&segment, &segments, i) || - grub_json_getuint64 (&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 %"PRIuGRUB_SIZE, i); - - if ((d->segments & (1 << idx))) - break; - } - if (j == size) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE); - - 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, const char *check_uuid, int check_boot) -{ - grub_cryptodisk_t cryptodisk; - grub_luks2_header_t header; - char uuid[sizeof (header.uuid) + 1]; - grub_size_t i, j; - - if (check_boot) - return NULL; - - if (luks2_read_header (disk, &header)) - { - grub_errno = GRUB_ERR_NONE; - return NULL; - } - - for (i = 0, j = 0; i < sizeof (header.uuid); i++) - if (header.uuid[i] != '-') - uuid[j++] = header.uuid[i]; - uuid[j] = '\0'; - - if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0) - return NULL; - - cryptodisk = grub_zalloc (sizeof (*cryptodisk)); - if (!cryptodisk) - return NULL; - - COMPILE_TIME_ASSERT (sizeof (cryptodisk->uuid) >= sizeof (uuid)); - grub_memcpy (cryptodisk->uuid, uuid, sizeof (uuid)); - - cryptodisk->modname = "luks2"; - return cryptodisk; -} - -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]; - grub_size_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 (!base64_decode (d->digest, grub_strlen (d->digest), (char *)digest, &digestlen)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest"); - if (!base64_decode (d->salt, grub_strlen (d->salt), (char *)salt, &saltlen)) - 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 disk, 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; - grub_size_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 (!base64_decode (k->kdf.salt, grub_strlen (k->kdf.salt), - (char *)salt, &saltlen)) - { - 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 (disk, 0, k->area.offset, k->area.size, split_key); - if (ret) - { - grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg); - goto err; - } - - gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0); - 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 disk, - grub_cryptodisk_t crypt) -{ - grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; - char passphrase[MAX_PASSPHRASE], cipher[32]; - char *json_header = NULL, *part = NULL, *ptr; - grub_size_t candidate_key_len = 0, i, 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; - - ret = luks2_read_header (disk, &header); - if (ret) - return ret; - - json_header = grub_zalloc (grub_be_to_cpu64 (header.hdr_size) - sizeof (header)); - if (!json_header) - return GRUB_ERR_OUT_OF_MEMORY; - - /* Read the JSON area. */ - ret = grub_disk_read (disk, 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; - } - - /* Get the passphrase from the user. */ - if (disk->partition) - part = grub_partition_get_name (disk->partition); - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name, - disk->partition ? "," : "", part ? : "", - crypt->uuid); - if (!grub_password_get (passphrase, MAX_PASSPHRASE)) - { - ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); - 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; - } - - /* Try all keyslot */ - for (i = 0; i < size; i++) - { - ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i); - if (ret) - goto err; - - if (keyslot.priority == 0) - { - grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i); - continue; - } - - grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i); - - /* Set up disk according to keyslot's segment. */ - crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL); - crypt->log_sector_size = sizeof (unsigned int) * 8 - - __builtin_clz ((unsigned int) segment.sector_size) - 1; - if (grub_strcmp (segment.size, "dynamic") == 0) - crypt->total_length = grub_disk_get_size (disk) - crypt->offset; - else - crypt->total_length = grub_strtoull (segment.size, NULL, 10); - - ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot, - (const grub_uint8_t *) passphrase, grub_strlen (passphrase)); - if (ret) - { - grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n", - i, grub_errmsg); - continue; - } - - ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size); - if (ret) - { - grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n", - i, grub_errmsg); - continue; - } - - /* - * 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 %"PRIuGRUB_SIZE" opened\n"), i); - - 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 (part); - 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 753545146..508e94af0 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -25,7 +25,6 @@ #include #include #include -#include #ifdef GRUB_UTIL #include @@ -34,20 +33,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); -struct cache_lv -{ - struct grub_diskfilter_lv *lv; - char *cache_pool; - char *origin; - struct cache_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 (const char ** const p, const char *str) +grub_lvm_getvalue (char **p, const char *str) { *p = grub_strstr (*p, str); if (! *p) @@ -72,12 +63,12 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl) #endif static int -grub_lvm_check_flag (const char *p, const char *str, const char *flag) +grub_lvm_check_flag (char *p, const char *str, const char *flag) { - grub_size_t len_str = grub_strlen (str), len_flag = grub_strlen (flag); + int len_str = grub_strlen (str), len_flag = grub_strlen (flag); while (1) { - const char *q; + char *q; p = grub_strstr (p, str); if (! p) return 0; @@ -104,34 +95,6 @@ grub_lvm_check_flag (const char *p, const char *str, const char *flag) } } -static void -grub_lvm_free_cache_lvs (struct cache_lv *cache_lvs) -{ - struct cache_lv *cache; - - while ((cache = cache_lvs)) - { - cache_lvs = cache_lvs->next; - - if (cache->lv) - { - unsigned int i; - - for (i = 0; i < cache->lv->segment_count; ++i) - if (cache->lv->segments) - grub_free (cache->lv->segments[i].nodes); - grub_free (cache->lv->segments); - grub_free (cache->lv->fullname); - grub_free (cache->lv->idname); - grub_free (cache->lv->name); - } - grub_free (cache->lv); - grub_free (cache->origin); - grub_free (cache->cache_pool); - grub_free (cache); - } -} - static struct grub_diskfilter_vg * grub_lvm_detect (grub_disk_t disk, struct grub_diskfilter_pv_id *id, @@ -139,19 +102,16 @@ grub_lvm_detect (grub_disk_t disk, { 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, *mda_end, *vgname; - const char *p, *q; + char *metadatabuf, *p, *q, *vgname; 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; - grub_size_t vgname_len; + unsigned int i, j, vgname_len; struct grub_diskfilter_vg *vg; struct grub_diskfilter_pv *pv; @@ -199,7 +159,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"); + grub_util_info ("we don't support multiple LVM data areas\n"); #endif goto fail; } @@ -212,7 +172,7 @@ grub_lvm_detect (grub_disk_t disk, first one. */ /* Allocate buffer space for the circular worst-case scenario. */ - metadatabuf = grub_calloc (2, mda_size); + metadatabuf = grub_malloc (2 * mda_size); if (! metadatabuf) goto fail; @@ -228,7 +188,7 @@ 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"); + grub_util_info ("unknown LVM metadata header\n"); #endif goto fail2; } @@ -244,31 +204,19 @@ 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); - if (grub_add ((grub_size_t)metadatabuf, - (grub_size_t)grub_le_to_cpu64 (rlocn->offset), - &ptr)) + while (*q != ' ' && q < metadatabuf + mda_size) + q++; + + if (q == metadatabuf + mda_size) { - error_parsing_metadata: #ifdef GRUB_UTIL - grub_util_info ("error parsing metadata"); + grub_util_info ("error parsing metadata\n"); #endif goto fail2; } - p = q = (char *)ptr; - - if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_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) @@ -281,7 +229,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("couldn't find ID"); + grub_util_info ("couldn't find ID\n"); #endif goto fail3; } @@ -293,8 +241,6 @@ grub_lvm_detect (grub_disk_t disk, if (! vg) { - struct cache_lv *cache_lvs = NULL; - /* First time we see this volume group. We've to create the whole volume group structure. */ vg = grub_malloc (sizeof (*vg)); @@ -311,7 +257,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown extent size"); + grub_util_info ("unknown extent size\n"); #endif goto fail4; } @@ -327,7 +273,7 @@ grub_lvm_detect (grub_disk_t disk, /* Add all the pvs to the volume group. */ while (1) { - grub_ssize_t s; + int s; while (grub_isspace (*p)) p++; @@ -359,7 +305,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown pe_start"); + grub_util_info ("unknown pe_start\n"); #endif goto pvs_fail; } @@ -368,7 +314,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("error parsing pe_start"); + grub_util_info ("error parsing pe_start\n"); #endif goto pvs_fail; } @@ -386,15 +332,15 @@ grub_lvm_detect (grub_disk_t disk, } } - 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) { - grub_ssize_t s; + int s; int skip_lv = 0; struct grub_diskfilter_lv *lv; struct grub_diskfilter_segment *seg; @@ -420,26 +366,8 @@ grub_lvm_detect (grub_disk_t disk, { const char *iptr; char *optr; - - /* - * 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); + lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len + + 1 + 2 * s + 1); if (!lv->fullname) goto lvs_fail; @@ -459,29 +387,6 @@ 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; @@ -493,11 +398,11 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown segment_count"); + grub_util_info ("unknown segment_count\n"); #endif goto lvs_fail; } - lv->segments = grub_calloc (lv->segment_count, sizeof (*seg)); + lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count); seg = lv->segments; for (i = 0; i < lv->segment_count; i++) @@ -507,7 +412,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown segment"); + grub_util_info ("unknown segment\n"); #endif goto lvs_segment_fail; } @@ -516,7 +421,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown start_extent"); + grub_util_info ("unknown start_extent\n"); #endif goto lvs_segment_fail; } @@ -524,7 +429,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown extent_count"); + grub_util_info ("unknown extent_count\n"); #endif goto lvs_segment_fail; } @@ -546,7 +451,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripe_count"); + grub_util_info ("unknown stripe_count\n"); #endif goto lvs_segment_fail; } @@ -554,15 +459,15 @@ grub_lvm_detect (grub_disk_t disk, if (seg->node_count != 1) seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); - seg->nodes = grub_calloc (seg->node_count, - sizeof (*stripe)); + seg->nodes = grub_zalloc (sizeof (*stripe) + * seg->node_count); stripe = seg->nodes; p = grub_strstr (p, "stripes = ["); if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripes"); + grub_util_info ("unknown stripes\n"); #endif goto lvs_segment_fail2; } @@ -604,7 +509,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirror_count"); + grub_util_info ("unknown mirror_count\n"); #endif goto lvs_segment_fail; } @@ -616,7 +521,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirrors"); + grub_util_info ("unknown mirrors\n"); #endif goto lvs_segment_fail2; } @@ -648,17 +553,13 @@ 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') - || p[sizeof ("raid") - 1] == '1') + else if (grub_memcmp (p, "raid", sizeof ("raid") - 1) + == 0 && (p[sizeof ("raid") - 1] >= '4' + && p[sizeof ("raid") - 1] <= '6') && 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; @@ -678,23 +579,21 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown device_count"); + grub_util_info ("unknown device_count\n"); #endif goto lvs_segment_fail; } - if (seg->type != GRUB_DISKFILTER_MIRROR) + seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + if (p == NULL) { - seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); - if (p == NULL) - { #ifdef GRUB_UTIL - grub_util_info ("unknown stripe_size"); + grub_util_info ("unknown stripe_size\n"); #endif - goto lvs_segment_fail; - } + goto lvs_segment_fail; } + seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) * seg->node_count); @@ -702,7 +601,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown raids"); + grub_util_info ("unknown mirrors\n"); #endif goto lvs_segment_fail2; } @@ -742,106 +641,6 @@ grub_lvm_detect (grub_disk_t disk, seg->nodes[seg->node_count - 1].name = tmp; } } - else if (grub_memcmp (p, "cache\"", - sizeof ("cache\"") - 1) == 0) - { - struct cache_lv *cache = NULL; - - char *p2, *p3; - grub_size_t sz; - - cache = grub_zalloc (sizeof (*cache)); - if (!cache) - goto cache_lv_fail; - cache->lv = grub_zalloc (sizeof (*cache->lv)); - if (!cache->lv) - goto cache_lv_fail; - grub_memcpy (cache->lv, lv, sizeof (*cache->lv)); - - if (lv->fullname) - { - cache->lv->fullname = grub_strdup (lv->fullname); - if (!cache->lv->fullname) - goto cache_lv_fail; - } - if (lv->idname) - { - cache->lv->idname = grub_strdup (lv->idname); - if (!cache->lv->idname) - goto cache_lv_fail; - } - if (lv->name) - { - cache->lv->name = grub_strdup (lv->name); - if (!cache->lv->name) - goto cache_lv_fail; - } - - skip_lv = 1; - - p2 = grub_strstr (p, "cache_pool = \""); - if (!p2) - goto cache_lv_fail; - - p2 = grub_strchr (p2, '"'); - if (!p2) - goto cache_lv_fail; - - p3 = ++p2; - p3 = grub_strchr (p3, '"'); - if (!p3) - goto cache_lv_fail; - - sz = p3 - p2; - - cache->cache_pool = grub_malloc (sz + 1); - if (!cache->cache_pool) - goto cache_lv_fail; - grub_memcpy (cache->cache_pool, p2, sz); - cache->cache_pool[sz] = '\0'; - - p2 = grub_strstr (p, "origin = \""); - if (!p2) - goto cache_lv_fail; - - p2 = grub_strchr (p2, '"'); - if (!p2) - goto cache_lv_fail; - - p3 = ++p2; - p3 = grub_strchr (p3, '"'); - if (!p3) - goto cache_lv_fail; - - sz = p3 - p2; - - cache->origin = grub_malloc (sz + 1); - if (!cache->origin) - goto cache_lv_fail; - grub_memcpy (cache->origin, p2, sz); - cache->origin[sz] = '\0'; - - cache->next = cache_lvs; - cache_lvs = cache; - break; - - cache_lv_fail: - if (cache) - { - grub_free (cache->origin); - grub_free (cache->cache_pool); - if (cache->lv) - { - grub_free (cache->lv->fullname); - grub_free (cache->lv->idname); - grub_free (cache->lv->name); - } - grub_free (cache->lv); - grub_free (cache); - } - grub_lvm_free_cache_lvs (cache_lvs); - goto fail4; - } else { #ifdef GRUB_UTIL @@ -849,7 +648,7 @@ grub_lvm_detect (grub_disk_t disk, p2 = grub_strchr (p, '"'); if (p2) *p2 = 0; - grub_util_info ("unknown LVM type %s", p); + grub_util_info ("unknown LVM type %s\n", p); if (p2) *p2 ='"'; #endif @@ -918,58 +717,6 @@ grub_lvm_detect (grub_disk_t disk, } } - - { - struct cache_lv *cache; - - for (cache = cache_lvs; cache; cache = cache->next) - { - struct grub_diskfilter_lv *lv; - - for (lv = vg->lvs; lv; lv = lv->next) - if (grub_strcmp (lv->name, cache->origin) == 0) - break; - if (lv) - { - cache->lv->segments = grub_calloc (lv->segment_count, sizeof (*lv->segments)); - if (!cache->lv->segments) - { - grub_lvm_free_cache_lvs (cache_lvs); - goto fail4; - } - grub_memcpy (cache->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; - - cache->lv->segments[i].nodes = grub_calloc (node_count, sizeof (*nodes)); - if (!cache->lv->segments[i].nodes) - { - for (j = 0; j < i; ++j) - grub_free (cache->lv->segments[j].nodes); - grub_free (cache->lv->segments); - cache->lv->segments = NULL; - grub_lvm_free_cache_lvs (cache_lvs); - goto fail4; - } - grub_memcpy (cache->lv->segments[i].nodes, nodes, node_count * sizeof (*nodes)); - } - - if (cache->lv->segments) - { - cache->lv->segment_count = lv->segment_count; - cache->lv->vg = vg; - cache->lv->next = vg->lvs; - vg->lvs = cache->lv; - cache->lv = NULL; - } - } - } - } - - grub_lvm_free_cache_lvs (cache_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 c980feba4..a0e65a8cc 100644 --- a/grub-core/disk/mdraid1x_linux.c +++ b/grub-core/disk/mdraid1x_linux.c @@ -97,7 +97,7 @@ 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 GRUB_PACKED, but since all members in this struct +/* Could be __attribute__ ((packed)), but since all members in this struct are already appropriately aligned, we can omit this and avoid suboptimal assembly in some cases. */ @@ -178,7 +178,7 @@ grub_mdraid_detect (grub_disk_t disk, return NULL; if (grub_disk_read (disk, sector, - (char *) (sb.dev_roles + grub_le_to_cpu32 (sb.dev_number)) + (char *) &sb.dev_roles[grub_le_to_cpu32 (sb.dev_number)] - (char *) &sb, sizeof (role), &role)) return NULL; diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c index 11024ae31..f408fd37e 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_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 +#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 #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_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 +#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 #endif #define RESERVED_BYTES (64 * 1024) @@ -175,7 +175,7 @@ struct grub_raid_super_09 * Active descriptor */ struct grub_raid_disk_09 this_disk; -} GRUB_PACKED; +} __attribute__ ((packed)); static struct grub_diskfilter_vg * grub_mdraid_detect (grub_disk_t disk, @@ -184,10 +184,9 @@ grub_mdraid_detect (grub_disk_t disk, { grub_disk_addr_t sector; grub_uint64_t size; - struct grub_raid_super_09 *sb = NULL; + struct grub_raid_super_09 sb; 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); @@ -196,31 +195,27 @@ grub_mdraid_detect (grub_disk_t disk, return NULL; sector = NEW_SIZE_SECTORS (size); - sb = grub_malloc (sizeof (*sb)); - if (!sb) + if (grub_disk_read (disk, sector, 0, SB_BYTES, &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. */ - goto fail; + return NULL; - 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. */ - goto fail; + return NULL; - /* 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) - goto fail; + if (((grub_disk_addr_t) grub_md_to_cpu32 (sb.size)) * 2 >= size) + return NULL; /* 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; @@ -230,43 +225,37 @@ grub_mdraid_detect (grub_disk_t disk, { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported RAID level: %d", level); - goto fail; + return NULL; } - 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. */ - goto fail; + return NULL; uuid = grub_malloc (16); if (!uuid) - goto fail; + return NULL; - 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)); - 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; + 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); } static struct grub_diskfilter grub_mdraid_dev = { diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 613779cf3..4de0971ae 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -30,13 +30,13 @@ static char *memdisk_addr; static grub_off_t memdisk_size = 0; static int -grub_memdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, +grub_memdisk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { if (pull != GRUB_DISK_PULL_NONE) return 0; - return hook ("memdisk", hook_data); + return hook ("memdisk"); } static grub_err_t @@ -46,8 +46,7 @@ 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->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; - disk->id = 0; + disk->id = (unsigned long) "mdsk"; return GRUB_ERR_NONE; } @@ -77,11 +76,11 @@ static struct grub_disk_dev grub_memdisk_dev = { .name = "memdisk", .id = GRUB_DISK_DEVICE_MEMDISK_ID, - .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, + .iterate = grub_memdisk_iterate, + .open = grub_memdisk_open, + .close = grub_memdisk_close, + .read = grub_memdisk_read, + .write = grub_memdisk_write, .next = 0 }; diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 23eef2be1..00b04e2d4 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -338,10 +338,9 @@ grub_pata_device_initialize (int port, int device, int addr) } #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS -static int +static int NESTED_FUNC_ATTR grub_pata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid, - void *data __attribute__ ((unused))) + grub_pci_id_t pciid) { static int compat_use[2] = { 0 }; grub_pci_address_t addr; @@ -402,15 +401,9 @@ 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) && (bar1 & ~3)) + if ((bar1 & 1) && (bar2 & 1)) { 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); - } } @@ -453,7 +446,7 @@ grub_pata_pciinit (grub_pci_device_t dev, static grub_err_t grub_pata_initialize (void) { - grub_pci_iterate (grub_pata_pciinit, NULL); + grub_pci_iterate (grub_pata_pciinit); return 0; } #else @@ -507,7 +500,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) } static int -grub_pata_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, +grub_pata_iterate (int (*hook) (int id, int bus), grub_disk_pull_t pull) { struct grub_pata_device *dev; @@ -516,8 +509,7 @@ grub_pata_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, return 0; for (dev = grub_pata_devices; dev; dev = dev->next) - if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device, - hook_data)) + if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device)) return 1; return 0; @@ -536,7 +528,13 @@ static struct grub_ata_dev grub_pata_dev = GRUB_MOD_INIT(ata_pthru) { - grub_stop_disk_firmware (); + /* 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; + } /* ATA initialization. */ grub_pata_initialize (); diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index 75fe464a4..ba889ba3d 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 unsigned powx_inv[256]; +static int powx_inv[256]; static const grub_uint8_t poly = 0x1d; static void -grub_raid_block_mulx (unsigned mul, char *buf, grub_size_t size) +grub_raid_block_mulx (int mul, char *buf, int size) { - grub_size_t i; + int i; grub_uint8_t *p; p = (grub_uint8_t *) buf; @@ -48,7 +48,7 @@ grub_raid_block_mulx (unsigned mul, char *buf, grub_size_t size) static void grub_raid6_init_table (void) { - unsigned i; + int i; grub_uint8_t cur = 1; for (i = 0; i < 255; i++) @@ -63,37 +63,15 @@ 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 -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) +grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, + char *buf, grub_disk_addr_t sector, grub_size_t size) { 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; @@ -103,17 +81,17 @@ grub_raid6_recover_gen (void *data, grub_uint64_t nstripes, int disknr, int p, goto quit; q = p + 1; - if (q == (int) nstripes) + if (q == (int) array->node_count) q = 0; pos = q + 1; - if (pos == (int) nstripes) + if (pos == (int) array->node_count) pos = 0; - for (i = 0; i < (int) nstripes - 2; i++) + for (i = 0; i < (int) array->node_count - 2; i++) { int c; - if (layout & GRUB_RAID_LAYOUT_MUL_FROM_POS) + if (array->layout & GRUB_RAID_LAYOUT_MUL_FROM_POS) c = pos; else c = i; @@ -121,7 +99,8 @@ grub_raid6_recover_gen (void *data, grub_uint64_t nstripes, int disknr, int p, bad1 = c; else { - if (!read_func (data, pos, sector, buf, size)) + if (! grub_diskfilter_read_node (&array->nodes[pos], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) { grub_crypto_xor (pbuf, pbuf, buf, size); grub_raid_block_mulx (c, buf, size); @@ -139,7 +118,7 @@ grub_raid6_recover_gen (void *data, grub_uint64_t nstripes, int disknr, int p, } pos++; - if (pos == (int) nstripes) + if (pos == (int) array->node_count) pos = 0; } @@ -150,14 +129,16 @@ grub_raid6_recover_gen (void *data, grub_uint64_t nstripes, int disknr, int p, if (bad2 < 0) { /* One bad device */ - if (!read_func (data, p, sector, buf, size)) + if ((! grub_diskfilter_read_node (&array->nodes[p], sector, + size >> GRUB_DISK_SECTOR_BITS, buf))) { grub_crypto_xor (buf, buf, pbuf, size); goto quit; } grub_errno = GRUB_ERR_NONE; - if (read_func (data, q, sector, buf, size)) + if (grub_diskfilter_read_node (&array->nodes[q], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) goto quit; grub_crypto_xor (buf, buf, qbuf, size); @@ -167,23 +148,24 @@ grub_raid6_recover_gen (void *data, grub_uint64_t nstripes, int disknr, int p, else { /* Two bad devices */ - unsigned c; + int c; - if (read_func (data, p, sector, buf, size)) + if (grub_diskfilter_read_node (&array->nodes[p], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) goto quit; grub_crypto_xor (pbuf, pbuf, buf, size); - if (read_func (data, q, sector, buf, size)) + if (grub_diskfilter_read_node (&array->nodes[q], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) goto quit; grub_crypto_xor (qbuf, qbuf, buf, size); - c = mod_255((255 ^ bad1) - + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)])); + c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255; grub_raid_block_mulx (c, qbuf, size); - c = mod_255((unsigned) bad2 + c); + c = (bad2 + c) % 255; grub_raid_block_mulx (c, pbuf, size); grub_crypto_xor (pbuf, pbuf, qbuf, size); @@ -197,15 +179,6 @@ 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 70767cf00..29dd0d3b8 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -201,7 +201,7 @@ 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_compile_time (sizeof (rcd)); + rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd)); rc.PMI = 0; rc.control = 0; @@ -423,59 +423,50 @@ grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector, -/* Context for grub_scsi_iterate. */ -struct grub_scsi_iterate_ctx -{ - grub_disk_dev_iterate_hook_t hook; - void *hook_data; -}; - -/* 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; - - /* 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 = 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_scsi_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { - struct grub_scsi_iterate_ctx ctx = { hook, hook_data }; grub_scsi_dev_t p; + auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns); + + int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns) + { + 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; + } + for (p = grub_scsi_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (scsi_iterate, &ctx, pull)) + if (p->iterate && (p->iterate) (scsi_iterate, pull)) return 1; return 0; @@ -606,19 +597,11 @@ 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_errno; + return grub_error (GRUB_ERR_IO, "invalid sector size %d", + scsi->blocksize); } for (disk->log_sector_size = 0; (1U << disk->log_sector_size) < scsi->blocksize; @@ -655,27 +638,40 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - grub_err_t err; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) + while (size) { - 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; + /* 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_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; + 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; } return GRUB_ERR_NONE; @@ -713,10 +709,10 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, } static grub_err_t -grub_scsi_write (grub_disk_t disk, - grub_disk_addr_t sector, - grub_size_t size, - const char *buf) +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_t scsi; @@ -725,18 +721,31 @@ grub_scsi_write (grub_disk_t disk, if (scsi->devtype == grub_scsi_devtype_cdrom) return grub_error (GRUB_ERR_IO, N_("cannot write to CD-ROM")); - grub_err_t err; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) + while (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; + /* 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; } return GRUB_ERR_NONE; @@ -747,11 +756,11 @@ static struct grub_disk_dev grub_scsi_dev = { .name = "scsi", .id = GRUB_DISK_DEVICE_SCSI_ID, - .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, + .iterate = grub_scsi_iterate, + .open = grub_scsi_open, + .close = grub_scsi_close, + .read = grub_scsi_read, + .write = grub_scsi_write, .next = 0 }; diff --git a/grub-core/disk/uboot/ubootdisk.c b/grub-core/disk/uboot/ubootdisk.c deleted file mode 100644 index 2d115a94d..000000000 --- a/grub-core/disk/uboot/ubootdisk.c +++ /dev/null @@ -1,307 +0,0 @@ -/* 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"); - - for (disk->log_sector_size = 0; - (1U << disk->log_sector_size) < d->block_size; - disk->log_sector_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 380ca4c4c..52cc33e93 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]; -} GRUB_PACKED; +} __attribute__ ((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; -} GRUB_PACKED; +} __attribute__ ((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_usb_err_t +static grub_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_usb_err_t +static grub_err_t grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) { /* Prepare array with Command Block Reset (=CBR) */ @@ -108,13 +108,17 @@ grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) return grub_usbms_cbi_cmd (dev, interface, (grub_uint8_t *)&cbicb); } -static grub_usb_err_t +static grub_err_t grub_usbms_bo_reset (grub_usb_device_t dev, int interface) { - return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0); + 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; } -static grub_usb_err_t +static grub_err_t grub_usbms_reset (grub_usbms_dev_t dev) { if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK) @@ -145,9 +149,7 @@ 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_USB_ERR_NONE; - - grub_boot_time ("Attaching USB mass storage"); + grub_usb_err_t err = GRUB_ERR_NONE; if (first_available_slot == ARRAY_SIZE (grub_usbms_devices)) return 0; @@ -244,8 +246,6 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) 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 (grub_scsi_dev_iterate_hook_t hook, void *hook_data, +grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), grub_disk_pull_t pull) { unsigned i; @@ -273,13 +273,12 @@ grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, if (pull != GRUB_DISK_PULL_NONE) return 0; - grub_usb_poll_devices (1); + grub_usb_poll_devices (); 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, - hook_data)) + if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns)) return 1; } @@ -298,8 +297,6 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, grub_usb_err_t errCSW = GRUB_USB_ERR_NONE; int retrycnt = 3 + 1; - tag++; - retry: retrycnt--; if (retrycnt == 0) @@ -307,8 +304,8 @@ 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_compile_time (0x43425355); - cbw.tag = tag; + cbw.signature = grub_cpu_to_le32 (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. */ @@ -328,7 +325,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, + err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, sizeof (cbw), (char *) &cbw); if (err) { @@ -337,13 +334,13 @@ 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; } - goto retry; + return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed"); } /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); + 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); if (err) { @@ -364,7 +361,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, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, 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], @@ -390,12 +387,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, + errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, 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, + errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, sizeof (status), (char *) &status); if (errCSW) { /* Bulk-only reset device. */ @@ -414,7 +411,7 @@ CheckCSW: /* If phase error or not valid signature, do bulk-only reset device. */ if ((status.status == 2) || - (status.signature != grub_cpu_to_le32_compile_time(0x53425355))) + (status.signature != grub_cpu_to_le32(0x53425355))) { /* Bulk-only reset device. */ grub_dprintf ("usb", "Bulk-only reset device - bad status\n"); grub_usbms_reset (dev); @@ -478,7 +475,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, + err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, 2, (char*)&status); grub_dprintf ("usb", "CBI cmdcb setup status: err=%d, status=0x%x\n", err, status); } @@ -489,7 +486,7 @@ 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, size, buf); + err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); grub_dprintf ("usb", "read: %d\n", err); if (err) { @@ -500,7 +497,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, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); grub_dprintf ("usb", "write: %d\n", err); if (err) { @@ -519,7 +516,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, + err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, 2, (char*)&status); grub_dprintf ("usb", "read status: %d\n", err); if (err) @@ -569,11 +566,8 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } } } - - if (err) - return grub_error (GRUB_ERR_IO, "USB error %d", err); - return GRUB_ERR_NONE; + return err; } @@ -612,8 +606,7 @@ grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not USB Mass Storage device"); - if (!grub_usbms_devices[devnum]) - grub_usb_poll_devices (1); + grub_usb_poll_devices (); 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 deleted file mode 100644 index d6612eebd..000000000 --- a/grub-core/disk/xen/xendisk.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * 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); - - for (disk->log_sector_size = 0; - (1U << disk->log_sector_size) < secsize; disk->log_sector_size++); - - 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 a262b5328..c3782fda9 100644 --- a/grub-core/efiemu/i386/coredetect.c +++ b/grub-core/efiemu/i386/coredetect.c @@ -18,10 +18,42 @@ #include #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) const char * grub_efiemu_get_default_core_name (void) { - return grub_cpuid_has_longmode ? "efiemu64.o" : "efiemu32.o"; + + 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"; } diff --git a/grub-core/efiemu/i386/loadcore64.c b/grub-core/efiemu/i386/loadcore64.c index 18facf47f..e49d0b6ff 100644 --- a/grub-core/efiemu/i386/loadcore64.c +++ b/grub-core/efiemu/i386/loadcore64.c @@ -98,7 +98,6 @@ 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 diff --git a/grub-core/efiemu/i386/pc/cfgtables.c b/grub-core/efiemu/i386/pc/cfgtables.c index e5fffb7d4..492c07c46 100644 --- a/grub-core/efiemu/i386/pc/cfgtables.c +++ b/grub-core/efiemu/i386/pc/cfgtables.c @@ -22,11 +22,11 @@ #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; @@ -57,10 +57,17 @@ grub_machine_efiemu_init_tables (void) if (err) return err; } - table = grub_smbios_get_eps (); - if (table) + + 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) { - err = grub_efiemu_register_configuration_table (smbios, 0, 0, table); + grub_dprintf ("efiemu", "Registering SMBIOS\n"); + err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr); if (err) return err; } diff --git a/grub-core/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c index 2b924623f..6968b3719 100644 --- a/grub-core/efiemu/loadcore.c +++ b/grub-core/efiemu/loadcore.c @@ -154,10 +154,7 @@ 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) - { - grub_free (seg); - return grub_errno; - } + return grub_errno; seg->off = 0; } @@ -201,7 +198,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_calloc (grub_efiemu_nelfsyms, sizeof (struct grub_efiemu_elf_sym)); + grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms); /* Relocators */ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); @@ -346,7 +343,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 + (grub_uint32_t) e->e_shentsize * e->e_shnum) + if ((grub_size_t) core_size < e->e_shoff + 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 a81934725..f2140ad29 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -187,7 +187,7 @@ grub_efiemu_load_file (const char *filename) grub_file_t file; grub_err_t err; - file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE); + file = grub_file_open (filename); if (! file) return grub_errno; @@ -196,7 +196,7 @@ grub_efiemu_load_file (const char *filename) { grub_file_close (file); grub_efiemu_unload (); - return err; + return grub_errno; } grub_dprintf ("efiemu", "mm initialized\n"); diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index 9b8e0d0ad..10cbc68cc 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -99,8 +99,7 @@ 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_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY || - type >= GRUB_EFI_MAX_MEMORY_TYPE) + if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE) return -2; /* Add new size to requested size */ @@ -167,13 +166,6 @@ 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 */ @@ -276,26 +268,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, NULL); + grub_machine_mmap_iterate (bounds_hook); #endif return GRUB_ERR_NONE; @@ -391,52 +383,48 @@ 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, NULL); + grub_machine_mmap_iterate (fill_hook); #endif return GRUB_ERR_NONE; } grub_err_t -grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +grub_efiemu_mmap_iterate (grub_memory_hook_t hook) { unsigned i; @@ -445,12 +433,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_CODE, hook_data); + GRUB_MEMORY_CODE); break; case GRUB_EFI_UNUSABLE_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_BADRAM, hook_data); + GRUB_MEMORY_BADRAM); break; case GRUB_EFI_RESERVED_MEMORY_TYPE: @@ -458,9 +446,9 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: - default: + case GRUB_EFI_MAX_MEMORY_TYPE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_RESERVED, hook_data); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -469,24 +457,18 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) 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, hook_data); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_ACPI, hook_data); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_NVS, hook_data); + GRUB_MEMORY_NVS); 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; @@ -522,8 +504,7 @@ 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_PERSISTENT_MEMORY] = 4 + [GRUB_EFI_PAL_CODE] = 4 }; int i, j, k, done; @@ -554,11 +535,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_calloc (mmap_num, sizeof (struct grub_efiemu_mmap_scan) * 2); + grub_malloc (sizeof (struct grub_efiemu_mmap_scan) * 2 * mmap_num); /* Number of chunks can't increase more than by factor of 2 */ result = (grub_efi_memory_descriptor_t *) - grub_calloc (mmap_num, sizeof (grub_efi_memory_descriptor_t) * 2); + grub_malloc (sizeof (grub_efi_memory_descriptor_t) * 2 * mmap_num); if (!result || !scanline_events) { grub_free (result); @@ -660,7 +641,7 @@ grub_efiemu_mm_do_alloc (void) /* Preallocate mmap */ efiemu_mmap = (grub_efi_memory_descriptor_t *) - grub_calloc (mmap_reserved_size, sizeof (grub_efi_memory_descriptor_t)); + grub_malloc (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 dd42bc691..28d005044 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, const char ** const end, int base) +grub_strtosl (const char *arg, char **end, int base) { if (arg[0] == '-') return -grub_strtoul (arg + 1, end, base); @@ -102,7 +102,92 @@ nvram_set (void * data __attribute__ ((unused))) grub_uint32_t *accuracy = grub_efiemu_mm_obtain_request (accuracy_handle); char *nvramptr; - struct grub_env_var *var; + + 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; + } /* Copy to definitive loaction */ grub_dprintf ("efiemu", "preparing pnvram\n"); @@ -118,89 +203,9 @@ nvram_set (void * data __attribute__ ((unused))) nvramptr = nvram; grub_memset (nvram, 0, nvramsize); - 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; - } + grub_env_iterate (iterate_env); 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 99ddb5abb..2aef8634d 100644 --- a/grub-core/efiemu/prepare.c +++ b/grub-core/efiemu/prepare.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -83,16 +82,10 @@ 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 */ - 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; - } - + grub_efiemu_write_value + (&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0, + conftable_handle, 0, 1, + sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table)); SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables; /* Fill the list of configuration tables */ @@ -129,10 +122,7 @@ SUFFIX (grub_efiemu_crc) (void) int handle; grub_off_t off; struct SUFFIX (grub_efiemu_runtime_services) *runtime_services; - grub_uint32_t crc32_val; - - if (GRUB_MD_CRC32->mdlen != 4) - return grub_error (GRUB_ERR_BUG, "incorrect mdlen"); + grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; /* compute CRC32 of runtime_services */ err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", @@ -144,11 +134,12 @@ 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(crc32_val); + grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)); err = grub_efiemu_resolve_symbol ("efiemu_system_table", &handle, &off); if (err) @@ -156,11 +147,12 @@ SUFFIX (grub_efiemu_crc) (void) /* compute CRC32 of system table */ SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0; - grub_crypto_hash (GRUB_MD_CRC32, &crc32_val, - SUFFIX (grub_efiemu_system_table), - SUFFIX (grub_efiemu_system_table)->hdr.header_size); + 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); SUFFIX (grub_efiemu_system_table)->hdr.crc32 = - grub_be_to_cpu32(crc32_val); + grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)); 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 c9fe02716..26fb2ff08 100644 --- a/grub-core/efiemu/runtime/config.h +++ b/grub-core/efiemu/runtime/config.h @@ -19,18 +19,16 @@ #define GRUB_TYPES_CPU_HEADER 1 -#ifdef __i386__ +#ifdef ELF32 # 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 -#elif defined (__x86_64__) +#else # 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 5db1f347b..84b02cb20 100644 --- a/grub-core/efiemu/runtime/efiemu.c +++ b/grub-core/efiemu/runtime/efiemu.c @@ -78,7 +78,7 @@ efiemu_get_next_variable_name (grub_efi_uintn_t *variable_name_size, grub_efi_status_t efiemu_set_variable (grub_efi_char16_t *variable_name, - const grub_efi_guid_t *vendor_guid, + grub_efi_guid_t *vendor_guid, grub_efi_uint32_t attributes, grub_efi_uintn_t data_size, void *data); @@ -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, const void *from, int count) +efiemu_memcpy (void *to, void *from, int count) { int i; for (i = 0; i < count; i++) - ((grub_uint8_t *) to)[i] = ((const grub_uint8_t *) from)[i]; + ((grub_uint8_t *) to)[i] = ((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; } @@ -503,10 +503,10 @@ grub_efi_status_t EFI_FUNC grub_efi_status_t EFI_FUNC (efiemu_set_variable) (grub_efi_char16_t *variable_name, - const grub_efi_guid_t *vendor_guid, - grub_efi_uint32_t attributes, - grub_efi_uintn_t data_size, - void *data) + grub_efi_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; diff --git a/grub-core/font/font.c b/grub-core/font/font.c index d09bb38d8..fca8c8d00 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -30,11 +30,10 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); -#if HAVE_FONT_SOURCE +#ifdef USE_ASCII_FAILBACK #include "ascii.h" #endif @@ -56,6 +55,23 @@ 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; @@ -111,14 +127,14 @@ static struct grub_font null_font; /* Flag to ensure module is initialized only once. */ static grub_uint8_t font_loader_initialized; -#if HAVE_FONT_SOURCE +#ifdef USE_ASCII_FAILBACK static struct grub_font_glyph *ascii_font_glyph[0x80]; #endif static struct grub_font_glyph * ascii_glyph_lookup (grub_uint32_t code) { -#if HAVE_FONT_SOURCE +#ifdef USE_ASCII_FAILBACK static int ascii_failback_initialized = 0; if (code >= 0x80) @@ -277,7 +293,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct grub_uint32_t last_code; #if FONT_DEBUG >= 2 - grub_dprintf ("font", "load_font_index(sect_length=%d)\n", sect_length); + grub_printf ("load_font_index(sect_length=%d)\n", sect_length); #endif /* Sanity check: ensure section length is divisible by the entry size. */ @@ -294,7 +310,8 @@ 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_calloc (font->num_chars, sizeof (struct char_index_entry)); + font->char_index = grub_malloc (font->num_chars + * sizeof (struct char_index_entry)); if (!font->char_index) return 1; font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); @@ -304,7 +321,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct #if FONT_DEBUG >= 2 - grub_dprintf ("font", "num_chars=%d)\n", font->num_chars); + grub_printf ("num_chars=%d)\n", font->num_chars); #endif last_code = 0; @@ -348,7 +365,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_dprintf ("font", "c=%d o=%d\n", entry->code, entry->offset); + grub_printf ("c=%d o=%d\n", entry->code, entry->offset); #endif } @@ -361,13 +378,9 @@ static char * read_section_as_string (struct font_file_section *section) { char *str; - grub_size_t sz; grub_ssize_t ret; - if (grub_add (section->length, 1, &sz)) - return NULL; - - str = grub_malloc (sz); + str = grub_malloc (section->length + 1); if (!str) return 0; @@ -409,7 +422,7 @@ read_section_as_short (struct font_file_section *section, /* Load a font and add it to the beginning of the global font list. Returns 0 upon success, nonzero upon failure. */ -grub_font_t +int grub_font_load (const char *filename) { grub_file_t file = 0; @@ -418,11 +431,11 @@ grub_font_load (const char *filename) grub_font_t font = 0; #if FONT_DEBUG >= 1 - grub_dprintf ("font", "add_font(%s)\n", filename); + grub_printf ("add_font(%s)\n", filename); #endif if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+') - file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024); + file = grub_buffile_open (filename, 1024); else { const char *prefix = grub_env_get ("prefix"); @@ -442,14 +455,14 @@ grub_font_load (const char *filename) ptr = grub_stpcpy (ptr, filename); ptr = grub_stpcpy (ptr, ".pf2"); *ptr = 0; - file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); + file = grub_buffile_open (fullname, 1024); grub_free (fullname); } if (!file) goto fail; #if FONT_DEBUG >= 3 - grub_dprintf ("font", "file opened\n"); + grub_printf ("file opened\n"); #endif /* Read the FILE section. It indicates the file format. */ @@ -457,7 +470,7 @@ grub_font_load (const char *filename) goto fail; #if FONT_DEBUG >= 3 - grub_dprintf ("font", "opened FILE section\n"); + grub_printf ("opened FILE section\n"); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE, sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0) @@ -468,7 +481,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_dprintf ("font", "section name ok\n"); + grub_printf ("section name ok\n"); #endif if (section.length != 4) { @@ -479,14 +492,14 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_dprintf ("font", "section length ok\n"); + grub_printf ("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_dprintf ("font", "read magic ok\n"); + grub_printf ("read magic ok\n"); #endif if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0) @@ -497,7 +510,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_dprintf ("font", "compare magic ok\n"); + grub_printf ("compare magic ok\n"); #endif /* Allocate the font object. */ @@ -509,7 +522,7 @@ grub_font_load (const char *filename) font->file = file; #if FONT_DEBUG >= 3 - grub_dprintf ("font", "allocate font ok; loading font info\n"); + grub_printf ("allocate font ok; loading font info\n"); #endif /* Load the font information. */ @@ -524,7 +537,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 2 - grub_dprintf ("font", "opened section %c%c%c%c ok\n", + grub_printf ("opened section %c%c%c%c ok\n", section.name[0], section.name[1], section.name[2], section.name[3]); #endif @@ -532,12 +545,6 @@ 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; @@ -614,7 +621,7 @@ grub_font_load (const char *filename) { /* Unhandled section type, simply skip past it. */ #if FONT_DEBUG >= 3 - grub_dprintf ("font", "Unhandled section type, skipping.\n"); + grub_printf ("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) @@ -629,7 +636,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 1 - grub_dprintf ("font", "Loaded font `%s'.\n" + grub_printf ("Loaded font `%s'.\n" "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n", font->name, font->ascent, font->descent, @@ -650,7 +657,7 @@ grub_font_load (const char *filename) if (register_font (font) != 0) goto fail; - return font; + return 0; fail: if (file) @@ -659,7 +666,7 @@ fail: font->file = 0; free_font (font); - return 0; + return 1; } /* Read a 16-bit big-endian integer from FILE, convert it to native byte @@ -787,7 +794,6 @@ 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; } } @@ -903,6 +909,20 @@ 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 @@ -1044,7 +1064,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) return best_glyph; } -#if 0 static struct grub_font_glyph * grub_font_dup_glyph (struct grub_font_glyph *glyph) { @@ -1056,7 +1075,6 @@ grub_font_dup_glyph (struct grub_font_glyph *glyph) + (glyph->width * glyph->height + 7) / 8); return ret; } -#endif /* FIXME: suboptimal. */ static void @@ -1125,49 +1143,6 @@ 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, @@ -1175,37 +1150,63 @@ 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 blit_comb_ctx ctx = { - .glyph = glyph, - .device_width = device_width - }; + struct grub_video_signed_rect bounds; unsigned i; signed above_rightx, above_righty; signed above_leftx, above_lefty; signed below_rightx, below_righty; signed min_devwidth = 0; - const struct grub_unicode_combining *comb; + 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; + } if (glyph) glyph->device_width = main_glyph->device_width; if (device_width) *device_width = main_glyph->device_width; - 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; + bounds.x = main_glyph->offset_x; + bounds.y = main_glyph->offset_y; + bounds.width = main_glyph->width; + bounds.height = main_glyph->height; above_rightx = main_glyph->offset_x + main_glyph->width; - above_righty = ctx.bounds.y + ctx.bounds.height; + above_righty = bounds.y + bounds.height; above_leftx = main_glyph->offset_x; - above_lefty = ctx.bounds.y + ctx.bounds.height; + above_lefty = bounds.y + bounds.height; - below_rightx = ctx.bounds.x + ctx.bounds.width; - below_righty = ctx.bounds.y; - - comb = grub_unicode_get_comb (glyph_id); + below_rightx = bounds.x + bounds.width; + below_righty = bounds.y; for (i = 0; i < glyph_id->ncomb; i++) { @@ -1215,41 +1216,41 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, if (!combining_glyphs[i]) continue; - targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; + targetx = (bounds.width - combining_glyphs[i]->width) / 2 + bounds.x; /* CGJ is to avoid diacritics reordering. */ - if (comb[i].code + if (glyph_id->combining[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) continue; - switch (comb[i].type) + switch (glyph_id->combining[i].type) { case GRUB_UNICODE_COMB_OVERLAY: do_blit (combining_glyphs[i], targetx, - (ctx.bounds.height - combining_glyphs[i]->height) / 2 - - (ctx.bounds.height + ctx.bounds.y), &ctx); + (bounds.height - combining_glyphs[i]->height) / 2 + - (bounds.height + bounds.y)); 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, &ctx); + do_blit (combining_glyphs[i], above_rightx, -above_righty); 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), &ctx); + -(above_righty + combining_glyphs[i]->height)); 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), &ctx); + -(above_lefty + combining_glyphs[i]->height)); break; case GRUB_UNICODE_COMB_BELOW_RIGHT: - do_blit (combining_glyphs[i], below_rightx, below_righty, &ctx); + do_blit (combining_glyphs[i], below_rightx, below_righty); below_rightx += combining_glyphs[i]->width; break; @@ -1275,7 +1276,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), &ctx); + + combining_glyphs[i]->height)); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1296,19 +1297,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, - -(ctx.bounds.height + ctx.bounds.y + space - + combining_glyphs[i]->height), &ctx); + -(bounds.height + bounds.y + space + + combining_glyphs[i]->height)); 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, - -(ctx.bounds.height / 2 + ctx.bounds.y - + combining_glyphs[i]->height / 2), &ctx); + -(bounds.height / 2 + bounds.y + + combining_glyphs[i]->height / 2)); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1337,17 +1338,15 @@ 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, -(ctx.bounds.y - space), - &ctx); + do_blit (combining_glyphs[i], targetx, -(bounds.y - space)); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_MN: - switch (comb[i].code) + switch (glyph_id->combining[i].code) { case GRUB_UNICODE_THAANA_ABAFILI: case GRUB_UNICODE_THAANA_AABAAFILI: @@ -1374,36 +1373,39 @@ 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), &ctx); - add_device_width (combining_glyphs[i]->device_width, &ctx); + + combining_glyphs[i]->offset_y)); + add_device_width (combining_glyphs[i]->device_width); } } } add_device_width ((above_rightx > below_rightx ? above_rightx : below_rightx) - - (main_glyph->offset_x + main_glyph->width), &ctx); - add_device_width (above_leftx - main_glyph->offset_x, &ctx); + (main_glyph->offset_x + main_glyph->width)); + add_device_width (above_leftx - main_glyph->offset_x); 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 = ctx.bounds; + *bounds_out = 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, + struct grub_font_glyph ***combining_glyphs_out, 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; - const struct grub_unicode_combining *comb; + + if (combining_glyphs_out) + *combining_glyphs_out = NULL; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED) desired_attributes |= GRUB_FONT_CODE_RIGHT_JOINED; @@ -1411,12 +1413,11 @@ 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 (comb[i].type == GRUB_UNICODE_STACK_ABOVE) + if (glyph_id->combining[i].type == GRUB_UNICODE_STACK_ABOVE) break; if (i < glyph_id->ncomb && base == 'i') base = GRUB_UNICODE_DOTLESS_LOWERCASE_I; @@ -1445,6 +1446,8 @@ 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; @@ -1454,33 +1457,18 @@ 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, - comb[i].code); + glyph_id->combining[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; - - render_max_comb_glyphs = 2 * glyph_id->ncomb; - if (render_max_comb_glyphs < 8) - render_max_comb_glyphs = 8; - grub_free (render_combining_glyphs); - render_combining_glyphs = grub_malloc (render_max_comb_glyphs - * sizeof (render_combining_glyphs[0])); - if (!render_combining_glyphs) - grub_errno = 0; -} - int grub_font_get_constructed_device_width (grub_font_t hinted_font, const struct grub_unicode_glyph @@ -1488,11 +1476,8 @@ 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, - render_combining_glyphs, &ret); + NULL, &ret); if (!main_glyph) return unknown_glyph->device_width; return ret; @@ -1504,42 +1489,26 @@ grub_font_construct_glyph (grub_font_t hinted_font, { struct grub_font_glyph *main_glyph; struct grub_video_signed_rect bounds; - static struct grub_font_glyph *glyph = 0; - static grub_size_t max_glyph_size = 0; - - ensure_comb_space (glyph_id); + struct grub_font_glyph *glyph; + struct grub_font_glyph **combining_glyphs; main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, - &bounds, render_combining_glyphs, - NULL); + &bounds, &combining_glyphs, NULL); if (!main_glyph) - return unknown_glyph; + return grub_font_dup_glyph (unknown_glyph); - if (!render_combining_glyphs && glyph_id->ncomb) - return main_glyph; + if (!combining_glyphs) + return grub_font_dup_glyph (main_glyph); - if (!glyph_id->ncomb && !glyph_id->attributes) - return main_glyph; - - if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) - { - grub_free (glyph); - max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; - if (max_glyph_size < 8) - max_glyph_size = 8; - glyph = grub_malloc (max_glyph_size); - } + glyph = + grub_zalloc (sizeof (*glyph) + (bounds.width * bounds.height + 7) / 8); if (!glyph) { grub_errno = GRUB_ERR_NONE; - return main_glyph; + return grub_font_dup_glyph (main_glyph); } - grub_memset (glyph, 0, sizeof (*glyph) - + (bounds.width * bounds.height - + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); - glyph->font = main_glyph->font; glyph->width = bounds.width; glyph->height = bounds.height; @@ -1558,7 +1527,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, render_combining_glyphs, NULL); + blit_comb (glyph_id, glyph, NULL, main_glyph, combining_glyphs, NULL); return glyph; } diff --git a/grub-core/font/font_cmd.c b/grub-core/font/font_cmd.c index f3b36f2d6..90f605d2f 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_COREBOOT) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) 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_COREBOOT) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) 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 220b3712f..ef654791c 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -36,7 +36,7 @@ struct grub_affs_bblock grub_uint8_t flags; grub_uint32_t checksum; grub_uint32_t rootblock; -} GRUB_PACKED; +} __attribute__ ((packed)); /* Set if the filesystem is a AFFS filesystem. Otherwise this is an OFS filesystem. */ @@ -51,14 +51,14 @@ struct grub_affs_rblock grub_uint32_t unused2; grub_uint32_t checksum; grub_uint32_t hashtable[1]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_affs_time { grub_int32_t day; grub_uint32_t min; grub_uint32_t hz; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The second part of a file header block. */ struct grub_affs_file @@ -76,7 +76,7 @@ struct grub_affs_file grub_uint32_t parent; grub_uint32_t extension; grub_uint32_t type; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The location of `struct grub_affs_file' relative to the end of a file header block. */ @@ -97,7 +97,6 @@ enum }; #define AFFS_MAX_LOG_BLOCK_SIZE 4 -#define AFFS_MAX_SUPERBLOCK 1 @@ -185,92 +184,94 @@ grub_affs_mount (grub_disk_t disk) { struct grub_affs_data *data; grub_uint32_t *rootblock = 0; - struct grub_affs_rblock *rblock = 0; + struct grub_affs_rblock *rblock; int log_blocksize = 0; - int bsnum = 0; data = grub_zalloc (sizeof (struct grub_affs_data)); if (!data) return 0; - for (bsnum = 0; bsnum < AFFS_MAX_SUPERBLOCK + 1; bsnum++) + /* 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)) { - /* Read the bootblock. */ - grub_disk_read (disk, bsnum, 0, sizeof (struct grub_affs_bblock), - &data->bblock); + 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); if (grub_errno) goto fail; - /* 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)) + 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; - /* 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; + for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize) + / sizeof (*currblock); + i++) + checksum += grub_be_to_cpu32 (currblock[i]); - 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 (checksum == 0) + break; + } + 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_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE) + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem"); grub_free (data); @@ -301,7 +302,7 @@ grub_affs_read_symlink (grub_fshelp_node_t node) return 0; } latin1[symlink_size] = 0; - utf8 = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, symlink_size); + utf8 = grub_malloc (symlink_size * GRUB_MAX_UTF8_PER_LATIN1 + 1); if (!utf8) { grub_free (latin1); @@ -316,87 +317,12 @@ grub_affs_read_symlink (grub_fshelp_node_t node) } -/* Helper for grub_affs_iterate_dir. */ -static int -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 **hashtable, - grub_uint32_t block, const struct grub_affs_file *fil) -{ - struct grub_affs_data *data = dir->data; - 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; - - *node = grub_zalloc (sizeof (**node)); - if (!*node) - { - 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; - } - break; - } - - if (nest == 8) - return 0; - - type |= GRUB_FSHELP_CASE_INSENSITIVE; - - if (hook ((char *) name_u8, type, *node, hook_data)) - { - grub_free (*hashtable); - *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) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { unsigned int i; struct grub_affs_file file; @@ -404,13 +330,88 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, struct grub_affs_data *data = dir->data; grub_uint32_t *hashtable; + auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, + const struct grub_affs_file *fil); + + int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, + const struct grub_affs_file *fil) + { + 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) + { + 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; + } + 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; + return 0; + } + /* Create the directory entries for `.' and `..'. */ node = grub_zalloc (sizeof (*node)); if (!node) return 1; *node = *dir; - if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) + if (hook (".", GRUB_FSHELP_DIR, node)) return 1; if (dir->parent) { @@ -418,11 +419,11 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (!node) return 1; *node = *dir->parent; - if (hook ("..", GRUB_FSHELP_DIR, node, hook_data)) + if (hook ("..", GRUB_FSHELP_DIR, node)) return 1; } - hashtable = grub_calloc (data->htsize, sizeof (*hashtable)); + hashtable = grub_zalloc (data->htsize * sizeof (*hashtable)); if (!hashtable) return 1; @@ -454,8 +455,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - if (grub_affs_create_node (dir, hook, hook_data, &node, &hashtable, - next, &file)) + if (grub_affs_create_node (next, &file)) return 1; next = grub_be_to_cpu32 (file.next); @@ -531,7 +531,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_data, + file->read_hook, file->offset, len, buf, grub_affs_read_block, grub_be_to_cpu32 (data->diropen.di.size), data->log_blocksize, 0); @@ -546,37 +546,31 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -588,7 +582,7 @@ grub_affs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_affs_iterate_dir (fdiro, grub_affs_dir_iter, &ctx); + grub_affs_iterate_dir (fdiro, iterate); fail: if (data && fdiro != &data->diropen) @@ -628,7 +622,7 @@ grub_affs_label (grub_device_t device, char **label) len = file.namelen; if (len > sizeof (file.name)) len = sizeof (file.name); - *label = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, len); + *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); if (*label) *grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0'; } @@ -685,12 +679,12 @@ grub_affs_mtime (grub_device_t device, grub_int32_t *t) static struct grub_fs grub_affs_fs = { .name = "affs", - .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, + .dir = grub_affs_dir, + .open = grub_affs_open, + .read = grub_affs_read, + .close = grub_affs_close, + .label = grub_affs_label, + .mtime = grub_affs_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 0, diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c deleted file mode 100644 index 0cf544f6f..000000000 --- a/grub-core/fs/archelp.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * 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 - -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; - - *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); - target = grub_malloc (linktarget_len + grub_strlen (*name) + 2); - 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 (((!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 47dbe2011..318dc3eec 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -29,7 +29,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -74,7 +73,7 @@ struct grub_bfs_extent grub_uint32_t ag; grub_uint16_t start; grub_uint16_t len; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_bfs_superblock { @@ -90,7 +89,7 @@ struct grub_bfs_superblock grub_uint8_t unused3[32]; grub_uint32_t magic3; struct grub_bfs_extent root_dir; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_bfs_inode { @@ -119,11 +118,11 @@ struct grub_bfs_inode grub_uint64_t max_double_indirect_range; grub_uint64_t size; grub_uint32_t pad[4]; - } GRUB_PACKED; + } __attribute__ ((packed)); char inplace_link[144]; - } GRUB_PACKED; + } __attribute__ ((packed)); grub_uint8_t small_data[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); enum { @@ -135,7 +134,7 @@ struct grub_bfs_small_data_element_header grub_uint32_t type; grub_uint16_t name_len; grub_uint16_t value_len; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_bfs_btree_header { @@ -152,7 +151,7 @@ struct grub_bfs_btree_header grub_uint64_t root; #endif grub_uint32_t unused2[2]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_bfs_btree_node { @@ -166,21 +165,12 @@ struct grub_bfs_btree_node grub_uint16_t count_keys; grub_uint16_t total_key_len; #endif -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_bfs_data { struct grub_bfs_superblock sb; - 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; + struct grub_bfs_inode ino[0]; }; static grub_err_t @@ -218,7 +208,9 @@ 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, - grub_disk_read_hook_t read_hook, void *read_hook_data) + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, + unsigned length)) { if (len == 0) return GRUB_ERR_NONE; @@ -244,7 +236,6 @@ 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; @@ -290,7 +281,6 @@ 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; @@ -402,7 +392,6 @@ 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; @@ -420,77 +409,18 @@ read_bfs_file (grub_disk_t disk, } } -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 (*hook) (const char *name, grub_uint64_t value, - struct grub_bfs_dir_ctx *ctx), - struct grub_bfs_dir_ctx *ctx) + int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t value)) { 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, 0); + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); if (err) return 0; node_off = grub_bfs_to_cpu64 (head.root); @@ -500,8 +430,7 @@ 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, 0); + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off @@ -511,7 +440,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, 0); + sizeof (grub_uint64_t), 0); if (err) return 0; @@ -520,51 +449,67 @@ iterate_in_b_tree (grub_disk_t disk, while (1) { - 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); - + struct grub_bfs_btree_node node; + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 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].val), - ctx)) - { - grub_free (node); + { + 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]))) return 1; - } key_data[end] = c; } - node_off = grub_bfs_to_cpu64 (node->right); - grub_free (node); + node_off = grub_bfs_to_cpu64 (node.right); 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) @@ -575,13 +520,16 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen) alen--; } - ac = alen ? *a : 0; - bc = *b; - #ifdef MODE_AFS - return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc; + if (!alen) + return - (int) (grub_int8_t) *b; + + return (int) (grub_int8_t) *a - (int) (grub_int8_t) *b; #else - return (int) (grub_uint8_t) ac - (int) (grub_uint8_t) bc; + if (!alen) + return - (int) (grub_uint8_t) *b; + + return (int) (grub_uint8_t) *a - (int) (grub_uint8_t) *b; #endif } @@ -596,7 +544,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, 0); + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); if (err) return err; node_off = grub_bfs_to_cpu64 (head.root); @@ -604,221 +552,264 @@ find_in_b_tree (grub_disk_t disk, level = grub_bfs_to_cpu32 (head.level) - 1; while (1) { - 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); + struct grub_bfs_btree_node node; + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); 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; - if (node->count_keys == 0) - { - grub_free (node); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), - name); - } + int lg, j; - 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)].val); - grub_free (node); - 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)]); + 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].val); - grub_free (node); - 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]); + 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].val); + node_off = grub_bfs_to_cpu64 (key_values[0]); 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].val); + node_off = grub_bfs_to_cpu64 (key_values[1]); 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].val); + node_off = grub_bfs_to_cpu64 (key_values[i + 1]); 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 -lookup_file (grub_fshelp_node_t dir, - const char *name, - grub_fshelp_node_t *foundnode, - enum grub_fshelp_filetype *foundtype) +hop_level (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + struct grub_bfs_inode *ino, const char *name) { grub_err_t err; - struct grub_bfs_inode *new_ino; grub_uint64_t res = 0; - err = find_in_b_tree (dir->disk, dir->sb, &dir->ino, name, &res); + 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); if (err) return err; - *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; + 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); } static grub_err_t find_file (const char *path, grub_disk_t disk, - const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino, - enum grub_fshelp_filetype exptype) + const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) { + char *ptr, *ptr2; + char *alloc = NULL; grub_err_t err; - struct grub_fshelp_node root = { - .disk = disk, - .sb = sb, - }; - struct grub_fshelp_node *found; + union + { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; + } old_ino; + unsigned symlinks_max = 32; - err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino, - sizeof (root.ino)); + err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, + grub_bfs_to_cpu32 (sb->bsize)); 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)); - if (&root != found) - grub_free (found); - return err; + 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; + } } static grub_err_t @@ -853,58 +844,61 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook_in) (const char *filename, + const struct grub_dirhook_info * info)) { - struct grub_bfs_dir_ctx ctx = { - .device = device, - .hook = hook, - .hook_data = hook_data - }; + struct grub_bfs_superblock sb; grub_err_t err; + auto int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value); - err = mount (device->disk, &ctx.sb); + 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); if (err) return err; { - struct grub_bfs_inode ino; - err = find_file (path, device->disk, &ctx.sb, &ino, GRUB_FSHELP_DIR); + 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); if (err) return err; - iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter, - &ctx); + 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); } return grub_errno; @@ -921,19 +915,26 @@ grub_bfs_open (struct grub_file *file, const char *name) return err; { - struct grub_bfs_inode ino; + union + { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; + } ino; struct grub_bfs_data *data; - err = find_file (name, file->device->disk, &sb, &ino, GRUB_FSHELP_REG); + err = find_file (name, file->device->disk, &sb, &ino.ino); 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)); + data = grub_zalloc (sizeof (struct grub_bfs_data) + + grub_bfs_to_cpu32 (sb.bsize)); if (!data) return grub_errno; data->sb = sb; - grub_memcpy (&data->ino, &ino, sizeof (data->ino)); + grub_memcpy (&data->ino, &ino, grub_bfs_to_cpu32 (sb.bsize)); file->data = data; - file->size = grub_bfs_to_cpu64 (ino.size); + file->size = grub_bfs_to_cpu64 (ino.ino.size); } return GRUB_ERR_NONE; @@ -954,8 +955,7 @@ 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, file->read_hook_data); + data->ino, file->offset, buf, len, file->read_hook); if (err) return -1; return len; @@ -981,7 +981,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, - struct grub_bfs_inode *ino, + const 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,27 +1012,32 @@ 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, ino, + err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, grub_bfs_to_cpu32 (sb->bsize)); if (err) return -1; - err = find_in_b_tree (disk, sb, ino, name, &res); + err = find_in_b_tree (disk, sb, &ino2.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 *) ino); - read = grub_bfs_to_cpu64 (ino->size); + grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); + read = grub_bfs_to_cpu64 (ino2.ino.size); if (read > len) read = len; - err = read_bfs_file (disk, sb, ino, 0, buf, read, 0, 0); + err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0); if (err) return -1; return read; @@ -1045,8 +1050,6 @@ 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; @@ -1054,24 +1057,23 @@ grub_bfs_uuid (grub_device_t device, char **uuid) if (err) return err; - 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) + { + union { - grub_free (ino); + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; + } ino; + grub_uint64_t vid; + + err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, + &ino, grub_bfs_to_cpu32 (sb.bsize)); + if (err) return err; - } - 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); - + 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)); + } return GRUB_ERR_NONE; } #endif @@ -1082,13 +1084,13 @@ static struct grub_fs grub_bfs_fs = { #else .name = "bfs", #endif - .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, + .dir = grub_bfs_dir, + .open = grub_bfs_open, + .read = grub_bfs_read, + .close = grub_bfs_close, + .label = grub_bfs_label, #ifndef MODE_AFS - .fs_uuid = grub_bfs_uuid, + .uuid = grub_bfs_uuid, #endif #ifdef GRUB_UTIL .reserved_first_sector = 1, diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 27339bdb3..a993f0747 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,2011,2012,2013 Free Software Foundation, Inc. + * 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 @@ -17,14 +17,6 @@ * 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 @@ -35,12 +27,7 @@ #include #include #include -#include #include -#include -#include -#include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -57,9 +44,6 @@ 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]; @@ -68,7 +52,7 @@ struct grub_btrfs_device grub_uint64_t device_id; grub_uint64_t size; grub_uint8_t dummy[0x62 - 0x10]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_superblock { @@ -86,17 +70,16 @@ struct grub_btrfs_superblock char label[0x100]; grub_uint8_t dummy4[0x100]; grub_uint8_t bootstrap_mapping[0x800]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct btrfs_header { grub_btrfs_checksum_t checksum; grub_btrfs_uuid_t uuid; - grub_uint64_t bytenr; - grub_uint8_t dummy[0x28]; + grub_uint8_t dummy[0x30]; grub_uint32_t nitems; grub_uint8_t level; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_device_desc { @@ -123,6 +106,24 @@ 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; @@ -135,35 +136,31 @@ 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; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_chunk_stripe { grub_uint64_t device_id; grub_uint64_t offset; grub_btrfs_uuid_t device_uuid; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_leaf_node { struct grub_btrfs_key key; grub_uint32_t offset; grub_uint32_t size; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_internal_node { struct grub_btrfs_key key; grub_uint64_t addr; grub_uint64_t dummy; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_dir_item { @@ -176,7 +173,7 @@ struct grub_btrfs_dir_item #define GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK 7 grub_uint8_t type; char name[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_leaf_descriptor { @@ -191,11 +188,18 @@ 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; -} GRUB_PACKED; +} __attribute__ ((aligned (4))); struct grub_btrfs_inode { @@ -203,7 +207,7 @@ struct grub_btrfs_inode grub_uint64_t size; grub_uint8_t dummy2[0x70]; struct grub_btrfs_time mtime; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_btrfs_extent_data { @@ -224,7 +228,7 @@ struct grub_btrfs_extent_data grub_uint64_t filled; }; }; -} GRUB_PACKED; +} __attribute__ ((packed)); #define GRUB_BTRFS_EXTENT_INLINE 0 #define GRUB_BTRFS_EXTENT_REGULAR 1 @@ -232,7 +236,6 @@ 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 @@ -248,11 +251,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]) @@ -305,25 +308,6 @@ 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) @@ -332,13 +316,9 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc, if (desc->allocated < desc->depth) { void *newdata; - 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); + desc->allocated *= 2; + newdata = grub_realloc (desc->data, sizeof (desc->data[0]) + * desc->allocated); if (!newdata) return grub_errno; desc->data = newdata; @@ -383,7 +363,6 @@ next (struct grub_btrfs_data *data, err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head, sizeof (head), 0); - check_btrfs_header (data, &head, grub_le_to_cpu64 (node.addr)); if (err) return -err; @@ -420,7 +399,7 @@ lower_bound (struct grub_btrfs_data *data, { desc->allocated = 16; desc->depth = 0; - desc->data = grub_calloc (desc->allocated, sizeof (desc->data[0])); + desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated); if (!desc->data) return grub_errno; } @@ -445,7 +424,6 @@ lower_bound (struct grub_btrfs_data *data, /* FIXME: preread few nodes into buffer. */ err = grub_btrfs_read_logical (data, addr, &head, sizeof (head), recursion_depth + 1); - check_btrfs_header (data, &head, addr); if (err) return err; addr += sizeof (head); @@ -560,301 +538,81 @@ lower_bound (struct grub_btrfs_data *data, } } -/* Context for find_device. */ -struct find_device_ctx -{ - 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; - } - 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; - } - - ctx->dev_found = dev; - return 1; -} - static grub_device_t -find_device (struct grub_btrfs_data *data, grub_uint64_t id) +find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) { - struct find_device_ctx ctx = { - .data = data, - .id = id, - .dev_found = NULL - }; + 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) + 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; + } + + dev_found = dev; + return 1; + } + unsigned i; for (i = 0; i < data->n_devices_attached; i++) if (id == data->devices_attached[i].id) return data->devices_attached[i].dev; - - grub_device_iterate (find_device_iter, &ctx); - + 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; + } data->n_devices_attached++; if (data->n_devices_attached > data->n_devices_allocated) { void *tmp; - 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); + 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])); 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 = 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; + data->devices_attached[data->n_devices_attached - 1].dev = dev_found; + return dev_found; } static grub_err_t @@ -870,6 +628,7 @@ 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; @@ -930,16 +689,8 @@ 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) { @@ -948,17 +699,15 @@ 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), - nstripes, + grub_le_to_cpu16 (chunk->nstripes), grub_le_to_cpu16 (chunk->nsubstripes), - chunk_stripe_length); + grub_le_to_cpu64 (chunk->stripe_length)); switch (grub_le_to_cpu64 (chunk->type) & ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE) @@ -968,27 +717,20 @@ 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), - nstripes, + grub_le_to_cpu16 (chunk->nstripes), NULL); - 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 (copies: %d)\n", ++redundancy); + grub_dprintf ("btrfs", "RAID1\n"); stripen = 0; stripe_offset = off; csize = grub_le_to_cpu64 (chunk->size) - off; + redundancy = 2; break; } case GRUB_BTRFS_CHUNK_TYPE_RAID0: @@ -997,114 +739,33 @@ 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, - chunk_stripe_length, + grub_le_to_cpu64 (chunk->stripe_length), &low); - high = grub_divmod64 (middle, nstripes, + high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes), &stripen); stripe_offset = - low + chunk_stripe_length * high; - csize = chunk_stripe_length - low; + low + grub_le_to_cpu64 (chunk->stripe_length) * high; + csize = grub_le_to_cpu64 (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, - chunk_stripe_length, + grub_le_to_cpu64 (chunk->stripe_length), &low); high = grub_divmod64 (middle, - nstripes / nsubstripes ? : 1, + grub_le_to_cpu16 (chunk->nstripes) + / grub_le_to_cpu16 (chunk->nsubstripes), &stripen); - stripen *= nsubstripes; - redundancy = nsubstripes; - stripe_offset = low + chunk_stripe_length + stripen *= grub_le_to_cpu16 (chunk->nsubstripes); + redundancy = grub_le_to_cpu16 (chunk->nsubstripes); + stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) * high; - csize = chunk_stripe_length - low; - 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.). - */ - 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; - + csize = grub_le_to_cpu64 (chunk->stripe_length) - low; break; } default: @@ -1121,41 +782,49 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, for (j = 0; j < 2; j++) { - 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 (is_raid56) + for (i = 0; i < redundancy; i++) { - err = btrfs_read_from_chunk (data, chunk, stripen, - stripe_offset, - 0, /* no mirror */ - csize, buf); + 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; - 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) + if (i != redundancy) break; } if (err) @@ -1214,8 +883,7 @@ 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++) - if (data->devices_attached[i].dev) - grub_device_close (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); @@ -1246,102 +914,13 @@ 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)); @@ -1385,21 +964,13 @@ 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) - { - grub_free (buf); - return -1; - } + return -1; if (to_copy > usize) to_copy = usize; @@ -1410,8 +981,6 @@ 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; } @@ -1482,7 +1051,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); @@ -1511,8 +1080,7 @@ 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_ZSTD) + && data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "compression type 0x%x not supported", @@ -1536,12 +1104,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, - (grub_uint8_t *) data->extent), extoff, buf, csize) != (grub_ssize_t) csize) - { - if (!grub_errno) - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, - "premature end of compressed"); - return -1; - } + return -1; } else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) { @@ -1552,15 +1115,6 @@ 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; @@ -1598,22 +1152,13 @@ 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) - { - if (!grub_errno) - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, - "premature end of compressed"); - return -1; - } + return -1; break; } @@ -1636,40 +1181,6 @@ 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, @@ -1682,31 +1193,42 @@ 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; - 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) { - 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 (!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; + } if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { @@ -1717,8 +1239,10 @@ find_path (struct grub_btrfs_data *data, if (ctokenlen == 1 && ctoken[0] == '.') { - path = slash; - continue; + if (!skip_default) + path = slash; + skip_default = 0; + continue; } if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.') { @@ -1748,7 +1272,9 @@ find_path (struct grub_btrfs_data *data, *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; key->object_id = key_out.offset; - path = slash; + if (!skip_default) + path = slash; + skip_default = 0; continue; } @@ -1818,7 +1344,9 @@ find_path (struct grub_btrfs_data *data, return err; } - path = slash; + if (!skip_default) + path = slash; + skip_default = 0; if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) { struct grub_btrfs_inode inode; @@ -1868,9 +1396,12 @@ find_path (struct grub_btrfs_data *data, path = path_alloc = tmp; if (path[0] == '/') { - 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; } continue; } @@ -1945,7 +1476,8 @@ find_path (struct grub_btrfs_data *data, static grub_err_t grub_btrfs_dir (grub_device_t device, const char *path, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_key key_in, key_out; @@ -2039,7 +1571,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, hook_data)) + if (hook (cdirel->name, &info)) goto out; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c; } @@ -2177,7 +1709,7 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), *nsectors = 64 * 2 - 1; if (*nsectors > max_nsectors) *nsectors = max_nsectors; - *sectors = grub_calloc (*nsectors, sizeof (**sectors)); + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); if (!*sectors) return grub_errno; for (i = 0; i < *nsectors; i++) @@ -2189,14 +1721,14 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), static struct grub_fs grub_btrfs_fs = { .name = "btrfs", - .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, + .dir = grub_btrfs_dir, + .open = grub_btrfs_open, + .read = grub_btrfs_read, + .close = grub_btrfs_close, + .uuid = grub_btrfs_uuid, + .label = grub_btrfs_label, #ifdef GRUB_UTIL - .fs_embed = grub_btrfs_embed, + .embed = grub_btrfs_embed, .reserved_first_sector = 1, .blocklist_install = 0, #endif diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c deleted file mode 100644 index 857bea991..000000000 --- a/grub-core/fs/cbfs.c +++ /dev/null @@ -1,402 +0,0 @@ -/* 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 - -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_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN) - goto fail; - - if (grub_disk_read (disk, grub_disk_get_size (disk) - 1, - GRUB_DISK_SECTOR_SIZE - sizeof (ptr), - sizeof (ptr), &ptr)) - goto fail; - - ptr = grub_cpu_to_le32 (ptr); - header_off = (grub_disk_get_size (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_get_size (disk) << GRUB_DISK_SECTOR_BITS) - - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset)); - data->cbfs_end = (grub_disk_get_size (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_get_size (disk) << GRUB_DISK_SECTOR_BITS)) - goto fail; - if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)) - data->cbfs_end = (grub_disk_get_size (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 *) 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 - grub_fs_register (&grub_cbfs_fs); -} - -GRUB_MOD_FINI (cbfs) -{ - 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 dab5f9898..e9236cd97 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,2013 Free Software Foundation, Inc. + * Copyright (C) 2007,2008,2009 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,11 +17,66 @@ * 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]; @@ -35,27 +90,695 @@ struct head grub_uint16_t mtime[2]; grub_uint16_t namesize[1]; grub_uint16_t filesize[2]; -} GRUB_PACKED; +} __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 +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 -#define FSNAME "cpiofs" - -#include "cpio_common.c" - -GRUB_MOD_INIT (cpio) +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) { - grub_fs_register (&grub_cpio_fs); +#ifndef MODE_USTAR + struct head hd; + grub_size_t namesize; + grub_uint32_t modeval; + + 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"); + 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_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 846548892..8bad314cd 100644 --- a/grub-core/fs/cpio_be.c +++ b/grub-core/fs/cpio_be.c @@ -1,61 +1,2 @@ -/* 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_fs_register (&grub_cpio_fs); -} - -GRUB_MOD_FINI (cpio_be) -{ - grub_fs_unregister (&grub_cpio_fs); -} +#define MODE_BIGENDIAN 1 +#include "cpio.c" diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c deleted file mode 100644 index 4e885d623..000000000 --- a/grub-core/fs/cpio_common.c +++ /dev/null @@ -1,253 +0,0 @@ -/* 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 - -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; - - 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"); - 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)); - - /* 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; - - *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) - { - *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; - - if (data->size == 0) - return grub_strdup (""); - ret = grub_malloc (data->size + 1); - 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/ext2.c b/grub-core/fs/ext2.c index ac33bcd68..c50e379d6 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -46,7 +46,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -59,15 +58,14 @@ 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) (1U << LOG2_BLOCK_SIZE (data)) +#define EXT2_BLOCK_SIZE(data) (1 << 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) \ - (data->sblock.revision_level \ - == grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) \ + (EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \ ? EXT2_GOOD_OLD_INODE_SIZE \ : grub_le_to_cpu16 (data->sblock.inode_size)) @@ -101,31 +99,21 @@ 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_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 \ - | EXT2_FEATURE_INCOMPAT_META_BG \ - | EXT4_FEATURE_INCOMPAT_64BIT \ - | EXT4_FEATURE_INCOMPAT_ENCRYPT) + | EXT4_FEATURE_INCOMPAT_FLEX_BG ) /* 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. - * mmp: Not really back-incompatible - was added as such to - * avoid multiple read-write mounts. Safe to ignore for this - * RO driver. - */ -#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \ - | EXT4_FEATURE_INCOMPAT_MMP) + * the ext2 drivers. Safe to ignore for this RO driver. */ +#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER ) #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U @@ -141,7 +129,6 @@ 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. */ @@ -192,7 +179,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 group_desc_size; + grub_uint16_t reserved_word_pad; grub_uint32_t default_mount_opts; grub_uint32_t first_meta_bg; grub_uint32_t mkfs_time; @@ -210,14 +197,6 @@ 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. */ @@ -258,7 +237,6 @@ struct ext2_dirent { grub_uint32_t inode; grub_uint16_t direntlen; -#define MAX_NAMELEN 255 grub_uint8_t namelen; grub_uint8_t filetype; }; @@ -332,7 +310,6 @@ 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; @@ -342,78 +319,25 @@ 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, grub_uint64_t group, +grub_ext2_blockgroup (struct grub_ext2_data *data, int 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) - + block) - << LOG2_EXT2_BLOCK_SIZE (data)), offset, + ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1) + << LOG2_EXT2_BLOCK_SIZE (data)), + group * sizeof (struct grub_ext2_block_group), sizeof (struct grub_ext2_block_group), blkgrp); } static struct grub_ext4_extent_header * -grub_ext4_find_leaf (struct grub_ext2_data *data, +grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, struct grub_ext4_extent_header *ext_block, grub_uint32_t fileblock) { struct grub_ext4_extent_idx *index; - void *buf = NULL; while (1) { @@ -422,8 +346,8 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, index = (struct grub_ext4_extent_idx *) (ext_block + 1); - if (ext_block->magic != grub_cpu_to_le16_compile_time (EXT4_EXT_MAGIC)) - goto fail; + if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC) + return 0; if (ext_block->depth == 0) return ext_block; @@ -435,24 +359,17 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, } if (--i < 0) - goto fail; + return 0; block = grub_le_to_cpu16 (index[i].leaf_hi); - block = (block << 32) | grub_le_to_cpu32 (index[i].leaf); - if (!buf) - buf = grub_malloc (EXT2_BLOCK_SIZE(data)); - if (!buf) - goto fail; + block = (block << 32) + grub_le_to_cpu32 (index[i].leaf); if (grub_disk_read (data->disk, block << LOG2_EXT2_BLOCK_SIZE (data), 0, EXT2_BLOCK_SIZE(data), buf)) - goto fail; + return 0; - ext_block = buf; + ext_block = (struct grub_ext4_extent_header *) buf; } - fail: - grub_free (buf); - return 0; } static grub_disk_addr_t @@ -460,21 +377,20 @@ 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 (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG)) + if (grub_le_to_cpu32(inode->flags) & 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; - leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock); + leaf = grub_ext4_find_leaf (data, buf, + (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, + fileblock); if (! leaf) { grub_error (GRUB_ERR_BAD_FS, "invalid extent"); @@ -492,7 +408,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)) - ret = 0; + return 0; else { grub_disk_addr_t start; @@ -500,80 +416,107 @@ 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); - ret = fileblock + start; + return fileblock + start; } } else { grub_error (GRUB_ERR_BAD_FS, "something wrong with extent"); - ret = -1; + return -1; } - - if (leaf != (struct grub_ext4_extent_header *) inode->blocks.dir_blocks) - grub_free (leaf); - - return ret; } - /* Direct blocks. */ if (fileblock < INDIRECT_BLOCKS) - return grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); - fileblock -= INDIRECT_BLOCKS; + blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); /* Indirect. */ - if (fileblock < blksz_quarter) + else if (fileblock < INDIRECT_BLOCKS + blksz / 4) { - indir = inode->blocks.indir_block; - shift = 0; - goto indirect; + 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]); } - fileblock -= blksz_quarter; /* Double indirect. */ - if (fileblock < blksz_quarter * blksz_quarter) + else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)) { - indir = inode->blocks.double_indir_block; - shift = 1; - goto indirect; + 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]); } - fileblock -= blksz_quarter * blksz_quarter; - /* Triple indirect. */ - if (fileblock < blksz_quarter * blksz_quarter * (blksz_quarter + 1)) + /* triple indirect. */ + else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1) + + (blksz / 4) * (blksz / 4) * (blksz / 4 + 1)) { - indir = inode->blocks.triple_indir_block; - shift = 2; - goto indirect; + 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"); } - grub_error (GRUB_ERR_BAD_FS, - "ext2fs doesn't support quadruple indirect blocks"); - return -1; -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); + return blknr; } /* 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, - grub_disk_read_hook_t read_hook, void *read_hook_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) { - return grub_fshelp_read_file (node->data->disk, node, - read_hook, read_hook_data, + return grub_fshelp_read_file (node->data->disk, node, read_hook, 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), @@ -592,7 +535,6 @@ 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--; @@ -609,14 +551,10 @@ 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, - ((base + blkno) << LOG2_EXT2_BLOCK_SIZE (data)), + (((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) + << LOG2_EXT2_BLOCK_SIZE (data)), EXT2_INODE_SIZE (data) * blkoff, sizeof (struct grub_ext2_inode), inode)) return grub_errno; @@ -640,42 +578,21 @@ grub_ext2_mount (grub_disk_t disk) goto fail; /* Make sure this is an ext2 filesystem. */ - 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) + if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC + || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16) { 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 (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)))) + if (grub_le_to_cpu32 (data->sblock.feature_incompat) + & ~(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; @@ -704,41 +621,28 @@ 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; - } } - 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); + symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1); 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) <= sizeof (diro->inode.symlink)) - grub_memcpy (symlink, - diro->inode.symlink, - grub_le_to_cpu32 (diro->inode.size)); + if (grub_le_to_cpu32 (diro->inode.size) <= 60) + grub_strncpy (symlink, + diro->inode.symlink, + grub_le_to_cpu32 (diro->inode.size)); else { - grub_ext2_read_file (diro, 0, 0, 0, + grub_ext2_read_file (diro, 0, 0, grub_le_to_cpu32 (diro->inode.size), symlink); if (grub_errno) @@ -754,7 +658,10 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) static int grub_ext2_iterate_dir (grub_fshelp_node_t dir, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { unsigned int fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; @@ -766,18 +673,12 @@ 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, 0, fpos, sizeof (struct ext2_dirent), + grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent), (char *) &dirent); if (grub_errno) return 0; @@ -787,11 +688,11 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, if (dirent.inode != 0 && dirent.namelen != 0) { - char filename[MAX_NAMELEN + 1]; + char filename[dirent.namelen + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; - grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent), + grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent), dirent.namelen, filename); if (grub_errno) return 0; @@ -842,7 +743,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_REG; } - if (hook (filename, type, fdiro, hook_data)) + if (hook (filename, type, fdiro)) return 1; } @@ -882,12 +783,6 @@ 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); @@ -924,75 +819,64 @@ 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, file->read_hook_data, + return grub_ext2_read_file (&data->diropen, file->read_hook, file->offset, len, buf); } -/* Context for grub_ext2_dir. */ -struct grub_ext2_dir_ctx -{ - grub_fs_dir_hook_t hook; - void *hook_data; - struct grub_ext2_data *data; -}; - -/* 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; - - grub_memset (&info, 0, sizeof (info)); - if (! node->inode_read) - { - 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) +grub_ext2_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - struct grub_ext2_dir_ctx ctx = { - .hook = hook, - .hook_data = hook_data - }; + struct grub_ext2_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) + { + 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_dl_ref (my_mod); - ctx.data = grub_ext2_mount (device->disk); - if (! ctx.data) + data = grub_ext2_mount (device->disk); + if (! data) goto fail; - grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, - grub_ext2_iterate_dir, grub_ext2_read_symlink, - GRUB_FSHELP_DIR); + grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir, + grub_ext2_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx); + grub_ext2_iterate_dir (fdiro, iterate); fail: - if (fdiro != &ctx.data->diropen) + if (fdiro != &data->diropen) grub_free (fdiro); - grub_free (ctx.data); + grub_free (data); grub_dl_unref (my_mod); @@ -1080,13 +964,13 @@ grub_ext2_mtime (grub_device_t device, grub_int32_t *tm) static struct grub_fs grub_ext2_fs = { .name = "ext2", - .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, + .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, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c deleted file mode 100644 index 8a9992ca9..000000000 --- a/grub-core/fs/f2fs.c +++ /dev/null @@ -1,1328 +0,0 @@ -/* - * 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 - -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 - -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[3900]; - 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_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) -{ - struct grub_f2fs_checkpoint *ckpt = &data->ckpt; - grub_uint32_t offset; - - 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); - - 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) -{ - int mask; - - p += (nr >> 3); - 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_uint32_t -get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid) -{ - grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); - grub_uint32_t blkaddr = 0; - grub_uint16_t i; - - 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 blkaddr; -} - -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; - grub_err_t err; - - blkaddr = get_blkaddr_from_nat_journal (data, nid); - 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)); - - if (grub_f2fs_test_bit (block_off, data->nat_bitmap)) - block_addr += data->blocks_per_seg; - - 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); - - 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: - 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; - - 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); - - symlink = grub_malloc (filesize + 1); - 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; - - 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); - filename = grub_malloc (name_len + 1); - 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_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 7f775a170..119fc945f 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -26,13 +26,7 @@ #include #include #include -#include -#ifndef MODE_EXFAT #include -#else -#include -#endif -#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -66,16 +60,33 @@ 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; @@ -94,7 +105,7 @@ struct grub_fat_dir_entry grub_uint8_t m_time_tenth; grub_uint8_t a_time_tenth; grub_uint8_t reserved2[9]; - } GRUB_PACKED file; + } __attribute__ ((packed)) file; struct { grub_uint8_t flags; grub_uint8_t reserved1; @@ -105,17 +116,17 @@ struct grub_fat_dir_entry grub_uint32_t reserved3; grub_uint32_t first_cluster; grub_uint64_t file_size; - } GRUB_PACKED stream_extension; + } __attribute__ ((packed)) stream_extension; struct { grub_uint8_t flags; grub_uint16_t str[15]; - } GRUB_PACKED file_name; + } __attribute__ ((packed)) file_name; struct { grub_uint8_t character_count; grub_uint16_t str[15]; - } GRUB_PACKED volume_label; - } GRUB_PACKED type_specific; -} GRUB_PACKED; + } __attribute__ ((packed)) volume_label; + } __attribute__ ((packed)) type_specific; +} __attribute__ ((packed)); struct grub_fat_dir_node { @@ -124,7 +135,7 @@ struct grub_fat_dir_node grub_uint64_t file_size; grub_uint64_t valid_size; int have_stream; - int is_contiguous; + int is_label; }; typedef struct grub_fat_dir_node grub_fat_dir_node_t; @@ -144,7 +155,7 @@ struct grub_fat_dir_entry grub_uint16_t w_date; grub_uint16_t first_cluster_low; grub_uint32_t file_size; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_fat_long_name_entry { @@ -156,7 +167,7 @@ struct grub_fat_long_name_entry grub_uint16_t name2[6]; grub_uint16_t first_cluster; grub_uint16_t name3[2]; -} GRUB_PACKED; +} __attribute__ ((packed)); typedef struct grub_fat_dir_entry grub_fat_dir_node_t; @@ -182,26 +193,13 @@ 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; -#ifndef MODE_EXFAT - grub_uint32_t file_size; -#else - grub_uint64_t file_size; -#endif + grub_ssize_t file_size; grub_uint32_t file_cluster; grub_uint32_t cur_cluster_num; grub_uint32_t cur_cluster; -#ifdef MODE_EXFAT - int is_contiguous; -#endif + grub_uint32_t uuid; }; static grub_dl_t my_mod; @@ -338,12 +336,13 @@ 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 ((bpb.volume_flags & grub_cpu_to_le16_compile_time (0x1)) - && bpb.num_fats > 1) + if ((flags & 0x1) && bpb.num_fats > 1) data->fat_sector += data->sectors_per_fat; } #else @@ -440,6 +439,10 @@ 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: @@ -450,8 +453,9 @@ grub_fat_mount (grub_disk_t disk) } static grub_ssize_t -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_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_off_t offset, grub_size_t len, char *buf) { grub_size_t size; @@ -463,87 +467,67 @@ grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node, #ifndef MODE_EXFAT /* This is a special case. FAT12 and FAT16 doesn't have the root directory in clusters. */ - if (node->file_cluster == ~0U) + if (data->file_cluster == ~0U) { - size = (node->data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; + size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; if (size > len) size = len; - if (grub_disk_read (disk, node->data->root_sector, offset, size, buf)) + if (grub_disk_read (disk, 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 = (node->data->cluster_bits + logical_cluster_bits = (data->cluster_bits + GRUB_DISK_SECTOR_BITS); logical_cluster = offset >> logical_cluster_bits; offset &= (1ULL << logical_cluster_bits) - 1; - if (logical_cluster < node->cur_cluster_num) + if (logical_cluster < data->cur_cluster_num) { - node->cur_cluster_num = 0; - node->cur_cluster = node->file_cluster; + data->cur_cluster_num = 0; + data->cur_cluster = data->file_cluster; } while (len) { - while (logical_cluster > node->cur_cluster_num) + while (logical_cluster > data->cur_cluster_num) { /* Find next cluster. */ grub_uint32_t next_cluster; - grub_uint32_t fat_offset; + unsigned long fat_offset; - switch (node->data->fat_size) + switch (data->fat_size) { case 32: - fat_offset = node->cur_cluster << 2; + fat_offset = data->cur_cluster << 2; break; case 16: - fat_offset = node->cur_cluster << 1; + fat_offset = data->cur_cluster << 1; break; default: /* case 12: */ - fat_offset = node->cur_cluster + (node->cur_cluster >> 1); + fat_offset = data->cur_cluster + (data->cur_cluster >> 1); break; } /* Read the FAT. */ - if (grub_disk_read (disk, node->data->fat_sector, fat_offset, - (node->data->fat_size + 7) >> 3, + if (grub_disk_read (disk, data->fat_sector, fat_offset, + (data->fat_size + 7) >> 3, (char *) &next_cluster)) return -1; next_cluster = grub_le_to_cpu32 (next_cluster); - switch (node->data->fat_size) + switch (data->fat_size) { case 16: next_cluster &= 0xFFFF; break; case 12: - if (node->cur_cluster & 1) + if (data->cur_cluster & 1) next_cluster >>= 4; next_cluster &= 0x0FFF; @@ -551,33 +535,32 @@ grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node, } grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", - node->data->fat_size, next_cluster); + data->fat_size, next_cluster); /* Check the end. */ - if (next_cluster >= node->data->cluster_eof_mark) + if (next_cluster >= data->cluster_eof_mark) return ret; - if (next_cluster < 2 || next_cluster >= node->data->num_clusters) + if (next_cluster < 2 || next_cluster >= data->num_clusters) { grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u", next_cluster); return -1; } - node->cur_cluster = next_cluster; - node->cur_cluster_num++; + data->cur_cluster = next_cluster; + data->cur_cluster_num++; } /* Read the data here. */ - sector = (node->data->cluster_sector - + ((node->cur_cluster - 2) - << node->data->cluster_bits)); + sector = (data->cluster_sector + + ((data->cur_cluster - 2) + << 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) @@ -597,7 +580,6 @@ 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 @@ -638,39 +620,39 @@ grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt) #ifdef MODE_EXFAT static grub_err_t -grub_fat_iterate_dir_next (grub_fshelp_node_t node, +grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, struct grub_fat_iterate_context *ctxt) { grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir)); while (1) { - struct grub_fat_dir_entry *dir = &ctxt->entry; + struct grub_fat_dir_entry dir; - ctxt->offset += sizeof (*dir); + ctxt->offset += sizeof (dir); - if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (*dir), - (char *) dir) - != sizeof (*dir)) + if (grub_fat_read_data (disk, data, 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 (node->disk, node, 0, 0, + if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (sec), (char *) &sec) != sizeof (sec)) break; @@ -687,8 +669,6 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, 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: { @@ -707,7 +687,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, if (i != nsec) { - ctxt->offset -= sizeof (*dir); + ctxt->offset -= sizeof (dir); continue; } @@ -717,51 +697,24 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, 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_int32_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_fshelp_node_t node, +grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, struct grub_fat_iterate_context *ctxt) { char *filep = 0; @@ -776,7 +729,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, ctxt->offset += sizeof (ctxt->dir); /* Read a directory entry. */ - if (grub_fat_read_data (node->disk, node, 0, 0, + if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (ctxt->dir), (char *) &ctxt->dir) != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0) @@ -863,9 +816,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, i--; } - /* XXX should we check that dir position is 0 or 1? */ - if (i > 2 || filep[0] != '.' || (i == 2 && filep[1] != '.')) - *filep++ = '.'; + *filep++ = '.'; for (i = 8; i < 11 && ctxt->dir.name[i]; i++) *filep++ = grub_tolower (ctxt->dir.name[i]); @@ -885,45 +836,65 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, 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_int32_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 -static grub_err_t lookup_file (grub_fshelp_node_t node, - const char *name, - grub_fshelp_node_t *foundnode, - enum grub_fshelp_filetype *foundtype) +/* 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)) { - grub_err_t err; + 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); err = grub_fat_iterate_init (&ctxt); if (err) - return err; - - while (!(err = grub_fat_iterate_dir_next (node, &ctxt))) { + grub_free (dirname); + return 0; + } + + while (!(err = grub_fat_iterate_dir_next (disk, data, &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) @@ -932,33 +903,32 @@ static grub_err_t lookup_file (grub_fshelp_node_t node, if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) continue; #endif - - if (grub_strcasecmp (name, ctxt.filename) == 0) + if (*dirname == '\0' && call_hook) { - *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); - if (!*foundnode) - return grub_errno; - (*foundnode)->attr = ctxt.dir.attr; + if (hook (ctxt.filename, &info)) + break; + else + continue; + } + + if (grub_strcasecmp (dirname, ctxt.filename) == 0) + { + found = 1; + data->attr = ctxt.dir.attr; #ifdef MODE_EXFAT - (*foundnode)->file_size = ctxt.dir.file_size; - (*foundnode)->file_cluster = ctxt.dir.first_cluster; - (*foundnode)->is_contiguous = ctxt.dir.is_contiguous; + data->file_size = ctxt.dir.file_size; + data->file_cluster = ctxt.dir.first_cluster; #else - (*foundnode)->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); - (*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) + data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); + data->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 - (*foundnode)->cur_cluster_num = ~0U; - (*foundnode)->data = node->data; - (*foundnode)->disk = node->disk; + data->cur_cluster_num = ~0U; - *foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG; + if (call_hook) + hook (ctxt.filename, &info); - grub_fat_iterate_fini (&ctxt); - return GRUB_ERR_NONE; + break; } } @@ -966,19 +936,25 @@ static grub_err_t lookup_file (grub_fshelp_node_t node, if (err == GRUB_ERR_EOF) err = 0; - return err; + if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); + fail: + grub_free (dirname); + + return found ? dirp : 0; } static grub_err_t -grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, - void *hook_data) +grub_fat_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { struct grub_fat_data *data = 0; grub_disk_t disk = device->disk; - grub_fshelp_node_t found = NULL; - grub_err_t err; - struct grub_fat_iterate_context ctxt; + grub_size_t len; + char *dirname = 0; + char *p; grub_dl_ref (my_mod); @@ -986,62 +962,27 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, if (! data) goto fail; - 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 - }; - - err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, NULL, GRUB_FSHELP_DIR); - if (err) + /* 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; - err = grub_fat_iterate_init (&ctxt); - if (err) - goto fail; - - while (!(err = grub_fat_iterate_dir_next (found, &ctxt))) + do { - 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 (info.mtimeset == 0) - grub_error (GRUB_ERR_OUT_OF_RANGE, - "invalid modification timestamp for %s", path); - - if (hook (ctxt.filename, &info, hook_data)) - break; + p = grub_fat_find_dir (disk, data, p, path, hook); } - grub_fat_iterate_fini (&ctxt); - if (err == GRUB_ERR_EOF) - err = 0; + while (p && grub_errno == GRUB_ERR_NONE); fail: - if (found != &root) - grub_free (found); + grub_free (dirname); grub_free (data); grub_dl_unref (my_mod); @@ -1053,43 +994,35 @@ static grub_err_t grub_fat_open (grub_file_t file, const char *name) { struct grub_fat_data *data = 0; - grub_fshelp_node_t found = NULL; - grub_err_t err; - grub_disk_t disk = file->device->disk; + char *p = (char *) name; grub_dl_ref (my_mod); - data = grub_fat_mount (disk); + data = grub_fat_mount (file->device->disk); if (! data) goto fail; - 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 + { + p = grub_fat_find_dir (file->device->disk, data, p, name, 0); + if (grub_errno != GRUB_ERR_NONE) + goto fail; + } + while (p); - err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG); - if (err) - goto fail; + if (data->attr & GRUB_FAT_ATTR_DIRECTORY) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); + goto fail; + } - file->data = found; - file->size = found->file_size; + file->data = data; + file->size = data->file_size; return GRUB_ERR_NONE; fail: - if (found != &root) - grub_free (found); - grub_free (data); grub_dl_unref (my_mod); @@ -1100,18 +1033,14 @@ 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, file->read_hook_data, + return grub_fat_read_data (file->device->disk, file->data, file->read_hook, file->offset, len, buf); } static grub_err_t grub_fat_close (grub_file_t file) { - grub_fshelp_node_t node = file->data; - - grub_free (node->data); - grub_free (node); + grub_free (file->data); grub_dl_unref (my_mod); @@ -1124,29 +1053,20 @@ 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, - }; - root.data = grub_fat_mount (disk); - if (! root.data) + data = grub_fat_mount (disk); + if (! data) return grub_errno; - root.file_cluster = root.data->root_cluster; - *label = NULL; while (1) { offset += sizeof (dir); - if (grub_fat_read_data (disk, &root, 0, 0, + if (grub_fat_read_data (disk, data, 0, offset, sizeof (dir), (char *) &dir) != sizeof (dir)) break; @@ -1166,7 +1086,7 @@ grub_fat_label (grub_device_t device, char **label) * GRUB_MAX_UTF8_PER_UTF16 + 1); if (!*label) { - grub_free (root.data); + grub_free (data); return grub_errno; } chc = dir.type_specific.volume_label.character_count; @@ -1178,7 +1098,7 @@ grub_fat_label (grub_device_t device, char **label) } } - grub_free (root.data); + grub_free (data); return grub_errno; } @@ -1187,32 +1107,30 @@ 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); - root.data = grub_fat_mount (disk); - if (! root.data) + data = grub_fat_mount (disk); + if (! data) goto fail; - root.file_cluster = root.data->root_cluster; + if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + return 0; + } err = grub_fat_iterate_init (&ctxt); if (err) goto fail; - while (!(err = grub_fat_iterate_dir_next (&root, &ctxt))) + while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID) { *label = grub_strdup (ctxt.filename); @@ -1225,7 +1143,7 @@ grub_fat_label (grub_device_t device, char **label) grub_dl_unref (my_mod); - grub_free (root.data); + grub_free (data); return grub_errno; } @@ -1260,29 +1178,6 @@ 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 @@ -1290,12 +1185,12 @@ static struct grub_fs grub_fat_fs = #else .name = "fat", #endif - .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, + .dir = grub_fat_dir, + .open = grub_fat_open, + .read = grub_fat_read, + .close = grub_fat_close, + .label = grub_fat_label, + .uuid = grub_fat_uuid, #ifdef GRUB_UTIL #ifdef MODE_EXFAT /* ExFAT BPB is 30 larger than FAT32 one. */ diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index 4c902adf3..21a72de84 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -27,281 +27,195 @@ GRUB_MOD_LICENSE ("GPLv3+"); -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 +/* 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) { - /* Inputs. */ - const char *path; - grub_fshelp_node_t rootnode; - - /* Global options. */ - int symlinknest; - - /* 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))) - { - grub_free (node); - return 0; - } - - /* The node is found, stop iterating over the nodes. */ - *ctx->foundnode = node; - *ctx->foundtype = filetype; - return 1; -} - -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; -} - -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) + enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR; + int symlinknest = 0; + + auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, + grub_fshelp_node_t currroot, + grub_fshelp_node_t *currfound); + + grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, + grub_fshelp_node_t currroot, + grub_fshelp_node_t *currfound) { - char c; - grub_fshelp_node_t foundnode = NULL; - enum grub_fshelp_filetype foundtype = 0; + 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; + + auto int NESTED_FUNC_ATTR iterate (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node); + + auto void free_node (grub_fshelp_node_t node); + + 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); /* 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] == '.') { - go_up_a_level (ctx); - continue; + *currfound = currnode; + return 0; } - /* 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) + for (;;) { - char *symlink; + int found; - /* 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] == '/') + /* Extract the actual part from the pathname. */ + next = grub_strchr (name, '/'); + if (next) { - err = go_to_root (ctx); - if (err) - return err; - } - else - { - /* Get from symlink to containing directory. */ - go_up_a_level (ctx); + /* Remove all leading slashes. */ + while (*next == '/') + *(next++) = '\0'; } + /* 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")); + } - /* Lookup the node the symlink points to. */ - find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx); - grub_free (symlink); + /* Iterate over the directory. */ + found = iterate_dir (currnode, iterate); + if (! found) + { + free_node (currnode); + currnode = 0; + if (grub_errno) + return grub_errno; - if (grub_errno) - return grub_errno; + 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; } + + 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] != '/') { - return grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); + return grub_errno; } - err = go_to_root (&ctx); + err = find_file (path, rootnode, foundnode); 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")); @@ -311,48 +225,16 @@ grub_fshelp_find_file_real (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. 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 + 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 blocks have a size of LOG2BLOCKSIZE (in log2). */ grub_ssize_t grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, - grub_disk_read_hook_t read_hook, void *read_hook_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_addr_t (*get_block) (grub_fshelp_node_t node, grub_disk_addr_t block), @@ -362,13 +244,6 @@ 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); - 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; @@ -411,7 +286,6 @@ 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); @@ -427,3 +301,24 @@ 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 3fe842b4d..0a249ccb8 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -29,7 +29,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -66,7 +65,7 @@ struct grub_hfs_node grub_uint8_t level; grub_uint16_t reccnt; grub_uint16_t unused; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The head of the B*-Tree. */ struct grub_hfs_treeheader @@ -82,7 +81,7 @@ struct grub_hfs_treeheader grub_uint32_t nodes; grub_uint32_t free_nodes; grub_uint8_t unused[76]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The state of a mounted HFS filesystem. */ struct grub_hfs_data @@ -113,7 +112,7 @@ struct grub_hfs_catalog_key /* Filename. */ grub_uint8_t str[31]; -} GRUB_PACKED; +} __attribute__ ((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 @@ -126,7 +125,7 @@ struct grub_hfs_extent_key grub_uint8_t forktype; grub_uint32_t fileid; grub_uint16_t first_block; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A directory record. This is used to find out the directory ID. */ struct grub_hfs_dirrec @@ -137,7 +136,7 @@ struct grub_hfs_dirrec grub_uint32_t dirid; grub_uint32_t ctime; grub_uint32_t mtime; -} GRUB_PACKED; +} __attribute__ ((packed)); /* Information about a file. */ struct grub_hfs_filerec @@ -155,22 +154,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; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A record descriptor, both key and data, used to pass to call back functions. */ struct grub_hfs_record { void *key; - grub_size_t keylen; + int keylen; void *data; - grub_size_t datalen; + int datalen; }; static grub_dl_t my_mod; static int grub_hfs_find_node (struct grub_hfs_data *, char *, - grub_uint32_t, int, char *, grub_size_t); + grub_uint32_t, int, char *, int); /* 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, @@ -244,17 +243,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, - grub_disk_read_hook_t read_hook, void *read_hook_data, - grub_uint32_t pos, grub_size_t len, char *buf) + 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_off_t i; grub_off_t blockcnt; - /* 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; + blockcnt = grub_divmod64 (((len + pos) + + data->blksz - 1), data->blksz, 0); - for (i = pos / data->blksz; i < blockcnt; i++) + for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++) { grub_disk_addr_t blknr; grub_off_t blockoff; @@ -262,7 +261,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, int skipfirst = 0; - blockoff = pos % data->blksz; + grub_divmod64 (pos, data->blksz, &blockoff); blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) @@ -271,7 +270,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, /* Last block. */ if (i == blockcnt - 1) { - blockend = (len + pos) % data->blksz; + grub_divmod64 ((len + pos), data->blksz, &blockend); /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) @@ -279,7 +278,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, } /* First block. */ - if (i == pos / data->blksz) + if (i == grub_divmod64 (pos, data->blksz, 0)) { skipfirst = blockoff; blockend -= skipfirst; @@ -290,7 +289,6 @@ 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; @@ -331,7 +329,6 @@ 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"); @@ -369,14 +366,9 @@ 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_compile_time (1); + key.parent_dir = grub_cpu_to_be32 (1); key.strlen = data->sblock.volname[0]; grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1)); @@ -404,8 +396,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 (const struct grub_hfs_catalog_key *k1, - const struct grub_hfs_catalog_key *k2) +grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1, + 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] = { @@ -648,8 +640,8 @@ grub_hfs_cmp_catkeys (const struct grub_hfs_catalog_key *k1, /* Compare the K1 and K2 extent overflow file keys. */ static int -grub_hfs_cmp_extkeys (const struct grub_hfs_extent_key *k1, - const struct grub_hfs_extent_key *k2) +grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1, + struct grub_hfs_extent_key *k2) { int cmp = k1->forktype - k2->forktype; if (cmp == 0) @@ -668,32 +660,22 @@ grub_hfs_cmp_extkeys (const 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 *, - void *hook_arg), - void *hook_arg) + struct grub_hfs_record *)) { - grub_size_t nodesize = type == 0 ? data->cat_size : data->ext_size; + int nodesize = type == 0 ? data->cat_size : data->ext_size; - union node_union + union { struct grub_hfs_node 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; + char rawnode[nodesize]; + grub_uint16_t offsets[nodesize / 2]; + } node; 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) @@ -704,101 +686,40 @@ 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_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); + if (grub_disk_read (data->disk, blk, 0, + sizeof (node), &node)) + return grub_errno; /* Iterate over all records in this node. */ - for (i = 0; i < reccnt; i++) + for (i = 0; i < grub_be_to_cpu16 (node.node.reccnt); i++) { int pos = (nodesize >> 1) - 1 - i; struct pointer { grub_uint8_t keylen; grub_uint8_t key; - } 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; + } __attribute__ ((packed)) *pnt; + pnt = (struct pointer *) (grub_be_to_cpu16 (node.offsets[pos]) + + node.rawnode); struct grub_hfs_record rec = { &pnt->key, pnt->keylen, &pnt->key + pnt->keylen +(pnt->keylen + 1) % 2, - nodesize - off - pnt->keylen - 1 + nodesize - grub_be_to_cpu16 (node.offsets[pos]) + - pnt->keylen - 1 }; - if (node_hook (&node->node, &rec, hook_arg)) - { - grub_free (node); - return 0; - } + if (node_hook (&node.node, &rec)) + 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; } @@ -810,84 +731,64 @@ grub_hfs_find_node_node_found (struct grub_hfs_node *hnd, struct grub_hfs_record 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, grub_size_t datalen) + grub_uint32_t idx, int type, char *datar, int datalen) { - struct grub_hfs_find_node_node_found_ctx ctx = + 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) { - .found = -1, - .isleaf = 0, - .done = 0, - .type = type, - .key = key, - .datar = datar, - .datalen = datalen - }; + 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; + } do { - ctx.found = -1; + found = -1; - if (grub_hfs_iterate_records (data, type, idx, 0, grub_hfs_find_node_node_found, &ctx)) + if (grub_hfs_iterate_records (data, type, idx, 0, node_found)) return 0; - if (ctx.found == -1) + if (found == -1) return 0; - idx = ctx.found; - } while (! ctx.isleaf); + idx = found; + } while (! isleaf); - 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); + return done; } @@ -896,35 +797,70 @@ grub_hfs_iterate_dir_it_dir (struct grub_hfs_node *hnd __attribute ((unused)), call HOOK. */ static grub_err_t grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, - grub_uint32_t dir, int (*hook) (struct grub_hfs_record *, void *hook_arg), - void *hook_arg) + unsigned int dir, int (*hook) (struct grub_hfs_record *)) { - 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 - }; + 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); + } do { - ctx.found = -1; + found = -1; - if (grub_hfs_iterate_records (data, 0, root_idx, 0, grub_hfs_iterate_dir_node_found, &ctx)) + if (grub_hfs_iterate_records (data, 0, root_idx, 0, node_found)) return grub_errno; - if (ctx.found == -1) + if (found == -1) return 0; - root_idx = ctx.found; - } while (! ctx.isleaf); + root_idx = found; + } while (! 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, ctx.next, 1, grub_hfs_iterate_dir_it_dir, &ctx); + grub_hfs_iterate_records (data, 0, next, 1, it_dir); return grub_errno; } @@ -1126,146 +1062,144 @@ 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, - grub_fshelp_node_t *found, - enum grub_fshelp_filetype exptype) + struct grub_hfs_filerec *retdata, int *retinode) { - struct grub_fshelp_node root = { - .data = data, - .inode = data->rootdir, - .fdrec = { - .frec = { - .type = GRUB_HFS_FILETYPE_DIR - } - } - }; - grub_err_t err; + int inode = data->rootdir; + char *next; + char *origpath; + union { + struct grub_hfs_filerec frec; + struct grub_hfs_dirrec dir; + } fdrec; - err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype); + fdrec.frec.type = GRUB_HFS_FILETYPE_DIR; - if (&root == *found) + if (path[0] != '/') { - *found = grub_malloc (sizeof (root)); - if (!*found) - return grub_errno; - grub_memcpy (*found, &root, sizeof (root)); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); + return 0; } - return err; + + origpath = grub_strdup (path); + if (!origpath) + return grub_errno; + + path = origpath; + while (*path == '/') + path++; + + while (path && grub_strlen (path)) + { + 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; + } + + if (retdata) + grub_memcpy (retdata, &fdrec.frec, sizeof (fdrec.frec)); + + if (retinode) + *retinode = inode; + + fail: + grub_free (origpath); + return grub_errno; } -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, grub_fs_dir_hook_t hook, - void *hook_data) +grub_hfs_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - struct grub_hfs_data *data; - struct grub_hfs_dir_hook_ctx ctx = + int inode; + + auto int dir_hook (struct grub_hfs_record *rec); + + int dir_hook (struct grub_hfs_record *rec) { - .hook = hook, - .hook_data = hook_data - }; - grub_fshelp_node_t found = NULL; - + 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; + grub_dl_ref (my_mod); data = grub_hfs_mount (device->disk); @@ -1273,13 +1207,18 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, goto fail; /* First the directory ID for the directory. */ - if (grub_hfs_find_dir (data, path, &found, GRUB_FSHELP_DIR)) + if (grub_hfs_find_dir (data, path, &frec, &inode)) goto fail; - grub_hfs_iterate_dir (data, data->cat_root, found->inode, grub_hfs_dir_hook, &ctx); + 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); fail: - grub_free (found); grub_free (data); grub_dl_unref (my_mod); @@ -1293,36 +1232,35 @@ static grub_err_t grub_hfs_open (struct grub_file *file, const char *name) { struct grub_hfs_data *data; - grub_fshelp_node_t found = NULL; - + struct grub_hfs_filerec frec; + grub_dl_ref (my_mod); data = grub_hfs_mount (file->device->disk); - if (!data) - { - grub_dl_unref (my_mod); - return grub_errno; - } - - if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG)) + if (grub_hfs_find_dir (data, name, &frec, 0)) { grub_free (data); - grub_free (found); grub_dl_unref (my_mod); return grub_errno; } - 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); + if (frec.type != GRUB_HFS_FILETYPE_FILE) + { + grub_free (data); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); + 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); file->offset = 0; file->data = data; - grub_free (found); - return 0; } @@ -1332,8 +1270,7 @@ 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->read_hook_data, - file->offset, len, buf); + return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf); } @@ -1360,7 +1297,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_calloc (MAX_UTF8_PER_MAC_ROMAN + 1, len); + *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1); if (*label) macroman_to_utf8 (*label, data->sblock.volname + 1, len + 1, 0); @@ -1417,13 +1354,13 @@ grub_hfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_hfs_fs = { .name = "hfs", - .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, + .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, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 9c4e4c88c..981246475 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -19,7 +19,6 @@ /* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ -#define grub_fshelp_node grub_hfsplus_file #include #include #include @@ -30,11 +29,50 @@ #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 { @@ -44,6 +82,16 @@ 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 { @@ -61,7 +109,36 @@ struct grub_hfsplus_btheader grub_uint8_t btree_type; grub_uint8_t key_compare; grub_uint32_t attributes; -} GRUB_PACKED; +} __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)); struct grub_hfsplus_catfile { @@ -76,7 +153,7 @@ struct grub_hfsplus_catfile grub_uint8_t unused3[44]; struct grub_hfsplus_forkdata data; struct grub_hfsplus_forkdata resource; -} GRUB_PACKED; +} __attribute__ ((packed)); /* Filetype information as used in inodes. */ #define GRUB_HFSPLUS_FILEMODE_MASK 0170000 @@ -85,13 +162,9 @@ struct grub_hfsplus_catfile #define GRUB_HFSPLUS_FILEMODE_SYMLINK 0120000 /* Some pre-defined file IDs. */ -enum - { - GRUB_HFSPLUS_FILEID_ROOTDIR = 2, - GRUB_HFSPLUS_FILEID_OVERFLOW = 3, - GRUB_HFSPLUS_FILEID_CATALOG = 4, - GRUB_HFSPLUS_FILEID_ATTR = 8 - }; +#define GRUB_HFSPLUS_FILEID_ROOTDIR 2 +#define GRUB_HFSPLUS_FILEID_OVERFLOW 3 +#define GRUB_HFSPLUS_FILEID_CATALOG 4 enum grub_hfsplus_filetype { @@ -104,15 +177,98 @@ enum grub_hfsplus_filetype #define GRUB_HFSPLUSX_BINARYCOMPARE 0xBC #define GRUB_HFSPLUSX_CASEFOLDING 0xCF -static grub_dl_t my_mod; +/* 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; + }; +}; -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); +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]; +} + /* 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 @@ -136,6 +292,14 @@ 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); @@ -146,8 +310,7 @@ 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->compressed - ? &node->resource_extents[0] : &node->extents[0]; + struct grub_hfsplus_extent *extents = &node->extents[0]; while (1) { @@ -181,11 +344,10 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) 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) - || !nnode) + grub_hfsplus_cmp_extkey, &nnode, &ptr)) { grub_error (GRUB_ERR_READ_ERROR, "no block found for the file id 0x%x and the block offset 0x%x", @@ -211,13 +373,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. */ -grub_ssize_t +static grub_ssize_t grub_hfsplus_read_file (grub_fshelp_node_t node, - grub_disk_read_hook_t read_hook, void *read_hook_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) { - return grub_fshelp_read_file (node->data->disk, node, - read_hook, read_hook_data, + return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_hfsplus_read_block, node->size, node->data->log2blksize - GRUB_DISK_SECTOR_BITS, @@ -298,27 +460,15 @@ 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); @@ -327,7 +477,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, 0, + if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) goto fail; @@ -337,40 +487,20 @@ grub_hfsplus_mount (grub_disk_t disk) data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) && (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE)); - if (data->catalog_tree.nodesize < 2) - goto fail; - - if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 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, 0, + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 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) - goto fail; - - 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; @@ -456,12 +586,6 @@ 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) @@ -476,16 +600,12 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node) { char *symlink; grub_ssize_t numread; - grub_size_t sz = node->size; - if (grub_add (sz, 1, &sz)) - return NULL; - - symlink = grub_malloc (sz); + symlink = grub_malloc (node->size + 1); if (!symlink) return 0; - numread = grub_hfsplus_read_file (node, 0, 0, 0, node->size, symlink); + numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink); if (numread != (grub_ssize_t) node->size) { grub_free (symlink); @@ -500,8 +620,7 @@ 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, void *hook_arg), - void *hook_arg) + int (*hook) (void *record)) { grub_disk_addr_t rec; grub_uint64_t saved_node = -1; @@ -514,7 +633,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), hook_arg)) + if (hook (grub_hfsplus_btree_recptr (btree, first_node, rec))) return 1; } @@ -530,7 +649,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, 0, + if (grub_hfsplus_read_file (&btree->file, 0, (((grub_disk_addr_t) grub_be_to_cpu32 (first_node->next)) * btree->nodesize), @@ -548,7 +667,7 @@ 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. */ -grub_err_t +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, @@ -563,12 +682,6 @@ 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; - } - node = grub_malloc (btree->nodesize); if (! node) return grub_errno; @@ -589,7 +702,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, node_count++; /* Read a node. */ - if (grub_hfsplus_read_file (&btree->file, 0, 0, + if (grub_hfsplus_read_file (&btree->file, 0, (grub_disk_addr_t) currnode * (grub_disk_addr_t) btree->nodesize, btree->nodesize, (char *) node) <= 0) @@ -646,162 +759,135 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, { *matchnode = 0; grub_free (node); - return 0; + return 1; } } } -struct list_nodes_ctx -{ - int ret; - grub_fshelp_node_t dir; - grub_fshelp_iterate_dir_hook_t hook; - void *hook_data; -}; - -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; - - 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; - - /* 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 (ctx->dir->fileid == 2) - return 0; - node = grub_malloc (sizeof (*node)); - if (!node) - return 1; - node->data = ctx->dir->data; - node->mtime = 0; - node->size = 0; - node->fileid = grub_be_to_cpu32 (fileinfo->parentid); - - 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) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { - struct list_nodes_ctx ctx = - { - .ret = 0, - .dir = dir, - .hook = hook, - .hook_data = hook_data - }; + int ret = 0; + + auto int list_nodes (void *record); + int list_nodes (void *record) + { + 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; + + 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)); + + /* 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); + + 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) + 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; + + 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; + } struct grub_hfsplus_key_internal intern; - struct grub_hfsplus_btnode *node = NULL; - grub_disk_addr_t ptr = 0; + struct grub_hfsplus_btnode *node; + grub_disk_addr_t ptr; { struct grub_fshelp_node *fsnode; @@ -809,7 +895,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, if (!fsnode) return 1; *fsnode = *dir; - if (hook (".", GRUB_FSHELP_DIR, fsnode, hook_data)) + if (hook (".", GRUB_FSHELP_DIR, fsnode)) return 1; } @@ -820,17 +906,16 @@ 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) - || !node) + grub_hfsplus_cmp_catkey, &node, &ptr)) return 0; /* Iterate over all entries in this directory. */ grub_hfsplus_btree_iterate_node (&dir->data->catalog_tree, node, ptr, - list_nodes, &ctx); + list_nodes); grub_free (node); - return ctx.ret; + return ret; } /* Open a file named NAME and initialize FILE. */ @@ -852,14 +937,6 @@ 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); @@ -883,13 +960,7 @@ grub_hfsplus_open (struct grub_file *file, const char *name) static grub_err_t grub_hfsplus_close (grub_file_t file) { - 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_free (file->data); grub_dl_unref (my_mod); @@ -903,52 +974,36 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hfsplus_data *data = (struct grub_hfsplus_data *) file->data; - 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); + return grub_hfsplus_read_file (&data->opened_file, file->read_hook, + file->offset, len, buf); } static grub_err_t grub_hfsplus_dir (grub_device_t device, const char *path, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -963,7 +1018,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, grub_hfsplus_dir_iter, &ctx); + grub_hfsplus_iterate_dir (fdiro, iterate); fail: if (data && fdiro != &data->dirroot) @@ -983,10 +1038,9 @@ 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 = NULL; - grub_disk_addr_t ptr = 0; + struct grub_hfsplus_btnode *node; + grub_disk_addr_t ptr; *label = 0; @@ -1001,8 +1055,7 @@ 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) - || !node) + grub_hfsplus_cmp_catkey_id, &node, &ptr)) { grub_free (data); return 0; @@ -1012,41 +1065,22 @@ 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); - label_name = grub_calloc (label_len, sizeof (*label_name)); - if (!label_name) - { - grub_free (node); - grub_free (data); - return grub_errno; - } - for (i = 0; i < label_len; i++) { - label_name[i] = grub_be_to_cpu16 (catkey->name[i]); + catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); /* 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; - } + if (catkey->name[i] == 0) + return 0; } - *label = grub_calloc (label_len, GRUB_MAX_UTF8_PER_UTF16 + 1); + *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! *label) - { - grub_free (label_name); - grub_free (node); - grub_free (data); - return grub_errno; - } + return grub_errno; - *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), label_name, + *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, label_len) = '\0'; - grub_free (label_name); grub_free (node); grub_free (data); @@ -1106,13 +1140,13 @@ grub_hfsplus_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_hfsplus_fs = { .name = "hfsplus", - .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, + .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, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c deleted file mode 100644 index d76f3f137..000000000 --- a/grub-core/fs/hfspluscomp.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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, 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, 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_malloc (node->compress_index_size - * sizeof (node->compress_index[0])); - if (!node->compress_index) - { - node->compressed = 0; - grub_free (attr_node); - return grub_errno; - } - 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 5ec4433b8..cd4acc8ec 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -28,7 +28,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -55,7 +54,7 @@ struct grub_iso9660_voldesc grub_uint8_t type; grub_uint8_t magic[5]; grub_uint8_t version; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_iso9660_date2 { @@ -66,7 +65,7 @@ struct grub_iso9660_date2 grub_uint8_t minute; grub_uint8_t second; grub_uint8_t offset; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A directory entry. */ struct grub_iso9660_dir @@ -80,9 +79,8 @@ 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; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_iso9660_date { @@ -94,7 +92,7 @@ struct grub_iso9660_date grub_uint8_t second[2]; grub_uint8_t hundredth[2]; grub_uint8_t offset; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The primary volume descriptor. Only little endian is used. */ struct grub_iso9660_primary_voldesc @@ -113,7 +111,7 @@ struct grub_iso9660_primary_voldesc grub_uint8_t unused6[624]; struct grub_iso9660_date created; struct grub_iso9660_date modified; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A single entry in the path table. */ struct grub_iso9660_path @@ -123,7 +121,7 @@ struct grub_iso9660_path grub_uint32_t first_sector; grub_uint16_t parentdir; grub_uint8_t name[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* An entry in the System Usage area of the directory entry. */ struct grub_iso9660_susp_entry @@ -132,7 +130,7 @@ struct grub_iso9660_susp_entry grub_uint8_t len; grub_uint8_t version; grub_uint8_t data[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The CE entry. This is used to describe the next block where data can be found. */ @@ -145,7 +143,7 @@ struct grub_iso9660_susp_ce grub_uint32_t off_be; grub_uint32_t len; grub_uint32_t len_be; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_iso9660_data { @@ -262,26 +260,42 @@ 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, void *hook_arg), - void *hook_arg) + (struct grub_iso9660_susp_entry *entry)) { char *sua; struct grub_iso9660_susp_entry *entry; - grub_err_t err; + 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; - sua = grub_malloc (sua_size); - if (!sua) + if (load_sua ()) return grub_errno; - /* Load a part of the System Usage Area. */ - err = read_node (node, off, sua_size, sua); - if (err) - return err; - - for (entry = (struct grub_iso9660_susp_entry *) sua; (char *) entry < (char *) sua + sua_size - 1 && entry->len > 0; + for (; (char *) entry < (char *) sua + sua_size - 1; entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len)) { @@ -293,28 +307,19 @@ grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, if (grub_strncmp ((char *) entry->sig, "CE", 2) == 0) { struct grub_iso9660_susp_ce *ce; - grub_disk_addr_t ce_block; + is_ce = 1; ce = (struct grub_iso9660_susp_ce *) entry; sua_size = grub_le_to_cpu32 (ce->len); off = grub_le_to_cpu32 (ce->off); ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; grub_free (sua); - sua = grub_malloc (sua_size); - if (!sua) + if (load_sua ()) return grub_errno; - - /* Load a part of the System Usage Area. */ - err = grub_disk_read (node->data->disk, ce_block, off, - sua_size, sua); - if (err) - return err; - - entry = (struct grub_iso9660_susp_entry *) sua; } - if (hook (entry, hook_arg)) + if (hook (entry)) { grub_free (sua); return 0; @@ -330,11 +335,11 @@ grub_iso9660_convert_string (grub_uint8_t *us, int len) { char *p; int i; - grub_uint16_t t[MAX_NAMELEN / 2 + 1]; + grub_uint16_t t[len]; - p = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1); + p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! p) - return NULL; + return p; 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) { @@ -368,6 +358,20 @@ 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 @@ -419,8 +423,7 @@ set_rockridge (struct grub_iso9660_data *data) /* Iterate over the entries in the SUA area to detect extensions. */ if (grub_iso9660_susp_iterate (&rootnode, - sua_pos, sua_size, susp_iterate_set_rockridge, - data)) + sua_pos, sua_size, susp_iterate)) { grub_free (sua); return grub_errno; @@ -516,187 +519,157 @@ 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) - ctx->filename = (char *) "."; - else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) - 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; - - /* 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 (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, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { 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; - struct iterate_dir_ctx ctx; + 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; + } len = get_node_size (dir); for (; offset < len; offset += dirent.len) { - ctx.symlink = 0; - ctx.was_continue = 0; + symlink = 0; + was_continue = 0; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; @@ -709,7 +682,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, } { - char name[MAX_NAMELEN + 1]; + char name[dirent.namelen + 1]; int nameoffset = offset + sizeof (dirent); struct grub_fshelp_node *node; int sua_off = (sizeof (dirent) + dirent.namelen + 1 @@ -718,13 +691,13 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, sua_off += offset + dir->data->susp_skip; - ctx.filename = 0; - ctx.filename_alloc = 0; - ctx.type = GRUB_FSHELP_UNKNOWN; + filename = 0; + filename_alloc = 0; + type = GRUB_FSHELP_UNKNOWN; if (dir->data->rockridge && grub_iso9660_susp_iterate (dir, sua_off, sua_size, - susp_iterate_dir, &ctx)) + susp_iterate_dir)) return 0; /* Read the name. */ @@ -744,51 +717,55 @@ 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 (ctx.type == GRUB_FSHELP_UNKNOWN) + if (type == GRUB_FSHELP_UNKNOWN) { if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR) - ctx.type = GRUB_FSHELP_DIR; + type = GRUB_FSHELP_DIR; else - ctx.type = GRUB_FSHELP_REG; + type = GRUB_FSHELP_REG; } /* . and .. */ - if (!ctx.filename && dirent.namelen == 1 && name[0] == 0) - ctx.filename = (char *) "."; + if (!filename && dirent.namelen == 1 && name[0] == 0) + filename = (char *) "."; - if (!ctx.filename && dirent.namelen == 1 && name[0] == 1) - ctx.filename = (char *) ".."; + if (!filename && dirent.namelen == 1 && name[0] == 1) + filename = (char *) ".."; /* The filename was not stored in a rock ridge entry. Read it from the iso9660 filesystem. */ - if (!dir->data->joliet && !ctx.filename) + if (!dir->data->joliet && !filename) { char *ptr; name[dirent.namelen] = '\0'; - ctx.filename = grub_strrchr (name, ';'); - if (ctx.filename) - *ctx.filename = '\0'; + filename = grub_strrchr (name, ';'); + if (filename) + *filename = '\0'; /* ISO9660 names are not case-preserving. */ - ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE; + type |= GRUB_FSHELP_CASE_INSENSITIVE; for (ptr = name; *ptr; ptr++) *ptr = grub_tolower (*ptr); if (ptr != name && *(ptr - 1) == '.') *(ptr - 1) = 0; - ctx.filename = name; + filename = name; } - if (dir->data->joliet && !ctx.filename) + if (dir->data->joliet && !filename) { - char *semicolon; + char *oldname, *semicolon; - ctx.filename = grub_iso9660_convert_string - ((grub_uint8_t *) name, dirent.namelen >> 1); + oldname = name; + filename = grub_iso9660_convert_string + ((grub_uint8_t *) oldname, dirent.namelen >> 1); - semicolon = grub_strrchr (ctx.filename, ';'); + semicolon = grub_strrchr (filename, ';'); if (semicolon) *semicolon = '\0'; - ctx.filename_alloc = 1; + if (filename_alloc) + grub_free (oldname); + + filename_alloc = 1; } node->dirents[0] = dirent; @@ -797,28 +774,24 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, offset += dirent.len; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) { - if (ctx.filename_alloc) - grub_free (ctx.filename); + if (filename_alloc) + grub_free (filename); grub_free (node); return 0; } if (node->have_dirents >= node->alloc_dirents) { struct grub_fshelp_node *new_node; - 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); + 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]))); if (!new_node) { - fail_0: - if (ctx.filename_alloc) - grub_free (ctx.filename); + if (filename_alloc) + grub_free (filename); grub_free (node); return 0; } @@ -826,26 +799,22 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, } node->dirents[node->have_dirents++] = dirent; } - if (ctx.symlink) + if (symlink) { if ((node->alloc_dirents - node->have_dirents) - * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) + * sizeof (node->dirents[0]) < grub_strlen (symlink) + 1) { struct grub_fshelp_node *new_node; - 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); + 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); if (!new_node) { - fail_1: - if (ctx.filename_alloc) - grub_free (ctx.filename); + if (filename_alloc) + grub_free (filename); grub_free (node); return 0; } @@ -854,19 +823,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), ctx.symlink); - grub_free (ctx.symlink); - ctx.symlink = 0; - ctx.was_continue = 0; + - sizeof (node->dirents), symlink); + grub_free (symlink); + symlink = 0; + was_continue = 0; } - if (hook (ctx.filename, ctx.type, node, hook_data)) + if (hook (filename, type, node)) { - if (ctx.filename_alloc) - grub_free (ctx.filename); + if (filename_alloc) + grub_free (filename); return 1; } - if (ctx.filename_alloc) - grub_free (ctx.filename); + if (filename_alloc) + grub_free (filename); } } @@ -875,39 +844,32 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -929,7 +891,7 @@ grub_iso9660_dir (grub_device_t device, const char *path, goto fail; /* List the files in the directory. */ - grub_iso9660_iterate_dir (foundnode, grub_iso9660_dir_iter, &ctx); + grub_iso9660_iterate_dir (foundnode, iterate); if (foundnode != &rootnode) grub_free (foundnode); @@ -992,15 +954,13 @@ 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; - data->disk->read_hook_data = file->read_hook_data; - err = read_node (data->node, file->offset, len, buf); + read_node (data->node, file->offset, len, buf); data->disk->read_hook = NULL; - if (err || grub_errno) + if (grub_errno) return -1; return len; @@ -1136,13 +1096,13 @@ grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) static struct grub_fs grub_iso9660_fs = { .name = "iso9660", - .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, + .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, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index d5a6d6527..b98a5a374 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -70,16 +70,13 @@ struct grub_jfs_extent /* The physical offset of the first block on the disk. */ grub_uint8_t blk1; grub_uint32_t blk2; -} GRUB_PACKED; - -#define GRUB_JFS_IAG_INODES_OFFSET 3072 -#define GRUB_JFS_IAG_INODES_COUNT 128 +} __attribute__ ((packed)); struct grub_jfs_iag { - grub_uint8_t unused[GRUB_JFS_IAG_INODES_OFFSET]; - struct grub_jfs_extent inodes[GRUB_JFS_IAG_INODES_COUNT]; -} GRUB_PACKED; + grub_uint8_t unused[3072]; + struct grub_jfs_extent inodes[128]; +} __attribute__ ((packed)); /* The head of the tree used to find extents. */ @@ -94,7 +91,7 @@ struct grub_jfs_treehead grub_uint16_t count; grub_uint16_t max; grub_uint8_t unused2[10]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A node in the extent tree. */ struct grub_jfs_tree_extent @@ -107,7 +104,7 @@ struct grub_jfs_tree_extent grub_uint32_t offset2; struct grub_jfs_extent extent; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The tree of directory entries. */ struct grub_jfs_tree_dir @@ -128,7 +125,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]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* An internal node in the dirents tree. */ struct grub_jfs_internal_dirent @@ -137,7 +134,7 @@ struct grub_jfs_internal_dirent grub_uint8_t next; grub_uint8_t len; grub_uint16_t namepart[11]; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A leaf node in the dirents tree. */ struct grub_jfs_leaf_dirent @@ -150,7 +147,7 @@ struct grub_jfs_leaf_dirent grub_uint8_t len; grub_uint16_t namepart[11]; grub_uint32_t index; -} GRUB_PACKED; +} __attribute__ ((packed)); /* A leaf in the dirents tree. This one is used if the previously dirent was not big enough to store the name. */ @@ -159,13 +156,13 @@ struct grub_jfs_leaf_next_dirent grub_uint8_t next; grub_uint8_t len; grub_uint16_t namepart[15]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_jfs_time { grub_int32_t sec; grub_int32_t nanosec; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_jfs_inode { @@ -185,7 +182,7 @@ struct grub_jfs_inode union { /* The tree describing the extents of the file. */ - struct GRUB_PACKED + struct __attribute__ ((packed)) { struct grub_jfs_treehead tree; struct grub_jfs_tree_extent extents[16]; @@ -206,15 +203,15 @@ struct grub_jfs_inode grub_uint8_t sorted[8]; } header; struct grub_jfs_leaf_dirent dirents[8]; - } GRUB_PACKED dir; + } dir __attribute__ ((packed)); /* Fast symlink. */ struct { grub_uint8_t unused[32]; grub_uint8_t path[256]; } symlink; - } GRUB_PACKED; -} GRUB_PACKED; + } __attribute__ ((packed)); +} __attribute__ ((packed)); struct grub_jfs_data { @@ -226,7 +223,7 @@ struct grub_jfs_data int pos; int linknest; int namecomponentlen; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_jfs_diropen { @@ -237,7 +234,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]; - } GRUB_PACKED *dirpage; + } *dirpage __attribute__ ((packed)); struct grub_jfs_data *data; struct grub_jfs_inode *inode; int count; @@ -251,72 +248,67 @@ struct grub_jfs_diropen */ char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1]; grub_uint32_t ino; -} GRUB_PACKED; +} __attribute__ ((packed)); static grub_dl_t my_mod; static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino); -static grub_int64_t -getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents, - struct grub_jfs_data *data, - grub_uint64_t blk) -{ - 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) - { - grub_int64_t ret = -1; - struct - { - struct grub_jfs_treehead treehead; - struct grub_jfs_tree_extent extents[254]; - } *tree; - - tree = grub_zalloc (sizeof (*tree)); - if (!tree) - return -1; - - 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)) - ret = getblk (&tree->treehead, &tree->extents[0], data, blk); - grub_free (tree); - return ret; - } - - return -1; -} - /* Get the block number for the block BLK in the node INODE in the mounted filesystem DATA. */ static grub_int64_t grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, grub_uint64_t blk) { - return getblk (&inode->file.tree, &inode->file.extents[0], data, 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]); } @@ -324,7 +316,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_extent iag_inodes[GRUB_JFS_IAG_INODES_COUNT]; + struct grub_jfs_iag iag; grub_uint32_t iagnum = ino / 4096; unsigned inoext = (ino % 4096) / 32; unsigned inonum = (ino % 4096) % 32; @@ -338,12 +330,11 @@ 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), - GRUB_JFS_IAG_INODES_OFFSET, - sizeof (iag_inodes), &iag_inodes)) + - GRUB_DISK_SECTOR_BITS), 0, + sizeof (struct grub_jfs_iag), &iag)) return grub_errno; - inoblk = grub_le_to_cpu32 (iag_inodes[inoext].blk2); + inoblk = grub_le_to_cpu32 (iag.inodes[inoext].blk2); inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS); inoblk += inonum; @@ -498,17 +489,6 @@ 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 @@ -521,6 +501,15 @@ 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) { @@ -558,10 +547,8 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) return grub_jfs_getent (diro); } - 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; + addstr (leaf->namepart, len < diro->data->namecomponentlen ? len + : diro->data->namecomponentlen); diro->ino = grub_le_to_cpu32 (leaf->inode); len -= diro->data->namecomponentlen; @@ -571,8 +558,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) do { next_leaf = &diro->next_leaf[nextent]; - le_to_cpu16_copy (filename + strpos, next_leaf->namepart, len < 15 ? len : 15); - strpos += len < 15 ? len : 15; + addstr (next_leaf->namepart, len < 15 ? len : 15 ); len -= 15; nextent = next_leaf->next; @@ -586,15 +572,13 @@ 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, - grub_disk_read_hook_t read_hook, void *read_hook_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_off_t i; @@ -632,7 +616,6 @@ 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), @@ -655,74 +638,136 @@ static grub_err_t grub_jfs_find_file (struct grub_jfs_data *data, const char *path, grub_uint32_t start_ino) { - const char *name; - const char *next = path; - struct grub_jfs_diropen *diro = NULL; + char fpath[grub_strlen (path)]; + char *name = fpath; + char *next; + struct grub_jfs_diropen *diro; + + grub_strncpy (fpath, path, grub_strlen (path) + 1); if (grub_jfs_read_inode (data, start_ino, &data->currinode)) return grub_errno; - while (1) + /* 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 (;;) { - name = next; - while (*name == '/') - name++; if (name[0] == 0) return GRUB_ERR_NONE; - for (next = name; *next && *next != '/'; next++); - if (name[0] == '.' && name + 1 == next) - continue; + if (name[0] == '.' && name[1] == 0) + { + if (!next) + return 0; - if (name[0] == '.' && name[1] == '.' && name + 2 == next) + name = next; + next = grub_strchr (name, '/'); + while (next && *next == '/') + { + next[0] = '\0'; + next++; + } + continue; + } + + if (name[0] == '.' && name[1] == '.' && name[2] == 0) { 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; } - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) - return grub_errno; + if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE) + break; - for (;;) + /* 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) { - if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE) + 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) { - grub_jfs_closedir (diro); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + grub_jfs_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; } - /* 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]) + if (!next) + return 0; + + name = next; + next = grub_strchr (name, '/'); + while (next && *next == '/') { - 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) - { - grub_jfs_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; - } - - break; + next[0] = '\0'; + next++; } + + /* 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; } @@ -730,21 +775,15 @@ 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; + char symlink[size + 1]; if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); - 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; - } + grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size); + else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0) + return grub_errno; symlink[size] = '\0'; @@ -754,15 +793,14 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { struct grub_jfs_data *data = 0; struct grub_jfs_diropen *diro = 0; @@ -794,7 +832,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, hook_data)) + if (hook (diro->name, &info)) goto fail; } @@ -857,8 +895,7 @@ 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->read_hook_data, - file->offset, len, buf); + return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf); } @@ -937,12 +974,12 @@ grub_jfs_label (grub_device_t device, char **label) static struct grub_fs grub_jfs_fs = { .name = "jfs", - .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, + .dir = grub_jfs_dir, + .open = grub_jfs_open, + .read = grub_jfs_read, + .close = grub_jfs_close, + .label = grub_jfs_label, + .uuid = grub_jfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index d0d08363c..1e1c13b56 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -65,6 +65,7 @@ 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 @@ -82,6 +83,19 @@ 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 @@ -147,18 +161,11 @@ 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; @@ -171,41 +178,27 @@ 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) @@ -213,33 +206,33 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) /* Indirect block. */ blk -= GRUB_MINIX_INODE_DIR_BLOCKS; - if (blk < data->block_per_zone) + if (blk < block_per_zone) { - indir = grub_get_indir (data, GRUB_MINIX_INODE_INDIR_ZONE (data), blk); + indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); return indir; } /* Double indirect block. */ - blk -= data->block_per_zone; - if (blk < (grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone) + blk -= block_per_zone; + if (blk < block_per_zone * block_per_zone) { - indir = grub_get_indir (data, GRUB_MINIX_INODE_DINDIR_ZONE (data), - blk / data->block_per_zone); + indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data), + blk / block_per_zone); - indir = grub_get_indir (data, indir, blk % data->block_per_zone); + indir = grub_get_indir (indir, blk % block_per_zone); return indir; } #if defined (MODE_MINIX3) || defined (MODE_MINIX2) - 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)) + 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)) { - 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); + 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); return indir; } @@ -256,7 +249,8 @@ 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, - grub_disk_read_hook_t read_hook, void *read_hook_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_uint32_t i; @@ -264,22 +258,15 @@ 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 - 1) - >> GRUB_DISK_SECTOR_BITS)) / data->block_size + 1; + blockcnt = ((grub_uint32_t) ((len + pos + + (data->block_size << GRUB_DISK_SECTOR_BITS) + - 1) + >> GRUB_DISK_SECTOR_BITS)) / data->block_size; posblock = (((grub_uint32_t) pos) / (data->block_size << GRUB_DISK_SECTOR_BITS)); blockoff = (((grub_uint32_t) pos) @@ -287,7 +274,7 @@ grub_minix_read_file (struct grub_minix_data *data, for (i = posblock; i < blockcnt; i++) { - grub_minix_uintn_t blknr; + grub_disk_addr_t blknr; grub_uint64_t blockend = data->block_size << GRUB_DISK_SECTOR_BITS; grub_off_t skipfirst = 0; @@ -314,9 +301,8 @@ 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(data, blknr), + GRUB_MINIX_ZONE2SECT(blknr), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) @@ -342,8 +328,7 @@ 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 (data, - 2 + grub_minix_to_cpu16 (sblock->inode_bmap_size) + block = GRUB_MINIX_ZONE2SECT (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 @@ -362,19 +347,16 @@ 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_size_t sz = GRUB_MINIX_INODE_SIZE (data); + char symlink[GRUB_MINIX_INODE_SIZE (data) + 1]; if (++data->linknest > GRUB_MINIX_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; - if (grub_minix_read_file (data, 0, 0, 0, sz, symlink) < 0) + if (grub_minix_read_file (data, 0, 0, + GRUB_MINIX_INODE_SIZE (data), symlink) < 0) return grub_errno; - symlink[sz] = '\0'; + symlink[GRUB_MINIX_INODE_SIZE (data)] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') @@ -395,70 +377,90 @@ 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) { - const char *name; - const char *next = path; + char fpath[grub_strlen (path) + 1]; + char *name = fpath; + char *next; unsigned int pos = 0; grub_minix_ino_t dirino; - while (1) + 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) { - name = next; - /* Skip the first slash. */ - while (*name == '/') - name++; - if (!*name) + next[0] = '\0'; + next++; + while (*next == '/') + next++; + } + + do + { + grub_minix_ino_t ino; + char filename[data->filename_size + 1]; + + if (grub_strlen (name) == 0) return GRUB_ERR_NONE; - if ((GRUB_MINIX_INODE_MODE (data) - & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + 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; - /* Extract the actual part from the pathname. */ - for (next = name; *next && *next != '/'; next++); + filename[data->filename_size] = '\0'; - for (pos = 0; ; ) + /* Check if the current direntry matches the current part of the + pathname. */ + if (!grub_strcmp (name, filename)) { - grub_minix_ino_t ino; - char filename[MAX_MINIX_FILENAME_SIZE + 1]; + dirino = data->ino; + grub_minix_read_inode (data, grub_minix_to_cpu_ino (ino)); - if (pos >= GRUB_MINIX_INODE_SIZE (data)) + /* Follow the symlink. */ + if ((GRUB_MINIX_INODE_MODE (data) + & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - return grub_errno; + grub_minix_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; } - 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; + if (!next) + return 0; - pos += sizeof (ino) + data->filename_size; + pos = 0; - 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') + name = next; + next = grub_strchr (name, '/'); + if (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; + next[0] = '\0'; + next++; + while (*next == '/') + next++; } + + 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; } @@ -518,12 +520,6 @@ 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: @@ -540,7 +536,8 @@ grub_minix_mount (grub_disk_t disk) static grub_err_t grub_minix_dir (grub_device_t device, const char *path, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { struct grub_minix_data *data = 0; unsigned int pos = 0; @@ -566,17 +563,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[MAX_MINIX_FILENAME_SIZE + 1]; + char filename[data->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, 0, pos, sizeof (ino), + if (grub_minix_read_file (data, 0, pos, sizeof (ino), (char *) &ino) < 0) return grub_errno; - if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino), + if (grub_minix_read_file (data, 0, pos + sizeof (ino), data->filename_size, (char *) filename) < 0) return grub_errno; @@ -593,7 +590,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, hook_data) ? 1 : 0) + if (hook (filename, &info) ? 1 : 0) break; /* Load the old inode back in. */ @@ -653,8 +650,7 @@ 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->read_hook_data, - file->offset, len, buf); + return grub_minix_read_file (data, file->read_hook, file->offset, len, buf); } @@ -687,10 +683,10 @@ static struct grub_fs grub_minix_fs = .name = "minix", #endif #endif - .fs_dir = grub_minix_dir, - .fs_open = grub_minix_open, - .fs_read = grub_minix_read, - .fs_close = grub_minix_close, + .dir = grub_minix_dir, + .open = grub_minix_open, + .read = grub_minix_read, + .close = grub_minix_close, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c index 4fb8b2e3d..fdcc160e8 100644 --- a/grub-core/fs/newc.c +++ b/grub-core/fs/newc.c @@ -1,73 +1,2 @@ -/* 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_fs_register (&grub_cpio_fs); -} - -GRUB_MOD_FINI (newc) -{ - grub_fs_unregister (&grub_cpio_fs); -} +#define MODE_NEWC 1 +#include "cpio.c" diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 7ed148d3b..f36c513fa 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -136,14 +136,13 @@ 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 -} GRUB_PACKED; +} __attribute__ ((packed)); enum { @@ -215,8 +214,6 @@ 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 { @@ -314,12 +311,10 @@ grub_nilfs2_palloc_group (struct grub_nilfs2_data *data, } static inline grub_uint32_t -grub_nilfs2_palloc_log_groups_per_desc_block (struct grub_nilfs2_data *data) +grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data) { - return LOG2_BLOCK_SIZE (data) - LOG_SIZE_GROUP_DESC; - - COMPILE_TIME_ASSERT (sizeof (struct grub_nilfs2_palloc_group_desc) - == (1 << LOG_SIZE_GROUP_DESC)); + return NILFS2_BLOCK_SIZE (data) / + sizeof (struct grub_nilfs2_palloc_group_desc); } static inline grub_uint32_t @@ -343,8 +338,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_blocks_per_group_log (data, log_entry_size) - << grub_nilfs2_palloc_log_groups_per_desc_block (data)) + 1; + return grub_nilfs2_palloc_groups_per_desc_block (data) * + grub_nilfs2_blocks_per_group_log (data, log_entry_size) + 1; } static inline grub_uint32_t @@ -353,7 +348,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_log_groups_per_desc_block (data); + group / grub_nilfs2_palloc_groups_per_desc_block (data); return desc_block * grub_nilfs2_blocks_per_desc_block_log (data, log_entry_size); } @@ -363,8 +358,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 - & ((1 << grub_nilfs2_palloc_log_groups_per_desc_block (data)) - 1); + unsigned long desc_offset = group % + grub_nilfs2_palloc_groups_per_desc_block (data); return grub_nilfs2_palloc_desc_block_offset_log (data, group, log_entry_size) + 1 @@ -506,13 +501,9 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_uint64_t key, int need_translate) { struct grub_nilfs2_btree_node *node; - void *block; + GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data)); grub_uint64_t ptr; - int level, found = 0, index; - - block = grub_malloc (NILFS2_BLOCK_SIZE (data)); - if (!block) - return -1; + int level, found, index; node = grub_nilfs2_btree_get_root (inode); level = grub_nilfs2_btree_get_level (node); @@ -527,14 +518,14 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_nilfs2_btree_get_nonroot_node (data, ptr, block); if (grub_errno) { - goto fail; + return -1; } node = (struct grub_nilfs2_btree_node *) block; if (node->bn_level != level) { grub_error (GRUB_ERR_BAD_FS, "btree level mismatch\n"); - goto fail; + return -1; } if (!found) @@ -551,19 +542,14 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, else { grub_error (GRUB_ERR_BAD_FS, "btree corruption\n"); - goto fail; + return -1; } } - grub_free (block); - if (!found) return -1; return ptr; - fail: - grub_free (block); - return -1; } static inline grub_uint64_t @@ -640,11 +626,13 @@ 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, - grub_disk_read_hook_t read_hook, void *read_hook_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) { - return grub_fshelp_read_file (node->data->disk, node, - read_hook, read_hook_data, + return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_nilfs2_read_block, grub_le_to_cpu64 (node->inode.i_size), LOG2_NILFS2_BLOCK_SIZE (node->data), 0); @@ -724,10 +712,6 @@ 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; } @@ -868,7 +852,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node) if (!symlink) return 0; - grub_nilfs2_read_file (diro, 0, 0, 0, + grub_nilfs2_read_file (diro, 0, 0, grub_le_to_cpu64 (diro->inode.i_size), symlink); if (grub_errno) { @@ -882,7 +866,10 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node) static int grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { grub_off_t fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; @@ -899,7 +886,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, { struct grub_nilfs2_dir_entry dirent; - grub_nilfs2_read_file (diro, 0, 0, fpos, + grub_nilfs2_read_file (diro, 0, fpos, sizeof (struct grub_nilfs2_dir_entry), (char *) &dirent); if (grub_errno) @@ -910,11 +897,11 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, if (dirent.name_len != 0) { - char filename[MAX_NAMELEN + 1]; + char filename[dirent.name_len + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; - grub_nilfs2_read_file (diro, 0, 0, + grub_nilfs2_read_file (diro, 0, fpos + sizeof (struct grub_nilfs2_dir_entry), dirent.name_len, filename); if (grub_errno) @@ -966,7 +953,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_REG; } - if (hook (filename, type, fdiro, hook_data)) + if (hook (filename, type, fdiro)) return 1; } @@ -1037,74 +1024,64 @@ 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, file->read_hook_data, + return grub_nilfs2_read_file (&data->diropen, file->read_hook, 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info * info)) { - struct grub_nilfs2_dir_ctx ctx = { - .hook = hook, - .hook_data = hook_data - }; + struct grub_nilfs2_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) + { + 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); - ctx.data = grub_nilfs2_mount (device->disk); - if (!ctx.data) + data = grub_nilfs2_mount (device->disk); + if (!data) goto fail; - grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, + grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_nilfs2_iterate_dir (fdiro, grub_nilfs2_dir_iter, &ctx); + grub_nilfs2_iterate_dir (fdiro, iterate); fail: - if (fdiro != &ctx.data->diropen) + if (fdiro != &data->diropen) grub_free (fdiro); - grub_free (ctx.data); + grub_free (data); grub_dl_unref (my_mod); @@ -1192,13 +1169,13 @@ grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm) static struct grub_fs grub_nilfs2_fs = { .name = "nilfs2", - .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, + .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, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 0, diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 2f34f76da..b9762b6a0 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -55,10 +55,10 @@ u64at (void *ptr, grub_size_t ofs) grub_ntfscomp_func_t grub_ntfscomp_func; static grub_err_t -fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic) +fixup (char *buf, int len, const char *magic) { - grub_uint16_t ss; - grub_uint8_t *pu; + int ss; + char *pu; grub_uint16_t us; COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE); @@ -86,20 +86,25 @@ fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic) return 0; } -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, +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, grub_disk_addr_t ofs, grub_size_t len, int cached, - grub_disk_read_hook_t read_hook, - void *read_hook_data); + void + NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t + sector, + unsigned offset, + unsigned length)); -static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, - grub_uint8_t *dest, +static grub_err_t read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - grub_disk_read_hook_t read_hook, - void *read_hook_data); + void + NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t + sector, + unsigned offset, + unsigned length)); static void init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft) @@ -118,8 +123,8 @@ free_attr (struct grub_ntfs_attr *at) grub_free (at->sbuf); } -static grub_uint8_t * -find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) +static char * +find_attr (struct grub_ntfs_attr *at, unsigned char attr) { if (at->flags & GRUB_NTFS_AF_ALST) { @@ -128,9 +133,9 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) { at->attr_cur = at->attr_nxt; at->attr_nxt += u16at (at->attr_cur, 4); - if ((*at->attr_cur == attr) || (attr == 0)) + if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) { - grub_uint8_t *new_pos; + char *new_pos; if (at->flags & GRUB_NTFS_AF_MMFT) { @@ -143,8 +148,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) 512, at->emft_buf + 512))) return NULL; - if (fixup (at->emft_buf, at->mft->data->mft_size, - (const grub_uint8_t *) "FILE")) + if (fixup (at->emft_buf, at->mft->data->mft_size, "FILE")) return NULL; } else @@ -155,9 +159,10 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) } new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)]; - while (*new_pos != 0xFF) + while ((unsigned char) *new_pos != 0xFF) { - if ((*new_pos == *at->attr_cur) + if (((unsigned char) *new_pos == + (unsigned char) *at->attr_cur) && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18))) { return new_pos; @@ -173,18 +178,18 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) return NULL; } at->attr_cur = at->attr_nxt; - while (*at->attr_cur != 0xFF) + while ((unsigned char) *at->attr_cur != 0xFF) { at->attr_nxt += u16at (at->attr_cur, 4); - if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) + if ((unsigned char) *at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) at->attr_end = at->attr_cur; - if ((*at->attr_cur == attr) || (attr == 0)) + if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) return at->attr_cur; at->attr_cur = at->attr_nxt; } if (at->attr_end) { - grub_uint8_t *pa; + char *pa; at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); if (at->emft_buf == NULL) @@ -193,7 +198,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) pa = at->attr_end; if (pa[8]) { - grub_uint32_t n; + int n; n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1) & (~(GRUB_DISK_SECTOR_SIZE - 1))); @@ -201,7 +206,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t 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, 0)) + if (read_data (at, pa, at->edat_buf, 0, n, 0, 0)) { grub_error (GRUB_ERR_BAD_FS, "fail to read non-resident attribute list"); @@ -218,7 +223,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) at->flags |= GRUB_NTFS_AF_ALST; while (at->attr_nxt < at->attr_end) { - if ((*at->attr_nxt == attr) || (attr == 0)) + if (((unsigned char) *at->attr_nxt == attr) || (attr == 0)) break; at->attr_nxt += u16at (at->attr_nxt, 4); } @@ -238,12 +243,12 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) pa = at->attr_nxt + u16at (pa, 4); while (pa < at->attr_end) { - if (*pa != attr) + if ((unsigned char) *pa != attr) break; 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, 0)) + at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) return NULL; pa += u16at (pa, 4); } @@ -255,11 +260,11 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) return NULL; } -static grub_uint8_t * +static char * locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, - grub_uint8_t attr) + unsigned char attr) { - grub_uint8_t *pa; + char *pa; init_attr (at, mft); pa = find_attr (at, attr); @@ -283,40 +288,49 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, return pa; } -static grub_disk_addr_t -read_run_data (const grub_uint8_t *run, int nn, int sig) +static char * +read_run_data (char *run, int nn, grub_disk_addr_t * val, int sig) { - grub_uint64_t r = 0; + grub_disk_addr_t r, v; - if (sig && nn && (run[nn - 1] & 0x80)) - r = -1; + r = 0; + v = 1; - grub_memcpy (&r, run, nn); + while (nn--) + { + r += v * (*(unsigned char *) (run++)); + v <<= 8; + } - return grub_le_to_cpu64 (r); + if ((sig) && (r & (v >> 1))) + r -= v; + + *val = r; + return run; } grub_err_t grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx) { - grub_uint8_t c1, c2; + int c1, c2; grub_disk_addr_t val; - grub_uint8_t *run; + char *run; run = ctx->cur_run; retry: - c1 = ((*run) & 0x7); - c2 = ((*run) >> 4) & 0x7; - run++; + c1 = ((unsigned char) (*run) & 0xF); + c2 = ((unsigned char) (*run) >> 4); if (!c1) { if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST)) { - grub_disk_read_hook_t save_hook; + void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector, + unsigned offset, + unsigned length); save_hook = ctx->comp.disk->read_hook; ctx->comp.disk->read_hook = 0; - run = find_attr (ctx->attr, *ctx->attr->attr_cur); + run = find_attr (ctx->attr, (unsigned char) *ctx->attr->attr_cur); ctx->comp.disk->read_hook = save_hook; if (run) { @@ -331,11 +345,10 @@ retry: } return grub_error (GRUB_ERR_BAD_FS, "run list overflown"); } + run = read_run_data (run + 1, c1, &val, 0); /* length of current VCN */ ctx->curr_vcn = ctx->next_vcn; - 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->next_vcn += val; + run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */ ctx->curr_lcn += val; if (val == 0) ctx->flags |= GRUB_NTFS_RF_BLNK; @@ -363,10 +376,13 @@ 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, grub_uint8_t *pa, grub_uint8_t *dest, +read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - grub_disk_read_hook_t read_hook, void *read_hook_data) + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, + unsigned length)) { + grub_disk_addr_t vcn; struct grub_ntfs_rlst cc, *ctx; if (len == 0) @@ -375,12 +391,9 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, grub_memset (&cc, 0, sizeof (cc)); ctx = &cc; ctx->attr = at; - ctx->comp.log_spc = at->mft->data->log_spc; + ctx->comp.spc = at->mft->data->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)) @@ -389,23 +402,52 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, 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); - ctx->next_vcn = u32at (pa, 0x10); - ctx->curr_lcn = 0; - - if ((pa[0xC] & GRUB_NTFS_FLAG_COMPRESSED) - && !(at->flags & GRUB_NTFS_AF_GPOS)) + if (ctx->flags & GRUB_NTFS_RF_COMP) { if (!cached) return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed"); - return (grub_ntfscomp_func) ? grub_ntfscomp_func (dest, ofs, len, ctx) - : grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), - "ntfscomp"); - } + if (at->sbuf) + { + if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == at->save_pos) + { + grub_disk_addr_t n; - ctx->target_vcn = ofs >> (GRUB_NTFS_BLK_SHR + ctx->comp.log_spc); + 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; + } + 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; while (ctx->next_vcn <= ctx->target_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -417,60 +459,71 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, grub_disk_addr_t st0, st1; grub_uint64_t m; - m = (ofs >> GRUB_NTFS_BLK_SHR) & ((1 << ctx->comp.log_spc) - 1); + grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, &m); st0 = - ((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) + m; + (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m; st1 = st0 + 1; if (st1 == - (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) + (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc) { if (grub_ntfs_read_run_list (ctx)) return grub_errno; - st1 = ctx->curr_lcn << ctx->comp.log_spc; + st1 = ctx->curr_lcn * ctx->comp.spc; } grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0)); grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1)); return 0; } - 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; + 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"); } static grub_err_t -read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, +read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - grub_disk_read_hook_t read_hook, void *read_hook_data) + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, + unsigned length)) { - grub_uint8_t *save_cur; - grub_uint8_t attr; - grub_uint8_t *pp; + char *save_cur; + unsigned char attr; + char *pp; grub_err_t ret; save_cur = at->attr_cur; at->attr_nxt = at->attr_cur; - attr = *at->attr_nxt; + attr = (unsigned char) *at->attr_nxt; if (at->flags & GRUB_NTFS_AF_ALST) { - grub_uint8_t *pa; + char *pa; grub_disk_addr_t vcn; /* If compression is possible make sure that we include possible compressed block size. */ - if (GRUB_NTFS_LOG_COM_SEC >= at->mft->data->log_spc) + if (GRUB_NTFS_COM_SEC >= at->mft->data->spc) vcn = ((ofs >> GRUB_NTFS_COM_LOG_LEN) - << (GRUB_NTFS_LOG_COM_SEC - at->mft->data->log_spc)) & ~0xFULL; + * (GRUB_NTFS_COM_SEC / at->mft->data->spc)) & ~0xFULL; else - vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR); + vcn = grub_divmod64 (ofs, at->mft->data->spc << GRUB_NTFS_BLK_SHR, 0); pa = at->attr_nxt + u16at (at->attr_nxt, 4); while (pa < at->attr_end) { - if (*pa != attr) + if ((unsigned char) *pa != attr) break; if (u32at (pa, 8) > vcn) break; @@ -480,8 +533,7 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, } pp = find_attr (at, attr); if (pp) - ret = read_data (at, pp, dest, ofs, len, cached, - read_hook, read_hook_data); + ret = read_data (at, pp, dest, ofs, len, cached, read_hook); else ret = (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS, @@ -491,17 +543,17 @@ read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, } static grub_err_t -read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, grub_uint64_t mftno) +read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_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, 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"); + 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"); } static grub_err_t -init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno) +init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) { unsigned short flag; @@ -516,17 +568,15 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno) flag = u16at (mft->buf, 0x16); if ((flag & 1) == 0) - return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%llx is not in use", - (unsigned long long) mftno); + return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%X is not in use", mftno); if ((flag & 2) == 0) { - grub_uint8_t *pa; + char *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%llx", - (unsigned long long) mftno); + return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno); if (!pa[8]) mft->size = u32at (pa, 0x10); @@ -549,45 +599,25 @@ free_file (struct grub_ntfs_file *mft) grub_free (mft->buf); } -static char * -get_utf8 (grub_uint8_t *in, grub_size_t len) -{ - 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_fshelp_iterate_dir_hook_t hook, void *hook_data) +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)) { - grub_uint8_t *np; + char *np; int ns; while (1) { - grub_uint8_t namespace; - char *ustr; + char *ustr, namespace; if (pos[0xC] & 2) /* end signature */ break; np = pos + 0x50; - ns = *(np++); + ns = (unsigned char) *(np++); namespace = *(np++); /* @@ -600,6 +630,12 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *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; @@ -613,19 +649,25 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, return 0; fdiro->data = diro->data; - fdiro->ino = u64at (pos, 0) & 0xffffffffffffULL; + fdiro->ino = u32at (pos, 0); fdiro->mtime = u64at (pos, 0x20); - ustr = get_utf8 (np, ns); + ustr = grub_malloc (ns * GRUB_MAX_UTF8_PER_UTF16 + 1); if (ustr == NULL) - { - grub_free (fdiro); - return 0; - } + 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'; + } if (namespace) type |= GRUB_FSHELP_CASE_INSENSITIVE; - if (hook (ustr, type, fdiro, hook_data)) + if (hook (ustr, type, fdiro)) { grub_free (ustr); return 1; @@ -646,7 +688,7 @@ struct symlink_descriptor grub_uint16_t len1; grub_uint16_t off2; grub_uint16_t len2; -} GRUB_PACKED; +} __attribute__ ((packed)); static char * grub_ntfs_read_symlink (grub_fshelp_node_t node) @@ -654,10 +696,11 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) struct grub_ntfs_file *mft; struct symlink_descriptor symdesc; grub_err_t err; - grub_uint8_t *buf16; + grub_uint16_t *buf16; char *buf, *end; grub_size_t len; - grub_uint8_t *pa; + grub_size_t i; + char *pa; grub_size_t off; mft = (struct grub_ntfs_file *) node; @@ -672,13 +715,12 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK); if (pa == NULL) { - grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%llx", - (unsigned long long) mft->ino); + grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%X", mft->ino); return NULL; } - err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0, - sizeof (struct symlink_descriptor), 1, 0, 0); + err = read_attr (&mft->attr, (char *) &symdesc, 0, + sizeof (struct symlink_descriptor), 1, 0); if (err) return NULL; @@ -704,22 +746,26 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) if (!buf16) return NULL; - err = read_attr (&mft->attr, buf16, off, len, 1, 0, 0); + err = read_attr (&mft->attr, (char *) buf16, off, len, 1, 0); if (err) return NULL; - buf = get_utf8 (buf16, len / 2); + buf = grub_malloc (len * 2 + 1); if (!buf) { grub_free (buf16); return NULL; } - grub_free (buf16); - for (end = buf; *end; end++) - if (*end == '\\') - *end = '/'; + for (i = 0; i < len / 2; i++) + { + buf16[i] = grub_le_to_cpu16 (buf16[i]); + if (buf16[i] == '\\') + buf16[i] = '/'; + } + 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])) @@ -732,11 +778,14 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) static int grub_ntfs_iterate_dir (grub_fshelp_node_t dir, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { - grub_uint8_t *bitmap; + unsigned char *bitmap; struct grub_ntfs_attr attr, *at; - grub_uint8_t *cur_pos, *indx, *bmp; + char *cur_pos, *indx, *bmp; int ret = 0; grub_size_t bitmap_len; struct grub_ntfs_file *mft; @@ -775,7 +824,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, } cur_pos += 0x10; /* Skip index root */ - ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data); + ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook); if (ret) goto done; @@ -787,7 +836,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, { int ofs; - ofs = cur_pos[0xA]; + ofs = (unsigned char) cur_pos[0xA]; /* Namelen=4, Name="$I30" */ if ((cur_pos[9] == 4) && (u32at (cur_pos, ofs) == 0x490024) && @@ -804,12 +853,12 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (is_resident) { - grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14), + grub_memcpy (bmp, (char *) (cur_pos + u16at (cur_pos, 0x14)), bitmap_len); } else { - if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0)) + if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0)) { grub_error (GRUB_ERR_BAD_FS, "fails to read non-resident $BITMAP"); @@ -818,7 +867,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, bitmap_len = u32at (cur_pos, 0x30); } - bitmap = bmp; + bitmap = (unsigned char *) bmp; break; } } @@ -843,8 +892,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (bitmap) { - grub_disk_addr_t i; - grub_uint8_t v; + grub_disk_addr_t v, i; indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR); if (indx == NULL) @@ -857,17 +905,15 @@ 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, 0)) - || (fixup (indx, mft->data->idx_size, - (const grub_uint8_t *) "INDX"))) + (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0)) + || (fixup (indx, mft->data->idx_size, "INDX"))) goto done; - ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], - hook, hook_data); + ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook); if (ret) goto done; } v <<= 1; - if (!v) + if (v >= 0x100) { v = 1; bitmap++; @@ -888,7 +934,6 @@ 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; @@ -910,30 +955,23 @@ grub_ntfs_mount (grub_disk_t disk) || (bpb.bytes_per_sector & (bpb.bytes_per_sector - 1)) != 0) goto fail; - 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) + 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) goto fail; - for (data->log_spc = 0; (1U << data->log_spc) < spc; data->log_spc++); - if (bpb.clusters_per_mft > 0) - 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; + data->mft_size = data->spc * bpb.clusters_per_mft; else - data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); + data->mft_size = 1 << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); if (bpb.clusters_per_index > 0) - 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; + data->idx_size = data->spc * bpb.clusters_per_index; else - data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); + data->idx_size = 1 << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); - data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) << data->log_spc; + data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc; if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX)) goto fail; @@ -951,7 +989,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, (const grub_uint8_t *) "FILE")) + if (fixup (data->mmft.buf, data->mft_size, "FILE")) goto fail; if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA)) @@ -974,39 +1012,33 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -1019,7 +1051,7 @@ grub_ntfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx); + grub_ntfs_iterate_dir (fdiro, iterate); fail: if ((fdiro) && (fdiro != &data->cmft)) @@ -1097,8 +1129,7 @@ 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, (grub_uint8_t *) buf, file->offset, len, 1, - file->read_hook, file->read_hook_data); + read_attr (&mft->attr, buf, file->offset, len, 1, file->read_hook); return (grub_errno) ? -1 : (grub_ssize_t) len; } @@ -1126,7 +1157,7 @@ grub_ntfs_label (grub_device_t device, char **label) { struct grub_ntfs_data *data = 0; struct grub_fshelp_node *mft = 0; - grub_uint8_t *pa; + char *pa; grub_dl_ref (my_mod); @@ -1156,11 +1187,21 @@ grub_ntfs_label (grub_device_t device, char **label) pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME); if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) { + char *buf; int len; len = u32at (pa, 0x10) / 2; + buf = grub_malloc (len * 4 + 1); pa += u16at (pa, 0x14); - *label = get_utf8 (pa, len); + { + 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; } fail: @@ -1212,12 +1253,12 @@ grub_ntfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_ntfs_fs = { .name = "ntfs", - .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, + .dir = grub_ntfs_dir, + .open = grub_ntfs_open, + .read = grub_ntfs_read, + .close = grub_ntfs_close, + .label = grub_ntfs_label, + .uuid = grub_ntfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c index 3cd97d337..ec359fa9d 100644 --- a/grub-core/fs/ntfscomp.c +++ b/grub-core/fs/ntfscomp.c @@ -33,9 +33,8 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) 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->log_spc, - 0, - 1 << (cc->log_spc + GRUB_NTFS_BLK_SHR), cc->cbuf)) + (cc->comp_table[cc->comp_head].next_vcn - cc->cbuf_vcn)) * cc->spc, 0, + cc->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)) @@ -45,21 +44,21 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) } static grub_err_t -decomp_getch (struct grub_ntfs_comp *cc, grub_uint8_t *res) +decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res) { - if (cc->cbuf_ofs >= (1U << (cc->log_spc + GRUB_NTFS_BLK_SHR))) + if (cc->cbuf_ofs >= (cc->spc << GRUB_NTFS_BLK_SHR)) { if (decomp_nextvcn (cc)) return grub_errno; } - *res = cc->cbuf[cc->cbuf_ofs++]; + *res = (unsigned char) cc->cbuf[cc->cbuf_ofs++]; return 0; } static grub_err_t decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res) { - grub_uint8_t c1 = 0, c2 = 0; + unsigned char c1 = 0, c2 = 0; if ((decomp_getch (cc, &c1)) || (decomp_getch (cc, &c2))) return grub_errno; @@ -69,7 +68,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, grub_uint8_t *dest) +decomp_block (struct grub_ntfs_comp *cc, char *dest) { grub_uint16_t flg, cnt; @@ -81,7 +80,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) { if (flg & 0x8000) { - grub_uint8_t tag; + unsigned char tag; grub_uint32_t bits, copied; bits = copied = tag = 0; @@ -104,7 +103,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) if (tag & 1) { grub_uint32_t i, len, delta, code, lmask, dshift; - grub_uint16_t word = 0; + grub_uint16_t word; if (decomp_get16 (cc, &word)) return grub_errno; @@ -136,7 +135,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) } else { - grub_uint8_t ch = 0; + unsigned char ch = 0; if (decomp_getch (cc, &ch)) return grub_errno; @@ -160,7 +159,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) { int n; - n = (1 << (cc->log_spc + GRUB_NTFS_BLK_SHR)) - cc->cbuf_ofs; + n = (cc->spc << GRUB_NTFS_BLK_SHR) - cc->cbuf_ofs; if (n > cnt) n = cnt; if ((dest) && (n)) @@ -177,9 +176,9 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) } static grub_err_t -read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *buf, grub_size_t num) +read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) { - int log_cpb = GRUB_NTFS_LOG_COM_SEC - ctx->comp.log_spc; + int cpb = GRUB_NTFS_COM_SEC / ctx->comp.spc; while (num) { @@ -193,7 +192,7 @@ read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *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 = (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR)); + ctx->comp.cbuf_ofs = (ctx->comp.spc << GRUB_NTFS_BLK_SHR); if (ctx->target_vcn >= ctx->next_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -212,23 +211,20 @@ read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *buf, grub_size_t num) } } - nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) >> log_cpb; + nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) / cpb; if (nn > num) nn = num; num -= nn; if (ctx->flags & GRUB_NTFS_RF_BLNK) { - ctx->target_vcn += nn << log_cpb; + ctx->target_vcn += nn * 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, - ctx->file); } } else @@ -239,16 +235,13 @@ read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *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, - ctx->file); nn--; } } } else { - nn <<= log_cpb; + nn *= cpb; while ((ctx->comp.comp_head < ctx->comp.comp_tail) && (nn)) { grub_disk_addr_t tt; @@ -265,15 +258,10 @@ read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *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.log_spc, 0, - tt << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR), buf)) + ctx->target_vcn)) * ctx->comp.spc, 0, + tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - if (grub_file_progress_hook && ctx->file) - grub_file_progress_hook (0, 0, - tt << (ctx->comp.log_spc - + GRUB_NTFS_BLK_SHR), - ctx->file); - buf += tt << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + buf += tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); } nn -= tt; if (ctx->target_vcn >= @@ -287,15 +275,10 @@ read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *buf, grub_size_t num) if (grub_disk_read (ctx->comp.disk, (ctx->target_vcn - ctx->curr_vcn + - ctx->curr_lcn) << ctx->comp.log_spc, 0, - nn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR), buf)) + ctx->curr_lcn) * ctx->comp.spc, 0, + nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - 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), - ctx->file); + buf += nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); } ctx->target_vcn += nn; } @@ -305,62 +288,23 @@ read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *buf, grub_size_t num) } static grub_err_t -ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs, - grub_size_t len, struct grub_ntfs_rlst *ctx) +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) { grub_err_t ret; - grub_disk_addr_t vcn; - - 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, 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 (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR)); + ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << GRUB_NTFS_BLK_SHR); 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) >> (GRUB_NTFS_LOG_COM_SEC - ctx->comp.log_spc)))) + (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / GRUB_NTFS_COM_SEC))) { ret = grub_errno; goto quit; @@ -369,28 +313,21 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs, if (ofs % GRUB_NTFS_COM_LEN) { grub_uint32_t t, n, o; - void *file = ctx->file; - ctx->file = 0; - - t = ctx->target_vcn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); - if (read_block (ctx, ctx->attr->sbuf, 1)) + t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + if (read_block (ctx, at->sbuf, 1)) { ret = grub_errno; goto quit; } - ctx->file = file; - - ctx->attr->save_pos = t; + at->save_pos = t; o = ofs % GRUB_NTFS_COM_LEN; n = GRUB_NTFS_COM_LEN - o; if (n > len) n = len; - grub_memcpy (dest, &ctx->attr->sbuf[o], n); - if (grub_file_progress_hook && ctx->file) - grub_file_progress_hook (0, 0, n, ctx->file); + grub_memcpy (dest, &at->sbuf[o], n); if (n == len) goto quit; dest += n; @@ -408,21 +345,17 @@ ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs, if (len) { grub_uint32_t t; - void *file = ctx->file; - ctx->file = 0; - t = ctx->target_vcn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); - if (read_block (ctx, ctx->attr->sbuf, 1)) + t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + if (read_block (ctx, at->sbuf, 1)) { ret = grub_errno; goto quit; } - ctx->attr->save_pos = t; + at->save_pos = t; - grub_memcpy (dest, ctx->attr->sbuf, len); - if (grub_file_progress_hook && file) - grub_file_progress_hook (0, 0, len, file); + grub_memcpy (dest, at->sbuf, len); } quit: diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c index 790000622..5fa88e3f9 100644 --- a/grub-core/fs/odc.c +++ b/grub-core/fs/odc.c @@ -1,61 +1,2 @@ -/* 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_fs_register (&grub_cpio_fs); -} - -GRUB_MOD_FINI (odc) -{ - grub_fs_unregister (&grub_cpio_fs); -} +#define MODE_ODC 1 +#include "cpio.c" diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c deleted file mode 100644 index 5f516502d..000000000 --- a/grub-core/fs/proc.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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_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 af6a226a7..26adf23c4 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -109,14 +109,14 @@ struct grub_reiserfs_superblock grub_uint8_t unused[4]; grub_uint16_t uuid[8]; char label[16]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_journal_header { grub_uint32_t last_flush_uid; grub_uint32_t unflushed_offset; grub_uint32_t mount_id; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_description_block { @@ -124,14 +124,14 @@ struct grub_reiserfs_description_block grub_uint32_t len; grub_uint32_t mount_id; grub_uint32_t real_blocks[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_commit_block { grub_uint32_t id; grub_uint32_t len; grub_uint32_t real_blocks[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_stat_item_v1 { @@ -145,7 +145,7 @@ struct grub_reiserfs_stat_item_v1 grub_uint32_t ctime; grub_uint32_t rdev; grub_uint32_t first_direct_byte; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_stat_item_v2 { @@ -160,7 +160,7 @@ struct grub_reiserfs_stat_item_v2 grub_uint32_t ctime; grub_uint32_t blocks; grub_uint32_t first_direct_byte; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_key { @@ -172,13 +172,13 @@ struct grub_reiserfs_key { grub_uint32_t offset; grub_uint32_t type; - } GRUB_PACKED v1; + } v1 __attribute__ ((packed)); struct { grub_uint64_t offset_type; - } GRUB_PACKED v2; + } v2 __attribute__ ((packed)); } u; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_item_header { @@ -187,11 +187,11 @@ struct grub_reiserfs_item_header { grub_uint16_t free_space; grub_uint16_t entry_count; - } GRUB_PACKED u; + } u __attribute__ ((packed)); grub_uint16_t item_size; grub_uint16_t item_location; grub_uint16_t version; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_block_header { @@ -200,14 +200,14 @@ struct grub_reiserfs_block_header grub_uint16_t free_space; grub_uint16_t reserved; struct grub_reiserfs_key block_right_delimiting_key; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_disk_child { grub_uint32_t block_number; grub_uint16_t size; grub_uint16_t reserved; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_reiserfs_directory_header { @@ -216,7 +216,7 @@ struct grub_reiserfs_directory_header grub_uint32_t object_id; grub_uint16_t location; grub_uint16_t state; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_fshelp_node { @@ -240,8 +240,9 @@ 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, - grub_disk_read_hook_t read_hook, - void *read_hook_data); + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, + unsigned length)); /* Internal-only functions. Not to be used outside of this file. */ @@ -365,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_compile_time (15ULL << 60)) + = ((key->u.v2.offset_type & grub_cpu_to_le64 (15ULL << 60)) | grub_cpu_to_le64 (value & (~0ULL >> 4))); } @@ -412,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_compile_time (~0ULL >> 4)) + = ((key->u.v2.offset_type & grub_cpu_to_le64 (~0ULL >> 4)) | grub_cpu_to_le64 ((grub_uint64_t) type << 60)); assert (grub_reiserfs_get_key_type (key) == grub_type); @@ -673,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, 0); + ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0); if (ret < 0) { grub_free (symlink_buffer); @@ -717,8 +718,10 @@ 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, - grub_fshelp_iterate_dir_hook_t hook, - void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { struct grub_reiserfs_data *data = item->data; struct grub_reiserfs_block_header *block_header = 0; @@ -781,32 +784,14 @@ 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_fshelp_filetype entry_type; + enum grub_reiserfs_item_type 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; @@ -953,7 +938,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, else { /* Pseudo file ".." never has stat block. */ - if (entry_name_end == entry_name + 2 && grub_memcmp (entry_name, "..", 2) != 0) + if (grub_strcmp (entry_name, "..")) grub_dprintf ("reiserfs", "Warning : %s has no stat block !\n", entry_name); @@ -961,21 +946,18 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, goto next; } } - - c = *entry_name_end; - *entry_name_end = 0; - if (hook (entry_name, entry_type, entry_item, hook_data)) + if (hook (entry_name, entry_type, entry_item)) { - *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) @@ -1018,8 +1000,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_compile_time (1); - key.object_id = grub_cpu_to_le32_compile_time (2); + key.directory_id = grub_cpu_to_le32 (1); + key.object_id = grub_cpu_to_le32 (2); key.u.v2.offset_type = 0; grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2); grub_reiserfs_set_key_offset (&key, 1); @@ -1056,7 +1038,9 @@ 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, - grub_disk_read_hook_t read_hook, void *read_hook_data) + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, + unsigned length)) { unsigned int indirect_block, indirect_block_count; struct grub_reiserfs_key key; @@ -1111,7 +1095,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, switch (found.type) { case GRUB_REISERFS_DIRECT: - block = ((grub_disk_addr_t) found.block_number) * (block_size >> GRUB_DISK_SECTOR_BITS); + block = 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) { @@ -1123,7 +1107,6 @@ 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 @@ -1150,7 +1133,6 @@ 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; @@ -1256,7 +1238,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_data); + file->read_hook); } /* Close the file FILE. */ @@ -1272,46 +1254,38 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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_compile_time (1); - root_key.object_id = grub_cpu_to_le32_compile_time (2); + root_key.directory_id = grub_cpu_to_le32 (1); + root_key.object_id = grub_cpu_to_le32 (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); @@ -1326,7 +1300,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, grub_reiserfs_dir_iter, &ctx); + grub_reiserfs_iterate_dir (found, iterate); grub_free (data); grub_dl_unref (my_mod); return GRUB_ERR_NONE; @@ -1402,12 +1376,12 @@ grub_reiserfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_reiserfs_fs = { .name = "reiserfs", - .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, + .dir = grub_reiserfs_dir, + .open = grub_reiserfs_open, + .read = grub_reiserfs_read, + .close = grub_reiserfs_close, + .label = grub_reiserfs_label, + .uuid = grub_reiserfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index d97b8fbb8..b30caef35 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -171,7 +171,10 @@ grub_romfs_read_symlink (grub_fshelp_node_t node) static int grub_romfs_iterate_dir (grub_fshelp_node_t dir, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { grub_disk_addr_t caddr; struct grub_romfs_file_header hdr; @@ -303,7 +306,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, } } - if (hook ((char *) name, filetype, node, hook_data)) + if (hook ((char *) name, filetype, node)) { grub_free (name); return 1; @@ -313,36 +316,30 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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; @@ -355,7 +352,7 @@ grub_romfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_romfs_iterate_dir (fdiro, grub_romfs_dir_iter, &ctx); + grub_romfs_iterate_dir (fdiro, iterate); fail: grub_free (data); @@ -399,7 +396,6 @@ 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), @@ -461,11 +457,11 @@ grub_romfs_label (grub_device_t device, char **label) static struct grub_fs grub_romfs_fs = { .name = "romfs", - .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, + .dir = grub_romfs_dir, + .open = grub_romfs_open, + .read = grub_romfs_read, + .close = grub_romfs_close, + .label = grub_romfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 0, diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index de2b107a4..f7cdb0898 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -26,7 +26,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -36,7 +35,7 @@ struct grub_sfs_bheader grub_uint8_t magic[4]; grub_uint32_t chksum; grub_uint32_t ipointtomyself; -} GRUB_PACKED; +} __attribute__ ((packed)); /* The sfs rootblock. */ struct grub_sfs_rblock @@ -51,7 +50,7 @@ struct grub_sfs_rblock grub_uint8_t unused3[8]; grub_uint32_t rootobject; grub_uint32_t btree; -} GRUB_PACKED; +} __attribute__ ((packed)); enum { @@ -70,18 +69,18 @@ struct grub_sfs_obj { grub_uint32_t first_block; grub_uint32_t size; - } GRUB_PACKED file; + } file __attribute__ ((packed)); struct { grub_uint32_t hashtable; grub_uint32_t dir_objc; - } GRUB_PACKED dir; + } dir __attribute__ ((packed)); } file_dir; grub_uint32_t mtime; grub_uint8_t type; grub_uint8_t filename[1]; grub_uint8_t comment[1]; -} GRUB_PACKED; +} __attribute__ ((packed)); #define GRUB_SFS_TYPE_DELETED 32 #define GRUB_SFS_TYPE_SYMLINK 64 @@ -96,13 +95,13 @@ struct grub_sfs_objc grub_uint32_t prev; /* The amount of objects depends on the blocksize. */ struct grub_sfs_obj objects[1]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_sfs_btree_node { grub_uint32_t key; grub_uint32_t data; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_sfs_btree_extent { @@ -110,7 +109,7 @@ struct grub_sfs_btree_extent grub_uint32_t next; grub_uint32_t prev; grub_uint16_t size; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_sfs_btree { @@ -121,7 +120,7 @@ struct grub_sfs_btree /* Normally this can be kind of node, but just extents are supported. */ struct grub_sfs_btree_node node[1]; -} GRUB_PACKED; +} __attribute__ ((packed)); @@ -174,11 +173,10 @@ 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 (blocksize); - if (!treeblock) - return grub_errno; + treeblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize); + if (!block) + return 0; next = grub_be_to_cpu32 (data->rblock.btree); tree = (struct grub_sfs_btree *) treeblock; @@ -186,21 +184,17 @@ 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, blocksize, treeblock); + 0, GRUB_DISK_SECTOR_SIZE << data->log_blocksize, + treeblock); if (grub_errno) { grub_free (treeblock); return grub_errno; } - nnodes = grub_be_to_cpu16 (tree->nodes); - if (nnodes * (grub_uint32_t) (tree)->nodesize > blocksize) - break; - - for (i = (int) nnodes - 1; i >= 0; i--) + for (i = grub_be_to_cpu16 (tree->nodes) - 1; i >= 0; i--) { #define EXTNODE(tree, index) \ @@ -267,7 +261,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_calloc (cache_size, sizeof (node->cache[0])); + node->cache = grub_malloc (sizeof (node->cache[0]) * cache_size); if (!node->cache) { grub_errno = 0; @@ -308,15 +302,10 @@ 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; - grub_size_t sz; - - if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz)) - goto fail; - - e = grub_realloc (node->cache, sz); + e = grub_realloc (node->cache,node->cache_allocated * 2 + * sizeof (e[0])); if (!e) { - fail: grub_errno = 0; grub_free (node->cache); node->cache = 0; @@ -356,11 +345,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, - grub_disk_read_hook_t read_hook, void *read_hook_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) { - return grub_fshelp_read_file (node->data->disk, node, - read_hook, read_hook_data, + return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_sfs_read_block, node->size, node->data->log_blocksize, 0); } @@ -471,54 +460,12 @@ 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, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { struct grub_fshelp_node *node = 0; struct grub_sfs_data *data = dir->data; @@ -527,6 +474,46 @@ 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; @@ -583,10 +570,9 @@ 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 (&node, data, filename, block, + if (grub_sfs_create_node (filename, block, grub_be_to_cpu32 (obj->file_dir.file.size), - type, grub_be_to_cpu32 (obj->mtime), - hook, hook_data)) + type, grub_be_to_cpu32 (obj->mtime))) { grub_free (objc_data); return 1; @@ -663,44 +649,37 @@ 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, file->read_hook_data, + return grub_sfs_read_file (&data->diropen, file->read_hook, 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -712,7 +691,7 @@ grub_sfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_sfs_iterate_dir (fdiro, grub_sfs_dir_iter, &ctx); + grub_sfs_iterate_dir (fdiro, iterate); fail: if (data && fdiro != &data->diropen) @@ -736,13 +715,8 @@ grub_sfs_label (grub_device_t device, char **label) data = grub_sfs_mount (disk); if (data) { - 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); + grub_size_t len = grub_strlen (data->label); + *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); if (*label) *grub_latin1_to_utf8 ((grub_uint8_t *) *label, (const grub_uint8_t *) data->label, @@ -758,11 +732,11 @@ grub_sfs_label (grub_device_t device, char **label) static struct grub_fs grub_sfs_fs = { .name = "sfs", - .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, + .dir = grub_sfs_dir, + .open = grub_sfs_open, + .read = grub_sfs_read, + .close = grub_sfs_close, + .label = grub_sfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 1, diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index a5f35c10e..44af0f82a 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "xz.h" @@ -72,7 +71,7 @@ struct grub_squash_super grub_uint64_t diroffset; grub_uint64_t unk1offset; grub_uint64_t unk2offset; -} GRUB_PACKED; +} __attribute__ ((packed)); /* Chunk-based */ struct grub_squash_inode @@ -90,7 +89,7 @@ struct grub_squash_inode grub_uint32_t offset; grub_uint32_t size; grub_uint32_t block_size[0]; - } GRUB_PACKED file; + } __attribute__ ((packed)) file; struct { grub_uint64_t chunk; grub_uint64_t size; @@ -99,13 +98,13 @@ struct grub_squash_inode grub_uint32_t offset; grub_uint32_t dummy3; grub_uint32_t block_size[0]; - } GRUB_PACKED long_file; + } __attribute__ ((packed)) long_file; struct { grub_uint32_t chunk; grub_uint32_t dummy; grub_uint16_t size; grub_uint16_t offset; - } GRUB_PACKED dir; + } __attribute__ ((packed)) dir; struct { grub_uint32_t dummy1; grub_uint32_t size; @@ -113,14 +112,14 @@ struct grub_squash_inode grub_uint32_t dummy2; grub_uint16_t dummy3; grub_uint16_t offset; - } GRUB_PACKED long_dir; + } __attribute__ ((packed)) long_dir; struct { grub_uint32_t dummy; grub_uint32_t namelen; char name[0]; - } GRUB_PACKED symlink; - } GRUB_PACKED; -} GRUB_PACKED; + } __attribute__ ((packed)) symlink; + } __attribute__ ((packed)); +} __attribute__ ((packed)); struct grub_squash_cache_inode { @@ -138,7 +137,7 @@ struct grub_squash_dirent_header grub_uint32_t nelems; grub_uint32_t ino_chunk; grub_uint32_t dummy; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_squash_dirent { @@ -148,7 +147,7 @@ struct grub_squash_dirent /* Actually the value is the length of name - 1. */ grub_uint16_t namelen; char name[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); enum { @@ -165,7 +164,7 @@ struct grub_squash_frag_desc grub_uint64_t offset; grub_uint32_t size; grub_uint32_t dummy; -} GRUB_PACKED; +} __attribute__ ((packed)); enum { @@ -460,17 +459,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node) { char *ret; grub_err_t err; - grub_size_t sz; - - if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz)) - { - grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); - return NULL; - } - - ret = grub_malloc (sz); - if (!ret) - return NULL; + ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); err = read_chunk (node->data, ret, grub_le_to_cpu32 (node->ino.symlink.namelen), @@ -489,7 +478,10 @@ grub_squash_read_symlink (grub_fshelp_node_t node) static int grub_squash_iterate_dir (grub_fshelp_node_t dir, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { grub_uint32_t off; grub_uint32_t endoff; @@ -517,32 +509,24 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, { grub_fshelp_node_t node; - 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); + node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); if (!node) return 0; - grub_memcpy (node, dir, sz); - if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) + grub_memcpy (node, dir, + sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); + if (hook (".", GRUB_FSHELP_DIR, node)) return 1; if (dir->stsize != 1) { grub_err_t err; - if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || - grub_add (sz, sizeof (*node), &sz)) - return 0; - - node = grub_malloc (sz); + node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); if (!node) return 0; - grub_memcpy (node, dir, sz); + grub_memcpy (node, dir, + sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); node->stsize--; err = read_chunk (dir->data, &node->ino, sizeof (node->ino), @@ -552,7 +536,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, if (err) return 0; - if (hook ("..", GRUB_FSHELP_DIR, node, hook_data)) + if (hook ("..", GRUB_FSHELP_DIR, node)) return 1; } } @@ -576,7 +560,6 @@ 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; err = read_chunk (dir->data, &di, sizeof (di), grub_le_to_cpu64 (dir->data->sb.diroffset) @@ -609,22 +592,19 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK) filetype = GRUB_FSHELP_SYMLINK; - if (grub_add (dir->stsize, 1, &sz) || - grub_mul (sz, sizeof (dir->stack[0]), &sz) || - grub_add (sz, sizeof (*node), &sz)) - return 0; - - node = grub_malloc (sz); + node = grub_malloc (sizeof (*node) + + (dir->stsize + 1) * sizeof (dir->stack[0])); if (! node) return 0; - grub_memcpy (node, dir, sz - sizeof(dir->stack[0])); + grub_memcpy (node, dir, + sizeof (*node) + dir->stsize * 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, hook_data); + r = hook (buf, filetype, node); grub_free (buf); if (r) @@ -660,34 +640,28 @@ 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - struct grub_squash_dir_ctx ctx = { hook, 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_data *data = 0; struct grub_fshelp_node *fdiro = 0; struct grub_fshelp_node root; @@ -704,7 +678,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, grub_squash_dir_iter, &ctx); + grub_squash_iterate_dir (fdiro, iterate); squash_unmount (data); @@ -769,7 +743,7 @@ 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_NONE; + grub_err_t err; grub_off_t cumulated_uncompressed_size = 0; grub_uint64_t a = 0; grub_size_t i; @@ -846,12 +820,7 @@ direct_read (struct grub_squash_data *data, curread = data->blksz - boff; if (curread > len) curread = len; - if (!ino->block_sizes[i]) - { - /* Sparse block */ - grub_memset (buf, '\0', curread); - } - else if (!(ino->block_sizes[i] + if (!(ino->block_sizes[i] & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED))) { char *block; @@ -901,57 +870,36 @@ direct_read (struct grub_squash_data *data, static grub_ssize_t -grub_squash_read (grub_file_t file, char *buf, grub_size_t len) +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) { - 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, b; + grub_uint64_t a = 0, 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; } - /* 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; + if (fragment == 0xffffffff) + return direct_read (data, ino, off, buf, 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; @@ -992,7 +940,16 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) if (err) return -1; } - return orig_len; + 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); } static grub_err_t @@ -1018,11 +975,11 @@ grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) static struct grub_fs grub_squash_fs = { .name = "squash4", - .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, + .dir = grub_squash_dir, + .open = grub_squash_open, + .read = grub_squash_read, + .close = grub_squash_close, + .mtime = grub_squash_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 0, diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c index c551ed6b5..6ab62bca7 100644 --- a/grub-core/fs/tar.c +++ b/grub-core/fs/tar.c @@ -1,345 +1,2 @@ -/* 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 - -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; - - data->hofs = data->next_hofs; - - 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 = 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_calloc (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; - data->next_hofs = 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 |= 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; - } - 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_fs_register (&grub_cpio_fs); -} - -GRUB_MOD_FINI (tar) -{ - grub_fs_unregister (&grub_cpio_fs); -} +#define MODE_USTAR 1 +#include "cpio.c" diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 2ac5c1d00..8e28d41e2 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -27,8 +27,6 @@ #include #include #include -#include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -118,32 +116,32 @@ struct grub_udf_lb_addr { grub_uint32_t block_num; grub_uint16_t part_ref; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_short_ad { grub_uint32_t length; grub_uint32_t position; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_long_ad { grub_uint32_t length; struct grub_udf_lb_addr block; grub_uint8_t imp_use[6]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_extent_ad { grub_uint32_t length; grub_uint32_t start; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_charspec { grub_uint8_t charset_type; grub_uint8_t charset_info[63]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_timestamp { @@ -157,14 +155,14 @@ struct grub_udf_timestamp grub_uint8_t centi_seconds; grub_uint8_t hundreds_of_micro_seconds; grub_uint8_t micro_seconds; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_regid { grub_uint8_t flags; grub_uint8_t ident[23]; grub_uint8_t ident_suffix[8]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_tag { @@ -176,7 +174,7 @@ struct grub_udf_tag grub_uint16_t desc_crc; grub_uint16_t desc_crc_length; grub_uint32_t tag_location; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_fileset { @@ -198,7 +196,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; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_icbtag { @@ -210,18 +208,17 @@ struct grub_udf_icbtag grub_uint8_t file_type; struct grub_udf_lb_addr parent_idb; grub_uint16_t flags; -} GRUB_PACKED; +} __attribute__ ((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; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_file_entry { @@ -246,7 +243,7 @@ struct grub_udf_file_entry grub_uint32_t ext_attr_length; grub_uint32_t alloc_descs_length; grub_uint8_t ext_attr[0]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_extended_file_entry { @@ -275,20 +272,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]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_vrs { grub_uint8_t type; grub_uint8_t magic[5]; grub_uint8_t version; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_avdp { struct grub_udf_tag tag; struct grub_udf_extent_ad vds; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_pd { @@ -301,7 +298,7 @@ struct grub_udf_pd grub_uint32_t access_type; grub_uint32_t start; grub_uint32_t length; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_partmap { @@ -320,33 +317,7 @@ struct grub_udf_partmap grub_uint8_t ident[62]; } type2; }; -} 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; +} __attribute__ ((packed)); struct grub_udf_lvd { @@ -363,19 +334,18 @@ struct grub_udf_lvd grub_uint8_t imp_use[128]; struct grub_udf_extent_ad integrity_seq_ext; grub_uint8_t part_maps[1608]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_udf_aed { struct grub_udf_tag tag; grub_uint32_t prev_ae; grub_uint32_t ae_len; -} GRUB_PACKED; +} __attribute__ ((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]; @@ -594,7 +564,9 @@ fail: static grub_ssize_t grub_udf_read_file (grub_fshelp_node_t node, - grub_disk_read_hook_t read_hook, void *read_hook_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) { switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK) @@ -619,11 +591,10 @@ grub_udf_read_file (grub_fshelp_node_t node, return 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); + 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); } static unsigned sblocklist[] = { 256, 512, 0 }; @@ -720,17 +691,7 @@ grub_udf_mount (grub_disk_t disk) } tag.tag_ident = U16 (tag.tag_ident); - 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 (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD) { if (data->npd >= GRUB_UDF_MAX_PDS) { @@ -840,24 +801,6 @@ 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) { @@ -874,7 +817,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) { unsigned i; utf16len = sz - 1; - utf16 = grub_calloc (utf16len, sizeof (utf16[0])); + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); if (!utf16) return NULL; for (i = 0; i < utf16len; i++) @@ -884,52 +827,26 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) { unsigned i; utf16len = (sz - 1) / 2; - utf16 = grub_calloc (utf16len, sizeof (utf16[0])); + utf16 = grub_malloc (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) - { - 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); - } + outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); 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, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { grub_fshelp_node_t child; struct grub_udf_file_ident dirent; @@ -942,12 +859,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, hook_data)) + if (hook (".", GRUB_FSHELP_DIR, child)) return 1; while (offset < U64 (dir->block.fe.file_size)) { - if (grub_udf_read_file (dir, 0, 0, offset, sizeof (dirent), + if (grub_udf_read_file (dir, 0, offset, sizeof (dirent), (char *) &dirent) != sizeof (dirent)) return 0; @@ -965,45 +882,36 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, return 0; if (grub_udf_read_icb (dir->data, &dirent.icb, child)) - { - grub_free (child); - return 0; - } + return 0; + if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT) { /* This is the parent directory. */ - if (hook ("..", GRUB_FSHELP_DIR, child, hook_data)) + if (hook ("..", GRUB_FSHELP_DIR, child)) return 1; } else { enum grub_fshelp_filetype type; char *filename; - grub_uint8_t raw[MAX_FILE_IDENT_LENGTH]; + grub_uint8_t raw[dirent.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, 0, offset, + if ((grub_udf_read_file (dir, 0, offset, dirent.file_ident_length, (char *) raw)) != dirent.file_ident_length) - { - grub_free (child); - return 0; - } + return 0; filename = read_string (raw, dirent.file_ident_length, 0); if (!filename) - { - /* As the hook won't get called. */ - grub_free (child); - grub_print_error (); - } + grub_print_error (); - if (filename && hook (filename, type, child, hook_data)) + if (filename && hook (filename, type, child)) { grub_free (filename); return 1; @@ -1025,24 +933,22 @@ grub_udf_read_symlink (grub_fshelp_node_t node) grub_size_t sz = U64 (node->block.fe.file_size); grub_uint8_t *raw; const grub_uint8_t *ptr; - char *out = NULL, *optr; + char *out, *optr; if (sz < 4) return NULL; raw = grub_malloc (sz); if (!raw) return NULL; - if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0) - goto fail_1; + if (grub_udf_read_file (node, NULL, 0, sz, (char *) raw) < 0) + { + grub_free (raw); + return NULL; + } - if (grub_mul (sz, 2, &sz) || - grub_add (sz, 1, &sz)) - goto fail_0; - - out = grub_malloc (sz); + out = grub_malloc (sz * 2 + 1); if (!out) { - fail_0: grub_free (raw); return NULL; } @@ -1053,18 +959,17 @@ grub_udf_read_symlink (grub_fshelp_node_t node) { grub_size_t s; if ((grub_size_t) (ptr - raw + 4) > sz) - goto fail_1; + goto fail; if (!(ptr[2] == 0 && ptr[3] == 0)) - goto fail_1; + goto fail; s = 4 + ptr[1]; if ((grub_size_t) (ptr - raw + s) > sz) - goto fail_1; + goto fail; switch (*ptr) { case 1: if (ptr[1]) - goto fail_1; - /* Fallthrough. */ + goto fail; case 2: /* in 4 bytes. out: 1 byte. */ optr = out; @@ -1088,11 +993,11 @@ grub_udf_read_symlink (grub_fshelp_node_t node) if (optr != out) *optr++ = '/'; if (!read_string (ptr + 4, s - 4, optr)) - goto fail_1; + goto fail; optr += grub_strlen (optr); break; default: - goto fail_1; + goto fail; } ptr += s; } @@ -1100,71 +1005,65 @@ grub_udf_read_symlink (grub_fshelp_node_t node) grub_free (raw); return out; - fail_1: + fail: 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -1184,7 +1083,7 @@ grub_udf_dir (grub_device_t device, const char *path, GRUB_FSHELP_DIR)) goto fail; - grub_udf_iterate_dir (foundnode, grub_udf_dir_iter, &ctx); + grub_udf_iterate_dir (foundnode, iterate); if (foundnode != rootnode) grub_free (foundnode); @@ -1247,8 +1146,7 @@ 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->read_hook_data, - file->offset, len, buf); + return grub_udf_read_file (node, file->read_hook, file->offset, len, buf); } static grub_err_t @@ -1275,7 +1173,7 @@ grub_udf_label (grub_device_t device, char **label) if (data) { - *label = read_dstring (data->lvd.ident, sizeof (data->lvd.ident)); + *label = read_string (data->lvd.ident, sizeof (data->lvd.ident), 0); grub_free (data); } else @@ -1284,95 +1182,13 @@ 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", - .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, + .dir = grub_udf_dir, + .open = grub_udf_open, + .read = grub_udf_read, + .close = grub_udf_close, + .label = grub_udf_label, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index fca46baa1..bd0cd1f49 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -49,46 +49,18 @@ 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_ufs_to_cpu32 (sblock->bsize)) +#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize)) #define UFS_LOG_BLKSZ(sblock) (data->log2_blksz) #ifdef MODE_UFS2 -#define INODE_ENDIAN(data,field,bits1,bits2) grub_ufs_to_cpu##bits2 (data->inode.field) +#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits2 (data->inode.field) #else -#define INODE_ENDIAN(data,field,bits1,bits2) grub_ufs_to_cpu##bits1 (data->inode.field) +#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits1 (data->inode.field) #endif -#define INODE_SIZE(data) grub_ufs_to_cpu64 (data->inode.size) -#define INODE_MODE(data) grub_ufs_to_cpu16 (data->inode.mode) +#define INODE_SIZE(data) grub_le_to_cpu64 (data->inode.size) +#define INODE_MODE(data) grub_le_to_cpu16 (data->inode.mode) #ifdef MODE_UFS2 #define LOG_INODE_BLKSZ 3 #else @@ -167,9 +139,9 @@ struct grub_ufs_inode grub_uint64_t mtime; grub_uint64_t ctime; grub_uint64_t create_time; - grub_uint32_t atime_usec; - grub_uint32_t mtime_usec; - grub_uint32_t ctime_usec; + grub_uint32_t atime_sec; + grub_uint32_t mtime_sec; + grub_uint32_t ctime_sec; grub_uint32_t create_time_sec; grub_uint32_t gen; grub_uint32_t kernel_flags; @@ -187,7 +159,7 @@ struct grub_ufs_inode }; grub_uint8_t unused[24]; -} GRUB_PACKED; +} __attribute__ ((packed)); #else /* UFS inode. */ struct grub_ufs_inode @@ -197,12 +169,9 @@ struct grub_ufs_inode grub_uint16_t uid; grub_uint16_t gid; grub_uint64_t size; - 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; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; union { struct @@ -217,7 +186,7 @@ struct grub_ufs_inode grub_uint32_t gen; grub_uint32_t unused; grub_uint8_t pad[12]; -} GRUB_PACKED; +} __attribute__ ((packed)); #endif /* Directory entry. */ @@ -234,7 +203,7 @@ struct grub_ufs_dirent grub_uint8_t namelen_bsd; }; }; -} GRUB_PACKED; +} __attribute__ ((packed)); /* Information about a "mounted" ufs filesystem. */ struct grub_ufs_data @@ -257,6 +226,7 @@ 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; @@ -264,41 +234,47 @@ 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_ufs_to_cpu32 (data->sblock.log2_blksz); + log2_blksz = grub_le_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) { - grub_ufs_blk_t indir; +#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_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 0)) << log2_blksz, - blk * sizeof (indir), sizeof (indir), &indir); - return indir; + 0, sizeof (indir), indir); + return indir[blk]; } blk -= indirsz; /* Double indirect block. */ if (blk < (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz) { - grub_ufs_blk_t indir; +#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_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 1)) << log2_blksz, - (blk >> log_indirsz) * sizeof (indir), - sizeof (indir), &indir); + 0, sizeof (indir), indir); grub_disk_read (data->disk, - grub_ufs_to_cpu_blk (indir) << log2_blksz, - (blk & ((1 << log_indirsz) - 1)) * sizeof (indir), - sizeof (indir), &indir); + ((grub_disk_addr_t) indir [blk >> log_indirsz]) + << log2_blksz, + 0, sizeof (indir), indir); - return indir; + return indir[blk & ((1 << log_indirsz) - 1)]; } blk -= (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz; @@ -306,28 +282,31 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) /* Triple indirect block. */ if (!(blk >> (3 * log_indirsz))) { - grub_ufs_blk_t indir; +#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_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 2)) << log2_blksz, - (blk >> (2 * log_indirsz)) * sizeof (indir), - sizeof (indir), &indir); + 0, sizeof (indir), indir); grub_disk_read (data->disk, - grub_ufs_to_cpu_blk (indir) << log2_blksz, - ((blk >> log_indirsz) - & ((1 << log_indirsz) - 1)) * sizeof (indir), - sizeof (indir), &indir); + ((grub_disk_addr_t) indir [blk >> (2 * log_indirsz)]) + << log2_blksz, + 0, sizeof (indir), indir); grub_disk_read (data->disk, - grub_ufs_to_cpu_blk (indir) << log2_blksz, - (blk & ((1 << log_indirsz) - 1)) * sizeof (indir), - sizeof (indir), &indir); + ((grub_disk_addr_t) indir [(blk >> log_indirsz) + & ((1 << log_indirsz) - 1)]) + << log2_blksz, + 0, sizeof (indir), indir); - return indir; + return indir[blk & ((1 << log_indirsz) - 1)]; } - grub_error (GRUB_ERR_BAD_FS, + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ufs does not support quadruple indirect blocks"); return 0; } @@ -337,7 +316,8 @@ 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, - grub_disk_read_hook_t read_hook, void *read_hook_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) { struct grub_ufs_sblock *sblock = &data->sblock; @@ -385,16 +365,15 @@ 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_ufs_to_cpu32 (data->sblock.log2_blksz), + blknr << grub_le_to_cpu32 (data->sblock.log2_blksz), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) return -1; } else - grub_memset (buf, 0, blockend); + grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0); buf += UFS_BLKSZ (sblock) - skipfirst; } @@ -410,17 +389,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_ufs_to_cpu32 (sblock->ino_per_group); + int group = ino / grub_le_to_cpu32 (sblock->ino_per_group); /* Determine the inode within the group. */ - int grpino = ino % grub_ufs_to_cpu32 (sblock->ino_per_group); + int grpino = ino % grub_le_to_cpu32 (sblock->ino_per_group); /* The first block of the group. */ - int grpblk = group * (grub_ufs_to_cpu32 (sblock->frags_per_group)); + int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group)); #ifndef MODE_UFS2 - grpblk += grub_ufs_to_cpu32 (sblock->cylg_offset) - * (group & (~grub_ufs_to_cpu32 (sblock->cylg_mask))); + grpblk += grub_le_to_cpu32 (sblock->cylg_offset) + * (group & (~grub_le_to_cpu32 (sblock->cylg_mask))); #endif if (!inode) @@ -430,8 +409,8 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) } grub_disk_read (data->disk, - ((grub_ufs_to_cpu32 (sblock->inoblk_offs) + grpblk) - << grub_ufs_to_cpu32 (data->sblock.log2_blksz)) + ((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk) + << grub_le_to_cpu32 (data->sblock.log2_blksz)) + grpino / UFS_INODE_PER_BLOCK, (grpino % UFS_INODE_PER_BLOCK) * sizeof (struct grub_ufs_inode), @@ -447,15 +426,11 @@ 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; - grub_size_t sz = INODE_SIZE (data); + char symlink[INODE_SIZE (data) + 1]; 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 @@ -465,14 +440,8 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) && INODE_SIZE (data) <= sizeof (data->inode.symlink)) grub_strcpy (symlink, (char *) data->inode.symlink); else - { - if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0) - { - grub_free(symlink); - return grub_errno; - } - } - symlink[sz] = '\0'; + grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink); + symlink[INODE_SIZE (data)] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') @@ -480,15 +449,10 @@ 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)) - { - grub_free (symlink); - return grub_errno; - } + return grub_errno; grub_ufs_find_file (data, symlink); - grub_free (symlink); - return grub_errno; } @@ -498,91 +462,95 @@ 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) { - const char *name; - const char *next = path; + char fpath[grub_strlen (path) + 1]; + char *name = fpath; + char *next; unsigned int pos = 0; int dirino; - char *filename; - /* 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; + grub_strcpy (fpath, path); - while (1) + /* 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 { struct grub_ufs_dirent dirent; + int namelen; - name = next; - /* Skip the first slash. */ - while (*name == '/') - name++; - if (*name == 0) - { - grub_free (filename); - return GRUB_ERR_NONE; - } + if (grub_strlen (name) == 0) + return GRUB_ERR_NONE; - 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; + if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), + (char *) &dirent) < 0) + return grub_errno; #ifdef MODE_UFS2 - namelen = dirent.namelen_bsd; + namelen = dirent.namelen_bsd; #else - namelen = grub_ufs_to_cpu16 (dirent.namelen); + namelen = grub_le_to_cpu16 (dirent.namelen); #endif - if (namelen < next - name) + { + 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")); + continue; + } + } - if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent), - next - name + (namelen != next - name), - filename) < 0) - goto fail; + pos += grub_le_to_cpu16 (dirent.direntlen); + } while (pos < INODE_SIZE (data)); - 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); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); return grub_errno; } @@ -608,13 +576,12 @@ grub_ufs_mount (grub_disk_t disk) /* No need to byteswap bsize in this check. It works the same on both endiannesses. */ - if (data->sblock.magic == grub_cpu_to_ufs32_compile_time (GRUB_UFS_MAGIC) + if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC && data->sblock.bsize != 0 - && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0) - && data->sblock.ino_per_group != 0) + && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0)) { for (data->log2_blksz = 0; - (1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize); + (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sblock.bsize); data->log2_blksz++); data->disk = disk; @@ -643,7 +610,8 @@ grub_ufs_mount (grub_disk_t disk) static grub_err_t grub_ufs_dir (grub_device_t device, const char *path, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { struct grub_ufs_data *data; unsigned int pos = 0; @@ -677,56 +645,40 @@ grub_ufs_dir (grub_device_t device, const char *path, struct grub_ufs_dirent dirent; int namelen; - if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent), + if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), (char *) &dirent) < 0) break; - if (dirent.direntlen == 0) - break; - #ifdef MODE_UFS2 namelen = dirent.namelen_bsd; #else - namelen = grub_ufs_to_cpu16 (dirent.namelen); + namelen = grub_le_to_cpu16 (dirent.namelen); #endif - char *filename = grub_malloc (namelen + 1); - if (!filename) - goto fail; - struct grub_dirhook_info info; - struct grub_ufs_inode inode; + { + char filename[namelen + 1]; + 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, 0, pos + sizeof (dirent), - namelen, filename) < 0) - { - grub_free (filename); + if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), + namelen, filename) < 0) break; - } - filename[namelen] = '\0'; - grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), - (char *) &inode); + filename[namelen] = '\0'; + grub_ufs_read_inode (data, dirent.ino, (char *) &inode); - 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; + 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; - if (hook (filename, &info, hook_data)) - { - grub_free (filename); + if (hook (filename, &info)) break; - } + } - grub_free (filename); - - pos += grub_ufs_to_cpu16 (dirent.direntlen); + pos += grub_le_to_cpu16 (dirent.direntlen); } fail: @@ -778,8 +730,7 @@ 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->read_hook_data, - file->offset, len, buf); + return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf); } @@ -822,8 +773,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_ufs_to_cpu32 (data->sblock.uuidhi), - (unsigned) grub_ufs_to_cpu32 (data->sblock.uuidlow)); + (unsigned) grub_le_to_cpu32 (data->sblock.uuidhi), + (unsigned) grub_le_to_cpu32 (data->sblock.uuidlow)); else *uuid = NULL; @@ -848,10 +799,10 @@ grub_ufs_mtime (grub_device_t device, grub_int32_t *tm) *tm = 0; else { - *tm = grub_ufs_to_cpu32 (data->sblock.mtime); + *tm = grub_le_to_cpu32 (data->sblock.mtime); #ifdef MODE_UFS2 - if (*tm < (grub_int64_t) grub_ufs_to_cpu64 (data->sblock.mtime2)) - *tm = grub_ufs_to_cpu64 (data->sblock.mtime2); + if (*tm < (grub_int64_t) grub_le_to_cpu64 (data->sblock.mtime2)) + *tm = grub_le_to_cpu64 (data->sblock.mtime2); #endif } @@ -868,20 +819,16 @@ static struct grub_fs grub_ufs_fs = { #ifdef MODE_UFS2 .name = "ufs2", -#else -#ifdef MODE_BIGENDIAN - .name = "ufs1_be", #else .name = "ufs1", #endif -#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, + .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, /* FIXME: set reserved_first_sector. */ #ifdef GRUB_UTIL .blocklist_install = 1, @@ -892,12 +839,8 @@ 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); my_mod = mod; @@ -906,12 +849,8 @@ GRUB_MOD_INIT(ufs1) #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); } diff --git a/grub-core/fs/ufs_be.c b/grub-core/fs/ufs_be.c deleted file mode 100644 index a58f75a99..000000000 --- a/grub-core/fs/ufs_be.c +++ /dev/null @@ -1,2 +0,0 @@ -#define MODE_BIGENDIAN 1 -#include "ufs.c" diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index ea6590290..2c6b00c2a 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -25,7 +25,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -35,64 +34,6 @@ 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) - -/* 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 */ - -/* - * 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. - */ -#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ - (XFS_SB_FEAT_INCOMPAT_FTYPE | \ - XFS_SB_FEAT_INCOMPAT_SPINODES | \ - XFS_SB_FEAT_INCOMPAT_META_UUID) struct grub_xfs_sblock { @@ -104,9 +45,7 @@ struct grub_xfs_sblock grub_uint64_t rootino; grub_uint8_t unused3[20]; grub_uint32_t agsize; - grub_uint8_t unused4[12]; - grub_uint16_t version; - grub_uint8_t unused5[6]; + grub_uint8_t unused4[20]; grub_uint8_t label[12]; grub_uint8_t log2_bsize; grub_uint8_t log2_sect; @@ -115,49 +54,34 @@ struct grub_xfs_sblock grub_uint8_t log2_agblk; grub_uint8_t unused6[67]; grub_uint8_t log2_dirblk; - 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; +} __attribute__ ((packed)); struct grub_xfs_dir_header { grub_uint8_t count; - grub_uint8_t largeino; + grub_uint8_t smallino; union { grub_uint32_t i4; grub_uint64_t i8; - } GRUB_PACKED parent; -} GRUB_PACKED; + } parent __attribute__ ((packed)); +} __attribute__ ((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 / 64 bits. */ -} GRUB_PACKED; + /* Inode number follows, 32 bits. */ +} __attribute__ ((packed)); -/* Structure for directory entry in a block */ struct grub_xfs_dir2_entry { grub_uint64_t inode; grub_uint8_t len; -} GRUB_PACKED; +} __attribute__ ((packed)); -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; +typedef grub_uint32_t grub_xfs_extent[4]; struct grub_xfs_btree_node { @@ -166,22 +90,21 @@ struct grub_xfs_btree_node grub_uint16_t numrecs; grub_uint64_t left; grub_uint64_t right; - /* In V5 here follow crc, uuid, etc. */ - /* Then follow keys and block pointers */ -} GRUB_PACKED; + grub_uint64_t keys[1]; +} __attribute__ ((packed)); struct grub_xfs_btree_root { grub_uint16_t level; grub_uint16_t numrecs; grub_uint64_t keys[1]; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_xfs_time { grub_uint32_t sec; grub_uint32_t nanosec; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_xfs_inode { @@ -200,16 +123,24 @@ struct grub_xfs_inode grub_uint16_t unused3; grub_uint8_t fork_offset; grub_uint8_t unused4[17]; -} GRUB_PACKED; - -#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode) -#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76) + 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)); struct grub_xfs_dirblock_tail { grub_uint32_t leaf_count; grub_uint32_t leaf_stale; -} GRUB_PACKED; +} __attribute__ ((packed)); struct grub_fshelp_node { @@ -226,8 +157,6 @@ struct grub_xfs_data int pos; int bsize; grub_uint32_t agsize; - unsigned int hasftype:1; - unsigned int hascrc:1; struct grub_fshelp_node diropen; }; @@ -235,71 +164,6 @@ 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; - } - return 0; -} - /* Filetype information as used in inodes. */ #define FILETYPE_INO_MASK 0170000 #define FILETYPE_INO_REG 0100000 @@ -316,14 +180,14 @@ static inline grub_uint64_t GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data, grub_uint64_t ino) { - return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); + return (grub_be_to_cpu64 (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 (ino >> GRUB_XFS_INO_AGBITS (data)); + return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)); } static inline grub_disk_addr_t @@ -334,25 +198,37 @@ GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb) } static inline grub_uint64_t -GRUB_XFS_EXTENT_OFFSET (struct grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex) { - return ((grub_be_to_cpu32 (exts[ex].raw[0]) & ~(1 << 31)) << 23 - | grub_be_to_cpu32 (exts[ex].raw[1]) >> 9); + return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 + | grub_be_to_cpu32 (exts[ex][1]) >> 9); } static inline grub_uint64_t -GRUB_XFS_EXTENT_BLOCK (struct grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex) { - return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex].raw[1]) + return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) & (0x1ff)) << 43 - | (grub_uint64_t) grub_be_to_cpu32 (exts[ex].raw[2]) << 11 - | grub_be_to_cpu32 (exts[ex].raw[3]) >> 21); + | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 + | grub_be_to_cpu32 (exts[ex][3]) >> 21); } static inline grub_uint64_t -GRUB_XFS_EXTENT_SIZE (struct grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) { - return (grub_be_to_cpu32 (exts[ex].raw[3]) & ((1 << 21) - 1)); + 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); } @@ -379,109 +255,6 @@ 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, @@ -490,11 +263,9 @@ 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, grub_xfs_inode_size(data), - inode)) + if (grub_disk_read (data->disk, block, offset, + 1 << data->sblock.log2_inode, inode)) return grub_errno; if (grub_strncmp ((char *) inode->magic, "IN", 2)) @@ -503,47 +274,42 @@ 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 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; - struct grub_xfs_extent *exts; + grub_xfs_extent *exts; grub_uint64_t ret = 0; if (node->inode.format == XFS_INODE_FORMAT_BTREE) { - struct grub_xfs_btree_root *root; - const char *keys; + grub_uint64_t *keys; int recoffset; leaf = grub_malloc (node->data->bsize); if (leaf == 0) return 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]; + nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); + keys = &node->inode.data.btree.keys[0]; if (node->inode.fork_offset) - recoffset = (node->inode.fork_offset - 1) / 2; + recoffset = (node->inode.fork_offset + - ((char *) &node->inode.data.btree.keys - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); else - recoffset = (grub_xfs_inode_size(node->data) - - ((char *) keys - (char *) &node->inode)) - / (2 * sizeof (grub_uint64_t)); + recoffset = ((1 << node->data->sblock.log2_inode) + - ((char *) &node->inode.data.btree.keys + - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); do { int i; for (i = 0; i < nrec; i++) { - if (fileblock < get_fsb(keys, i)) + if (fileblock < grub_be_to_cpu64 (keys[i])) break; } @@ -553,16 +319,12 @@ 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, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + 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 ((!node->data->hascrc && - grub_strncmp ((char *) leaf->magic, "BMAP", 4)) || - (node->data->hascrc && - grub_strncmp ((char *) leaf->magic, "BMA3", 4))) + if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) { grub_free (leaf); grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node"); @@ -570,18 +332,18 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } nrec = grub_be_to_cpu16 (leaf->numrecs); - keys = grub_xfs_btree_keys(node->data, leaf); - recoffset = ((node->data->bsize - ((char *) keys + keys = &leaf->keys[0]; + recoffset = ((node->data->bsize - ((char *) &leaf->keys - (char *) leaf)) / (2 * sizeof (grub_uint64_t))); } while (leaf->level); - exts = (struct grub_xfs_extent *) keys; + exts = (grub_xfs_extent *) keys; } else if (node->inode.format == XFS_INODE_FORMAT_EXT) { nrec = grub_be_to_cpu32 (node->inode.nextents); - exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode); + exts = &node->inode.data.extents[0]; } else { @@ -619,13 +381,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, - 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) + 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) { - return grub_fshelp_read_file (node->data->disk, node, - read_hook, read_hook_data, + return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_xfs_read_block, - grub_be_to_cpu64 (node->inode.size) + header_size, + grub_be_to_cpu64 (node->inode.size), node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS, 0); } @@ -634,34 +396,23 @@ grub_xfs_read_file (grub_fshelp_node_t node, static char * grub_xfs_read_symlink (grub_fshelp_node_t node) { - grub_ssize_t size = grub_be_to_cpu64 (node->inode.size); - - if (size < 0) - { - grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); - return 0; - } + int size = grub_be_to_cpu64 (node->inode.size); switch (node->inode.format) { case XFS_INODE_FORMAT_INO: - return grub_strndup (grub_xfs_inode_data(&node->inode), size); + return grub_strndup (node->inode.data.raw, size); case XFS_INODE_FORMAT_EXT: { char *symlink; grub_ssize_t numread; - int off = 0; - - if (node->data->hascrc) - off = 56; symlink = grub_malloc (size + 1); if (!symlink) return 0; - node->inode.size = grub_be_to_cpu64 (size + off); - numread = grub_xfs_read_file (node, 0, 0, off, size, symlink, off); + numread = grub_xfs_read_file (node, 0, 0, size, symlink); if (numread != size) { grub_free (symlink); @@ -692,84 +443,84 @@ 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; - - fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1); - 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 (); - 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, - grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - struct grub_xfs_iterate_dir_ctx ctx = { - .hook = hook, - .hook_data = hook_data, - .diro = diro - }; + 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); + } switch (diro->inode.format) { case XFS_INODE_FORMAT_INO: { - 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; + struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0]; + int smallino = !diro->inode.data.dir.dirhead.smallino; 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 (head->parent.i4); + { + 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); + } else - parent = grub_be_to_cpu64 (head->parent.i8); + { + parent = diro->inode.data.dir.dirhead.parent.i8; + } /* Synthesize the direntries for `.' and `..'. */ - if (iterate_dir_call_hook (diro->ino, ".", &ctx)) + if (call_hook (diro->ino, ".")) return 1; - if (iterate_dir_call_hook (parent, "..", &ctx)) + if (call_hook (parent, "..")) return 1; - for (i = 0; i < head->count; i++) + for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) { grub_uint64_t ino; - grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); - grub_uint8_t c; + grub_uint8_t *inopos = (((grub_uint8_t *) de) + + sizeof (struct grub_xfs_dir_entry) + + de->len - 1); + char name[de->len + 1]; /* inopos might be unaligned. */ if (smallino) @@ -786,17 +537,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); - 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; + grub_memcpy (name, de->name, de->len); + name[de->len] = '\0'; + if (call_hook (ino, name)) + return 1; - de = grub_xfs_inline_next_de(dir->data, head, de); + 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)); } break; } @@ -823,30 +574,34 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, >> dirblk_log2); blk++) { - struct grub_xfs_dir2_entry *direntry = - grub_xfs_first_de(dir->data, dirblock); + /* The header is skipped, the first direntry is stored + from byte 16. */ + int pos = 16; int entries; - struct grub_xfs_dirblock_tail *tail = - grub_xfs_dir_tail(dir->data, dirblock); + int tail_start = (dirblk_size + - sizeof (struct grub_xfs_dirblock_tail)); - numread = grub_xfs_read_file (dir, 0, 0, + struct grub_xfs_dirblock_tail *tail; + tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start]; + + numread = grub_xfs_read_file (dir, 0, blk << dirblk_log2, - dirblk_size, dirblock, 0); + dirblk_size, dirblock); if (numread != dirblk_size) return 0; 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 ((char *)direntry < (char *)tail) + while (pos < (dirblk_size + - (int) sizeof (struct grub_xfs_dir2_entry))) { + 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) @@ -854,20 +609,17 @@ 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. */ - direntry = (struct grub_xfs_dir2_entry *) - (((char *)direntry) + - grub_be_to_cpu16 (grub_get_unaligned16 (skip))); + pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); continue; } - filename = (char *)(direntry + 1); - /* The byte after the filename is for the filetype, padding, or - tag, which is not used by GRUB. So it can be overwritten. */ + 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[direntry->len] = '\0'; - if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), - filename, &ctx)) + if (call_hook (direntry->inode, filename)) { grub_free (dirblock); return 1; @@ -880,7 +632,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, break; /* Select the next directory entry. */ - direntry = grub_xfs_next_de(dir->data, direntry); + pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len); + pos = GRUB_XFS_ROUND_TO_DIRENT (pos); } } grub_free (dirblock); @@ -900,42 +653,41 @@ 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; - 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_xfs_sb_valid(data)) - 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_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); + data = grub_realloc (data, + sizeof (struct grub_xfs_data) + - sizeof (struct grub_xfs_inode) + + (1 << data->sblock.log2_inode)); if (! data) goto fail; data->diropen.data = data; - data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino); + data->diropen.ino = 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); @@ -951,40 +703,34 @@ 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; -}; - -/* 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_be_to_cpu32 (node->inode.mtime.sec); - } - 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, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - 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); @@ -996,7 +742,7 @@ grub_xfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_xfs_iterate_dir (fdiro, grub_xfs_dir_iter, &ctx); + grub_xfs_iterate_dir (fdiro, iterate); fail: if (fdiro != &data->diropen) @@ -1038,7 +784,10 @@ grub_xfs_open (struct grub_file *file, const char *name) if (fdiro != &data->diropen) { - grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data)); + grub_memcpy (&data->diropen, fdiro, + sizeof (struct grub_fshelp_node) + - sizeof (struct grub_xfs_inode) + + (1 << data->sblock.log2_inode)); grub_free (fdiro); } @@ -1066,9 +815,8 @@ 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->read_hook_data, - file->offset, len, buf, 0); + return grub_xfs_read_file (&data->diropen, file->read_hook, + file->offset, len, buf); } @@ -1140,12 +888,12 @@ grub_xfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_xfs_fs = { .name = "xfs", - .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, + .dir = grub_xfs_dir, + .open = grub_xfs_open, + .read = grub_xfs_read, + .close = grub_xfs_close, + .label = grub_xfs_label, + .uuid = grub_xfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 1, diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 41ef0ff57..ba0554abd 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2,7 +2,6 @@ * 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 @@ -55,7 +54,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -130,7 +128,7 @@ LEAF_HASH (int bs, grub_uint64_t h, zap_leaf_phys_t *l) static inline int ZAP_LEAF_NUMCHUNKS (int bs) { - return (((1U << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) / + return (((1 << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) / ZAP_LEAF_CHUNKSIZE - 2); } @@ -142,10 +140,7 @@ ZAP_LEAF_NUMCHUNKS (int bs) static inline zap_leaf_chunk_t * ZAP_LEAF_CHUNK (zap_leaf_phys_t *l, int bs, int idx) { - 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 + return &((zap_leaf_chunk_t *) (l->l_entries + (ZAP_LEAF_HASH_NUMENTRIES(bs) * 2) / sizeof (grub_properly_aligned_t)))[idx]; } @@ -158,13 +153,11 @@ ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) /* - * Decompression Entry - lzjb & lz4 + * Decompression Entry - lzjb */ 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 @@ -183,10 +176,10 @@ typedef void zio_checksum_t(const void *data, grub_uint64_t size, * 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 @@ -256,17 +249,10 @@ 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, @@ -277,37 +263,14 @@ 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", - NULL -}; - -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) == (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; + if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0) + return grub_errno; + return GRUB_ERR_NONE; } static grub_err_t @@ -359,7 +322,6 @@ 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 */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, @@ -379,7 +341,7 @@ zfs_log2 (grub_uint64_t num) num = num >> 1; } - return i; + return (i); } /* Checksum Functions */ @@ -426,7 +388,7 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, { grub_dprintf ("zfs", "unknown checksum function %d\n", checksum); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown checksum function %d", checksum); + "unknown checksum function %d", checksum); } if (ci->ci_eck) @@ -487,19 +449,19 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) 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_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) < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) - return -1; + 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); } /* @@ -520,11 +482,15 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset, if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC - && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN))) + && 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) endian = GRUB_ZFS_LITTLE_ENDIAN; if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC - && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN))) + && 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) endian = GRUB_ZFS_BIG_ENDIAN; if (endian == GRUB_ZFS_UNKNOWN_ENDIAN) @@ -581,7 +547,7 @@ find_bestub (uberblock_phys_t * ub_array, if (!ubbest) grub_errno = err; - return ubbest; + return (ubbest); } static inline grub_size_t @@ -777,14 +743,11 @@ fill_vdev_info (struct grub_zfs_data *data, if (data->n_devices_attached > data->n_devices_allocated) { void *tmp; - 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); + 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])); if (!data->devices_attached) { data->devices_attached = tmp; @@ -800,167 +763,6 @@ 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. * @@ -968,10 +770,10 @@ nvpair_value (const char *nvp,char **val, static grub_err_t check_pool_label (struct grub_zfs_data *data, struct grub_zfs_device_desc *diskdesc, - int *inserted, int original) + int *inserted) { grub_uint64_t pool_state, txg = 0; - char *nvlist,*features; + char *nvlist; #if 0 char *nv; #endif @@ -979,9 +781,6 @@ 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; @@ -989,28 +788,6 @@ 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) - return err; - grub_dprintf ("zfs", "check 2 passed\n"); found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE, @@ -1060,13 +837,13 @@ check_pool_label (struct grub_zfs_data *data, } grub_dprintf ("zfs", "check 8 passed\n"); - if (!SPA_VERSION_IS_SUPPORTED(version)) + if (version > SPA_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_BEFORE_FEATURES); + (unsigned long long) SPA_VERSION); } grub_dprintf ("zfs", "check 9 passed\n"); @@ -1092,11 +869,10 @@ check_pool_label (struct grub_zfs_data *data, grub_dprintf ("zfs", "check 11 passed\n"); - if (original) - data->guid = poolguid; - - if (data->guid != poolguid) + if (data->mounted && data->guid != poolguid) return grub_error (GRUB_ERR_BAD_FS, "another zpool"); + else + data->guid = poolguid; { char *nv; @@ -1117,31 +893,7 @@ 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); - return err; - } - } - } - grub_dprintf ("zfs", "check 12 passed (feature flags)\n"); + grub_free (nvlist); return GRUB_ERR_NONE; @@ -1198,7 +950,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, original); + err = check_pool_label (data, &desc, inserted); if (err || !*inserted) { grub_errno = GRUB_ERR_NONE; @@ -1236,47 +988,43 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, 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) { - grub_device_iterate (scan_devices_iter, 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); return GRUB_ERR_NONE; } @@ -1289,9 +1037,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, - unsigned known_idx, unsigned recovery_pow) + int known_idx, int recovery_pow) { - unsigned add; + int add; /* Simple xor. */ if (known_idx == 0 || recovery_pow == 0) @@ -1313,12 +1061,10 @@ gf_mul (grub_uint8_t a, grub_uint8_t b) return powx[powx_inv[a] + powx_inv[b]]; } -#define MAX_NBUFS 4 - -static grub_err_t +static inline grub_err_t recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, const unsigned *powers, - const unsigned *idx) + const int *idx) { grub_dprintf ("zfs", "recovering %u buffers\n", nbufs); /* Now we have */ @@ -1369,9 +1115,9 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, return GRUB_ERR_NONE; } /* Otherwise use Gauss. */ - case 3: + default: { - grub_uint8_t matrix1[MAX_NBUFS][MAX_NBUFS], matrix2[MAX_NBUFS][MAX_NBUFS]; + grub_uint8_t matrix1[nbufs][nbufs], matrix2[nbufs][nbufs]; int i, j, k; for (i = 0; i < nbufs; i++) @@ -1381,7 +1127,7 @@ 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++) { @@ -1439,7 +1185,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[MAX_NBUFS]; + grub_uint8_t b[nbufs]; for (j = 0; j < nbufs; j++) b[j] = bufs[j][i]; for (j = 0; j < nbufs; j++) @@ -1451,8 +1197,6 @@ 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"); } } @@ -1490,9 +1234,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, break; grub_errno = GRUB_ERR_NONE; } - grub_errno = err; - - return err; + return (grub_errno = err); } case DEVICE_RAIDZ: { @@ -1505,7 +1247,7 @@ 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]; - unsigned recovery_idx[4]; + int recovery_idx[4]; unsigned failed_devices = 0; int idx, orig_idx; @@ -1513,9 +1255,6 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, 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; @@ -1763,7 +1502,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 (BP_IS_HOLE(&zio_gb->zg_blkptr[i])) + if (zio_gb->zg_blkptr[i].blk_birth == 0) continue; err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data); @@ -1812,39 +1551,6 @@ 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. @@ -1863,26 +1569,12 @@ 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) & 0x7f; + comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3); - 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=%u)\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); + lsize = (BP_IS_HOLE(bp) ? 0 : + (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) + << SPA_MINBLOCKSHIFT)); + psize = get_psize (bp, endian); if (size) *size = lsize; @@ -1896,41 +1588,33 @@ 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)); + { + /* It's not really necessary to align to 16, just for safety. */ + compbuf = grub_malloc (ALIGN_UP (psize, 16)); + if (! compbuf) + return grub_errno; + } else compbuf = *buf = grub_malloc (lsize); - if (! compbuf) - return grub_errno; grub_dprintf ("zfs", "endian = %d\n", endian); - 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); - } + err = zio_read_data (bp, endian, compbuf, data); if (err) { grub_free (compbuf); *buf = NULL; return err; } + grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize); - if (!BP_IS_EMBEDDED(bp)) + err = zio_checksum_verify (zc, checksum, endian, + compbuf, psize); + if (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; - } + grub_dprintf ("zfs", "incorrect checksum\n"); + grub_free (compbuf); + *buf = NULL; + return err; } if (encrypted) @@ -1969,7 +1653,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, zc.zc_mac, + compbuf, psize, ((grub_uint32_t *) &zc + 5), endian); } if (err) @@ -2042,7 +1726,7 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, dn->endian) << SPA_MINBLOCKSHIFT; *buf = grub_malloc (size); - if (!*buf) + if (*buf) { err = grub_errno; break; @@ -2080,14 +1764,12 @@ 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, - grub_uint32_t objsize, const char *name, grub_uint64_t * value, + int objsize, const char *name, grub_uint64_t * value, int case_insensitive) { - grub_uint32_t i, chunks; + int 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++) { @@ -2104,9 +1786,8 @@ 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 (*hook) (const char *name, grub_uint64_t val, - struct grub_zfs_dir_ctx *ctx), - struct grub_zfs_dir_ctx *ctx) + int NESTED_FUNC_ATTR (*hook) (const char *name, + grub_uint64_t val)) { int i, chunks; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; @@ -2118,7 +1799,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, 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), ctx)) + grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian))) return 1; } @@ -2160,7 +1841,7 @@ zap_hash (grub_uint64_t salt, const char *name, */ crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1); - return crc; + return (crc); } /* @@ -2182,7 +1863,7 @@ name_cmp (const char *s1, const char *s2, grub_size_t 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++; @@ -2369,11 +2050,12 @@ 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 (*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) + 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) { zap_leaf_phys_t *l; void *l_in; @@ -2403,11 +2085,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; @@ -2433,53 +2115,53 @@ 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) - continue; - - 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); + /* Verify the chunk entry */ + if (le->le_type != ZAP_CHUNK_ENTRY) 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 (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; - } + 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; - 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); - } + 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); + } grub_free (l); } return 0; @@ -2495,7 +2177,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; - grub_uint32_t size; + int size; void *zapbuf; grub_err_t err; grub_zfs_endian_t endian; @@ -2503,7 +2185,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_uint32_t) grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + size = 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) @@ -2535,35 +2217,11 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, 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_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) + int NESTED_FUNC_ATTR (*hook) (const char *name, + grub_uint64_t val), + struct grub_zfs_data *data) { grub_uint64_t block_type; int size; @@ -2572,6 +2230,23 @@ 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); @@ -2584,21 +2259,15 @@ 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, ctx); + ret = mzap_iterate (zapbuf, endian, size, hook); 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, - zap_iterate_u64_transform, &transform_ctx, data); + ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data); grub_free (zapbuf); return ret; } @@ -2609,11 +2278,12 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, static int zap_iterate (dnode_end_t * zap_dnode, grub_size_t nameelemlen, - 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) + 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) { grub_uint64_t block_type; void *zapbuf; @@ -2638,8 +2308,7 @@ zap_iterate (dnode_end_t * zap_dnode, { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data, - data); + ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data); grub_free (zapbuf); return ret; } @@ -2873,12 +2542,9 @@ 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) + dnode_path->dn.endian) << SPA_MINBLOCKSHIFT); - if (blksz == 0) - return grub_error(GRUB_ERR_BAD_FS, "0-sized block"); - sym_value = grub_malloc (sym_sz); if (!sym_value) return grub_errno; @@ -2889,10 +2555,7 @@ 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) - { - grub_free (sym_value); - return err; - } + return err; movesize = sym_sz - block * blksz; if (movesize > blksz) @@ -2907,8 +2570,6 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, if (!path_buf) { grub_free (oldpathbuf); - if (free_symval) - grub_free (sym_value); return grub_errno; } grub_memcpy (path, sym_value, sym_sz); @@ -2926,11 +2587,11 @@ 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); + } } if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA) { @@ -2987,11 +2648,11 @@ 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); + } } } } @@ -3092,7 +2753,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, grub_dprintf ("zfs", "alive\n"); - err = dnode_get (mosmdn, objnum, 0, mdn, data); + err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); if (err) return err; @@ -3125,7 +2786,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, if (err) return err; - err = dnode_get (mosmdn, objnum, 0, mdn, data); + err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); if (err) return err; @@ -3139,7 +2800,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) { void *osp; blkptr_t *bp; - grub_size_t ospsize = 0; + grub_size_t ospsize; grub_err_t err; grub_dprintf ("zfs", "endian = %d\n", mdn->endian); @@ -3161,61 +2822,6 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) 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, @@ -3225,7 +2831,57 @@ 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) @@ -3280,7 +2936,8 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); - err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data); + err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn, + data); if (err) { grub_free (fsname); @@ -3292,10 +2949,6 @@ 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); @@ -3309,12 +2962,12 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } - err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0); + err = zap_lookup (&props_dn, "salt", &salt, data, 0); if (err == GRUB_ERR_FILE_NOT_FOUND) { err = 0; grub_errno = 0; - ctx.salt = 0; + salt = 0; } if (err) { @@ -3331,15 +2984,15 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } subvol->nkeys = 0; - zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data); - subvol->keyring = grub_calloc (subvol->nkeys, sizeof (subvol->keyring[0])); + zap_iterate (&keychain_dn, 8, count_zap_keys, data); + subvol->keyring = grub_zalloc (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, &ctx, data); + zap_iterate (&keychain_dn, 8, load_zap_key, data); } if (snapname) @@ -3381,15 +3034,34 @@ 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) { - grub_size_t nvp_name_len, name_len = grub_strlen(name); - int type; - const char *nvpair=NULL,*nvlist=nvlist_in; - char *nvp_name; + int name_len, type, encode_size; + const char *nvpair, *nvp_name, *nvlist = nvlist_in; /* Verify if the 1st and 2nd byte in the nvlist are valid. */ /* NOTE: independently of what endianness header announces all @@ -3402,21 +3074,62 @@ 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 ((nvpair=nvlist_next_nvpair(nvlist,nvpair))) + while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist)))) { - 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) + int nelm; + + if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE) { - return nvpair_value(nvpair,val,size_out,nelm_out); + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return 0; } + + 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; } @@ -3475,18 +3188,14 @@ grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name) { char *nvpair; char *ret; - grub_size_t size, sz; + grub_size_t size; int found; found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, &size, 0); if (!found) return 0; - - if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz)) - return 0; - - ret = grub_zalloc (sz); + ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t)); if (!ret) return 0; grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); @@ -3677,16 +3386,6 @@ zfs_mount (grub_device_t dev) return NULL; } - if (ub->ub_version >= SPA_VERSION_FEATURES && - check_mos_features(&((objset_phys_t *) 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); @@ -3694,6 +3393,8 @@ zfs_mount (grub_device_t dev) ub_endian) >> 63) & 1; grub_free (osp); + data->mounted = 1; + return data; } @@ -3884,12 +3585,6 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) 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 @@ -3966,7 +3661,7 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, return err; } -static grub_err_t +static void fill_fs_info (struct grub_dirhook_info *info, dnode_end_t mdn, struct grub_zfs_data *data) { @@ -3983,36 +3678,34 @@ fill_fs_info (struct grub_dirhook_info *info, { 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, 0, &mdn, data); + err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return err; + return; } } - err = make_mdn (&mdn, data); - if (err) - return err; + make_mdn (&mdn, data); err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, &dn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return err; + return; } err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0); if (err) { grub_dprintf ("zfs", "failed here\n"); - return err; + return; } err = dnode_get (&mdn, objnum, 0, &dn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return err; + return; } if (dn.dn.dn_bonustype == DMU_OT_SA) @@ -4030,12 +3723,12 @@ fill_fs_info (struct grub_dirhook_info *info, err = zio_read (bp, dn.endian, &sahdrp, NULL, data); if (err) - return err; + return; } else { grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - return grub_errno; + return; } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); @@ -4048,146 +3741,111 @@ 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 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; - - 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; - } - } - 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 (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; - - 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) - 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; - - 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) - return 0; - - err = fill_fs_info (&info, mdn, ctx->data); - if (err) - { - grub_errno = 0; - return 0; - } - - name2 = grub_malloc (grub_strlen (name) + 2); - name2[0] = '@'; - grub_memcpy (name2 + 1, name, grub_strlen (name) + 1); - ret = ctx->hook (name2, &info, ctx->hook_data); - grub_free (name2); - return ret; + return; } static grub_err_t grub_zfs_dir (grub_device_t device, const char *path, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *, const struct grub_dirhook_info *)) { - 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) @@ -4198,8 +3856,6 @@ 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; @@ -4207,18 +3863,9 @@ grub_zfs_dir (grub_device_t device, const char *path, dnode_end_t dn; struct grub_dirhook_info 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; - } - + fill_fs_info (&info, data->dnode, data); + hook ("@", &info); + 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, @@ -4229,7 +3876,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx); + zap_iterate_u64 (&dn, iterate_zap_fs, data); err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data); if (err) @@ -4248,7 +3895,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx); + zap_iterate_u64 (&dn, iterate_zap_snap, data); } else { @@ -4257,74 +3904,12 @@ 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, &ctx); + zap_iterate_u64 (&(data->dnode), iterate_zap, data); } 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; - 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; - return mzap_iterate (mzp,endianzap, size, check_feature,NULL); -} - - #ifdef GRUB_UTIL static grub_err_t grub_zfs_embed (grub_device_t device __attribute__ ((unused)), @@ -4339,7 +3924,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")); @@ -4347,7 +3932,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_calloc (*nsectors, sizeof (**sectors)); + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); if (!*sectors) return grub_errno; for (i = 0; i < *nsectors; i++) @@ -4359,15 +3944,15 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), static struct grub_fs grub_zfs_fs = { .name = "zfs", - .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, + .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, #ifdef GRUB_UTIL - .fs_embed = grub_zfs_embed, + .embed = grub_zfs_embed, .reserved_first_sector = 1, .blocklist_install = 0, #endif diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c deleted file mode 100644 index 5453822d0..000000000 --- a/grub-core/fs/zfs/zfs_lz4.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index de3b015f5..4ea53b863 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -83,13 +82,9 @@ 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; - if (grub_add (sizeof (*key), keylen, &sz)) - return GRUB_ERR_OUT_OF_RANGE; - key = grub_malloc (sz); + key = grub_malloc (sizeof (*key) + keylen); if (!key) return grub_errno; key->is_passphrase = passphrase; @@ -148,7 +143,7 @@ grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, return err; if (mac_out) grub_crypto_xor (mac_out, mac, mul, m); - return GPG_ERR_NO_ERROR; + return GRUB_ERR_NONE; } static void @@ -243,13 +238,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] ^= ((((grub_uint64_t) psize) * 8) >> (8 * j)); + mac[15 - j] ^= ((psize * 8) >> (8 * j)); grub_gcm_mul (mac, h); if (mac_out) grub_crypto_xor (mac_out, mac, mac_xor, m); - return GPG_ERR_NO_ERROR; + return GRUB_ERR_NONE; } @@ -263,14 +258,13 @@ 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 GPG_ERR_CIPHER_ALGO; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "algorithm %" + PRIuGRUB_UINT64_T " is not supported yet", algo); } } @@ -285,7 +279,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, grub_uint32_t mac[4]; unsigned i; grub_uint32_t sw[4]; - gcry_err_code_t err; + grub_err_t err; grub_memcpy (sw, nonce, 16); if (endian != GRUB_ZFS_BIG_ENDIAN) @@ -301,7 +295,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, size, mac, sw + 1, 3, 12); if (err) - return grub_crypto_gcry_error (err); + return err; for (i = 0; i < 3; i++) if (grub_zfs_to_cpu32 (expected_mac[i], endian) @@ -359,7 +353,6 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, if (err) { grub_errno = GRUB_ERR_NONE; - grub_crypto_cipher_close (cipher); continue; } @@ -368,7 +361,6 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, if (err) { grub_errno = GRUB_ERR_NONE; - grub_crypto_cipher_close (cipher); continue; } @@ -379,7 +371,6 @@ 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; } @@ -389,25 +380,21 @@ 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); - grub_crypto_cipher_close (cipher); - continue; - } - grub_crypto_cipher_close (cipher); + grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (ret); + continue; + } return ret; } return NULL; @@ -430,7 +417,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], GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY); + file = grub_file_open (args[0]); 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 c8a28acf5..fdb587a4c 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -130,35 +130,23 @@ 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 (is_mirror || is_raidz) + if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) { 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 VDEV")); + grub_puts_ (N_("Incorrect mirror")); return GRUB_ERR_NONE; } - grub_printf_ (N_("VDEV with %d children\n"), nelm); + grub_printf_ (N_("Mirror with %d children\n"), nelm); print_state (nvlist, tab); for (i = 0; i < nelm; i++) { @@ -174,14 +162,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_("VDEV element number %d isn't correct\n"), i); + grub_printf_ (N_("Mirror 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_("VDEV element number %d:\n"), i); + grub_printf_ (N_("Mirror element number %d:\n"), i); print_vdev_info (child, tab + 1); grub_free (child); diff --git a/grub-core/gdb/cstub.c b/grub-core/gdb/cstub.c index b64acd70f..a5c0c4316 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 __attribute__ ((regparm(3))) +void grub_gdb_trap (int trap_no) { - unsigned int sig_no; + 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_fatal ("Unhandled exception"); + grub_abort (); } 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 & 0xf]; + grub_gdb_outbuf[2] = hexchars[sig_no % 16]; grub_gdb_outbuf[3] = 0; break; @@ -336,7 +336,6 @@ 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/i386/machdep.S b/grub-core/gdb/i386/machdep.S index f96d2b9c4..1615b0c9f 100644 --- a/grub-core/gdb/i386/machdep.S +++ b/grub-core/gdb/i386/machdep.S @@ -71,7 +71,11 @@ 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 @@ -186,7 +190,11 @@ VARIABLE(grub_gdb_stack) .text 1: .if EC - add MACRO_DOLLAR(4), %esp +#ifdef __APPLE__ + add $$4, %esp +#else + add $4, %esp +#endif .endif save_context diff --git a/grub-core/gdb/i386/signal.c b/grub-core/gdb/i386/signal.c index 1ac3bbd18..23b7c3506 100644 --- a/grub-core/gdb/i386/signal.c +++ b/grub-core/gdb/i386/signal.c @@ -24,7 +24,7 @@ /* Converting CPU trap number to UNIX signal number as described in System V ABI i386 Processor Supplement, 3-25. */ -unsigned int +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 e322d3dc1..01ef3e15b 100644 --- a/grub-core/gdb_grub.in +++ b/grub-core/gdb_grub.in @@ -22,7 +22,7 @@ define dump_module_sections printf "%s", $mod->name set $segment = $mod->segment while ($segment) - printf " %i 0x%lx", $segment->section, $segment->addr + printf " %i 0x%x", $segment->section, $segment->addr set $segment = $segment->next end printf "\n" @@ -61,7 +61,7 @@ end define load_all_modules set $this = grub_dl_head while ($this != 0) - dump_module_sections $this + dump_module_sections $this->mod set $this = $this->next end match_and_load_symbols diff --git a/grub-core/genemuinit.sh b/grub-core/genemuinit.sh index 8c6bb1c18..45c15ecb9 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 ();" + echo "grub_${line}_init ();" | sed 's,\.mod,,g;' 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 ();" + echo "grub_${line}_fini ();" | sed 's,\.mod,,g;' fi done diff --git a/grub-core/genemuinitheader.sh b/grub-core/genemuinitheader.sh index a99a15d06..6b83f5993 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);" + echo "void grub_${line}_init (void);" | sed 's,\.mod,,g;' fi if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then - echo "void grub_${line%%.*}_fini (void);" + echo "void grub_${line}_fini (void);" | sed 's,\.mod,,g;' fi done diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in index 1250589b3..76df0bbb4 100644 --- a/grub-core/genmod.sh.in +++ b/grub-core/genmod.sh.in @@ -1,4 +1,4 @@ -#! @BUILD_SHEBANG@ +#! /bin/sh set -e # Copyright (C) 2010 Free Software Foundation, Inc. @@ -15,12 +15,12 @@ set -e # # Example: # -# genmod.sh moddep.lst normal.module build-grub-module-verifier normal.mod +# genmod.sh moddep.lst normal.module normal.mod # moddep=$1 infile=$2 -outfile=$4 +outfile=$3 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_LINKER@ != x1; then +if test x@TARGET_APPLE_CC@ != x1; then # stripout .modname and .moddeps sections from input module - @TARGET_OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile + @OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile # Attach .modname and .moddeps sections t1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 @@ -47,25 +47,21 @@ if test x@TARGET_APPLE_LINKER@ != x1; then for dep in $deps; do printf "$dep\0" >> $t2; done if test -n "$deps"; then - @TARGET_OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile + @OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile else - @TARGET_OBJCOPY@ --add-section .modname=$t1 $tmpfile + @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 - @TARGET_STRIP@ --strip-unneeded \ + @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 .gnu.build.attributes \ - -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 + -R .note -R .comment $tmpfile || exit 1 fi else tmpfile2=${outfile}.tmp2 @@ -91,13 +87,10 @@ else mv $tmpfile2 $tmpfile cp $tmpfile $tmpfile.bin - @TARGET_OBJCONV@ -f@TARGET_MODULE_FORMAT@ \ + @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 $tmpfile.bin -fi -if test x@platform@ != xemu; then - ./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@ @platform@ + rm -f $name.bin fi mv $tmpfile $outfile diff --git a/grub-core/genmoddep.awk b/grub-core/genmoddep.awk index 04c2863e5..9ffea7309 100644 --- a/grub-core/genmoddep.awk +++ b/grub-core/genmoddep.awk @@ -14,28 +14,26 @@ # Read symbols' info from stdin. BEGIN { error = 0 -} - -{ - 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++; + 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++; + } } - 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"; + else { + printf "error: %u: unrecognized input format\n", lineno; error++; + break; } } - else { - printf "error: %u: unrecognized input format\n", NR >"/dev/stderr"; - error++; - } } # Output the result. @@ -43,8 +41,6 @@ END { if (error >= 1) exit 1; - total_depcount = 0 - for (mod in modtab) { # Remove duplications. split(modtab[mod], depmods, " "); @@ -58,42 +54,14 @@ END { uniqmods[depmod] = 1; } modlist = "" - depcount[mod] = 0 for (depmod in uniqmods) { 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 9bc767532..d383f2640 100644 --- a/grub-core/gensyminfo.sh.in +++ b/grub-core/gensyminfo.sh.in @@ -1,4 +1,4 @@ -#! @BUILD_SHEBANG@ +#! /bin/sh set -e # Copyright (C) 2010 Free Software Foundation, Inc. @@ -22,16 +22,14 @@ module=$1 modname=`echo $module | sed -e 's@\.module.*$@@'` # Print all symbols defined by module -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" +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" else - @TARGET_NM@ -g --defined-only @TARGET_NMFLAGS_MINUS_P@ -p $module | \ + @NM@ -g --defined-only -P -p $module | \ sed "s@^\([^ ]*\).*@defined $modname \1@g" fi # Print all undefined symbols used by module -@TARGET_NM@ -u @TARGET_NMFLAGS_MINUS_P@ -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" +@NM@ -u -P -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" diff --git a/grub-core/gensymlist.sh b/grub-core/gensymlist.sh index 5beaabdd6..a13d7cc38 100644 --- a/grub-core/gensymlist.sh +++ b/grub-core/gensymlist.sh @@ -59,7 +59,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", (void *) \&\1, 0},/;p;}' \ + -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", \&\1, 0},/;p;}' \ | sort -u cat <device_width; + grub_free (glyph); + if (err) + return err; } -out: - for (ptr = visual; ptr < visual + visual_len; ptr++) - grub_unicode_destroy_glyph (ptr); grub_free (visual); - return err; + return GRUB_ERR_NONE; } /* Get the width in pixels of the specified UTF-8 string, when rendered in @@ -108,9 +102,8 @@ grub_font_get_string_width (grub_font_t font, const char *str) &glyph); width += grub_font_get_constructed_device_width (font, &glyph); - grub_unicode_destroy_glyph (&glyph); + grub_free (glyph.combining); } - grub_free (logical); return width; } diff --git a/grub-core/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c index 8a17dda2c..09e86213f 100644 --- a/grub-core/gfxmenu/gfxmenu.c +++ b/grub-core/gfxmenu/gfxmenu.c @@ -53,7 +53,6 @@ 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; @@ -63,35 +62,23 @@ 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"); - err = grub_video_get_info (&mode_info); - if (err) - return err; - 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); - } + err = grub_video_get_info (&mode_info); + if (err) + return err; - if (!cached_view || grub_strcmp (cached_view->theme_path, - full_theme_path ? : theme_path) != 0 + if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 || cached_view->screen.width != mode_info.width || cached_view->screen.height != mode_info.height) { - grub_gfxmenu_view_destroy (cached_view); + grub_free (cached_view); /* Create the view. */ - cached_view = grub_gfxmenu_view_new (full_theme_path ? : theme_path, - mode_info.width, + cached_view = grub_gfxmenu_view_new (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 37bab3fbb..38b15f96d 100644 --- a/grub-core/gfxmenu/gui_box.c +++ b/grub-core/gfxmenu/gui_box.c @@ -234,30 +234,14 @@ 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 a05491242..b3919c2d3 100644 --- a/grub-core/gfxmenu/gui_canvas.c +++ b/grub-core/gfxmenu/gui_canvas.c @@ -80,13 +80,9 @@ 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) { @@ -139,16 +135,9 @@ 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 (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); + if (grub_video_have_common_points (region, &r)) + comp->ops->paint (comp, region); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/gui_circular_progress.c b/grub-core/gfxmenu/gui_circular_progress.c index 7578bfbec..098ae1c92 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; - unsigned num_ticks; + int num_ticks; int start_angle; int ticks_disappear; char *theme_dir; @@ -138,53 +138,49 @@ circprog_paint (void *vself, const grub_video_rect_t *region) (height - center_height) / 2, 0, 0, center_width, center_height); - if (self->num_ticks) + 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) { - 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); - } + tick_begin = nticks; + tick_end = self->num_ticks - 1; } + 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); } @@ -227,36 +223,17 @@ circprog_set_state (void *vself, int visible, int start, 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_strtoul (value, 0, 10); + self->num_ticks = grub_strtol (value, 0, 10); } else if (grub_strcmp (name, "start_angle") == 0) { - self->start_angle = parse_angle (value); + self->start_angle = grub_strtol (value, 0, 10); } 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 6b2e976f1..29784ed2d 100644 --- a/grub-core/gfxmenu/gui_image.c +++ b/grub-core/gfxmenu/gui_image.c @@ -195,10 +195,7 @@ load_image (grub_gui_image_t self, const char *path) return grub_errno; if (self->bitmap && (self->bitmap != self->raw_bitmap)) - { - grub_video_bitmap_destroy (self->bitmap); - self->bitmap = 0; - } + grub_video_bitmap_destroy (self->bitmap); if (self->raw_bitmap) grub_video_bitmap_destroy (self->raw_bitmap); diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c index a4c817891..637578f77 100644 --- a/grub-core/gfxmenu/gui_label.c +++ b/grub-core/gfxmenu/gui_label.c @@ -23,7 +23,6 @@ #include #include #include -#include static const char *align_options[] = { @@ -154,8 +153,6 @@ 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))) @@ -237,8 +234,6 @@ 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 01477cdf2..1982d9a40 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -23,13 +23,6 @@ #include #include #include -#include - -enum scrollbar_slice_mode { - SCROLLBAR_SLICE_WEST, - SCROLLBAR_SLICE_CENTER, - SCROLLBAR_SLICE_EAST -}; struct grub_gui_list_impl { @@ -47,10 +40,9 @@ 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_inherit; + int selected_item_color_set; grub_video_rgba_color_t selected_item_color; int draw_scrollbar; @@ -59,25 +51,16 @@ 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; @@ -93,22 +76,14 @@ 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); } @@ -122,21 +97,9 @@ get_num_shown_items (list_impl_t self) 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 - - max_top_pad - max_bottom_pad - - box_top_pad - box_bottom_pad) / (item_height + item_vspace); + - box_top_pad - box_bottom_pad) / (item_height + item_vspace); } static int @@ -148,10 +111,6 @@ 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); @@ -159,8 +118,7 @@ check_boxes (list_impl_t self) self->need_to_recreate_boxes = 0; } - return (self->menu_box != 0 && self->selected_item_box != 0 - && self->item_box != 0); + return (self->menu_box != 0 && self->selected_item_box != 0); } static int @@ -179,34 +137,7 @@ check_scrollbar (list_impl_t self) self->need_to_recreate_scrollbar = 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; + return (self->scrollbar_frame != 0 && self->scrollbar_thumb != 0); } static const char * @@ -252,73 +183,36 @@ 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 scrollbar_width, int scrollbar_height) + int rightx, int topy, int 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)); - 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); + 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); } /* 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 || ! self->item_box) + if (! self->menu_box || ! self->selected_item_box) return; int boxpad = self->item_padding; @@ -327,26 +221,14 @@ 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 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; + int item_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 max_leftpad = grub_max (item_leftpad, sel_leftpad); - int max_toppad = grub_max (item_toppad, sel_toppad); - int item_top = 0; + int item_top = sel_toppad; int menu_index; int visible_index; struct grub_video_rect oviewport; @@ -358,92 +240,48 @@ draw_menu (list_impl_t self, int num_shown_items) 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) { - 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; + 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); } icon = get_item_icon (self, menu_index); if (icon != 0) grub_video_blit_bitmap (icon, GRUB_VIDEO_BLIT_BLEND, - max_leftpad, - item_top + icon_top_offset, + sel_leftpad, + item_top + (item_height - self->icon_height) / 2, 0, 0, self->icon_width, self->icon_height); const char *item_title = grub_menu_get_entry (self->view->menu, menu_index)->title; - - sviewport.y = item_top + top_pad; - sviewport.width = viewport_width; - grub_gui_set_viewport (&sviewport, &svpsave); + 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); grub_font_draw_string (item_title, font, - color, - 0, - text_top_offset); - grub_gui_restore_viewport (&svpsave); + grub_video_map_rgba_color (text_color), + sel_leftpad + self->icon_width + icon_text_space, + (item_top + (item_height - (ascent + descent)) + / 2 + ascent)); - item_top += text_box_height + item_vspace; + item_top += item_height + item_vspace; } grub_video_set_viewport (oviewport.x, oviewport.y, @@ -464,7 +302,7 @@ list_paint (void *vself, const grub_video_rect_t *region) check_boxes (self); - if (! self->menu_box || ! self->selected_item_box || ! self->item_box) + if (! self->menu_box || ! self->selected_item_box) return; grub_gui_set_viewport (&self->bounds, &vpsave); @@ -479,7 +317,6 @@ 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; @@ -490,65 +327,18 @@ 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) - { - 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); - } + 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); } grub_gui_restore_viewport (&vpsave); @@ -602,52 +392,21 @@ list_get_minimal_size (void *vself, unsigned *width, unsigned *height) unsigned width_s; grub_gfxmenu_box_t selbox = self->selected_item_box; - 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); - + int sel_toppad = selbox->get_top_pad (selbox); + *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 - + 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; - } + *width += 2 * boxpad + box_left_pad + box_right_pad; /* 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 - + max_top_pad + max_bottom_pad); + + box_top_pad + box_bottom_pad + sel_toppad); } else { @@ -663,48 +422,29 @@ 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 = self->item_font; - self->selected_item_font_inherit = 1; - } + self->selected_item_font = 0; else - { - self->selected_item_font = grub_font_get (value); - self->selected_item_font_inherit = 0; - } + self->selected_item_font = grub_font_get (value); } else if (grub_strcmp (name, "item_color") == 0) { - 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; - } + grub_video_parse_color (value, &self->item_color); } else if (grub_strcmp (name, "selected_item_color") == 0) { if (! value || grub_strcmp (value, "inherit") == 0) { - self->selected_item_color = self->item_color; - self->selected_item_color_inherit = 1; + self->selected_item_color_set = 0; } else { - grub_video_rgba_color_t color; - if (grub_video_parse_color (value, &color) + if (grub_video_parse_color (value, &self->selected_item_color) == GRUB_ERR_NONE) - { - self->selected_item_color = color; - self->selected_item_color_inherit = 0; - } + self->selected_item_color_set = 1; } } else if (grub_strcmp (name, "icon_width") == 0) @@ -747,33 +487,11 @@ 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, "item_pixmap_style") == 0) - { - self->need_to_recreate_boxes = 1; - 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 = value ? grub_strdup (value) : 0; - self->selected_item_box_pattern_inherit = 0; - } + self->need_to_recreate_boxes = 1; + grub_free (self->selected_item_box_pattern); + self->selected_item_box_pattern = value ? grub_strdup (value) : 0; } else if (grub_strcmp (name, "scrollbar_frame") == 0) { @@ -787,39 +505,10 @@ 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; @@ -852,16 +541,6 @@ 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, @@ -878,8 +557,7 @@ static struct grub_gui_component_ops list_comp_ops = static struct grub_gui_list_ops list_ops = { - .set_view_info = list_set_view_info, - .refresh_list = list_refresh_info + .set_view_info = list_set_view_info }; grub_gui_component_t @@ -908,10 +586,9 @@ grub_gui_list_new (void) self->item_icon_space = 4; self->item_spacing = 16; self->item_font = default_font; - self->selected_item_font_inherit = 1; /* Default to using the item_font. */ - self->selected_item_font = default_font; + self->selected_item_font = 0; /* Default to using the item_font. */ self->item_color = default_fg_color; - self->selected_item_color_inherit = 1; /* Default to using the item_color. */ + self->selected_item_color_set = 0; /* Default to using the item_color. */ self->selected_item_color = default_fg_color; self->draw_scrollbar = 1; @@ -920,24 +597,15 @@ 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 b128f0866..7b005f400 100644 --- a/grub-core/gfxmenu/gui_progress_bar.c +++ b/grub-core/gfxmenu/gui_progress_bar.c @@ -25,7 +25,6 @@ #include #include #include -#include struct grub_gui_progress_bar { @@ -52,7 +51,6 @@ 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; @@ -61,9 +59,6 @@ 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); } @@ -118,15 +113,9 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self) f.width + 2, f.height + 2); /* Bar background. */ - 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)); + int 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); @@ -150,47 +139,21 @@ 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); - - 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); - } + hl->draw (hl, bar_l_pad, bar_t_pad); } -#pragma GCC diagnostic ignored "-Wformat-nonliteral" - static void draw_text (grub_gui_progress_bar_t self) { @@ -216,12 +179,9 @@ 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) { @@ -280,40 +240,22 @@ static void progress_bar_get_minimal_size (void *vself, unsigned *width, unsigned *height) { - unsigned min_width = 0; - unsigned min_height = 0; + unsigned text_width = 0, text_height = 0; grub_gui_progress_bar_t self = vself; if (self->template) { - 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; + 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); } *width = 200; - if (*width < min_width) - *width = min_width; + if (*width < text_width) + *width = text_width; *height = 28; - if (*height < min_height) - *height = min_height; + if (*height < text_height) + *height = text_height; } static void @@ -384,10 +326,6 @@ 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; @@ -448,7 +386,6 @@ 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 ba1e1eab3..a9a415e31 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_calloc (components, sizeof (*path_array)); + char **path_array = grub_malloc (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 1894682ef..45e8f7dea 100644 --- a/grub-core/gfxmenu/icon_manager.c +++ b/grub-core/gfxmenu/icon_manager.c @@ -106,10 +106,8 @@ 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) - return; - if (mgr->theme_path == 0 || path == 0 - || grub_strcmp (mgr->theme_path, path) != 0) + 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); @@ -139,19 +137,23 @@ static struct grub_video_bitmap * try_loading_icon (grub_gfxmenu_icon_manager_t mgr, const char *dir, const char *class_name) { - char *path, *ptr; + char *path; + int l; path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + grub_strlen (icon_extension) + 3); if (! path) return 0; - 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'; + 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); struct grub_video_bitmap *raw_bitmap; grub_video_bitmap_load (&raw_bitmap, path); diff --git a/grub-core/lib/libgcrypt/mpi/powerpc64/distfiles b/grub-core/gfxmenu/model.c similarity index 100% rename from grub-core/lib/libgcrypt/mpi/powerpc64/distfiles rename to grub-core/gfxmenu/model.c diff --git a/grub-core/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c index eae83086b..f9c711d3e 100644 --- a/grub-core/gfxmenu/theme_loader.c +++ b/grub-core/gfxmenu/theme_loader.c @@ -30,10 +30,6 @@ #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. @@ -116,24 +112,6 @@ 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 @@ -165,6 +143,7 @@ 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) @@ -175,56 +154,20 @@ theme_set_string (grub_gfxmenu_view_t view, return grub_errno; } grub_free(path); - 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); + 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; } else if (! grub_strcmp ("desktop-color", name)) grub_video_parse_color (value, &view->desktop_color); @@ -235,52 +178,6 @@ 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); @@ -465,10 +362,10 @@ read_expression (struct parsebuf *p) } static grub_err_t -parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop) +parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop) { signed num; - const char *ptr; + char *ptr; int sig = 0; *abs = 0; *prop = 0; @@ -743,7 +640,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, GRUB_FILE_TYPE_THEME); + file = grub_file_open (theme_path); if (! file) { grub_free (p.theme_dir); @@ -774,8 +671,6 @@ 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 ad5e82b81..9023fd3c4 100644 --- a/grub-core/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -40,8 +40,7 @@ static void init_terminal (grub_gfxmenu_view_t view); -static void -init_background (grub_gfxmenu_view_t view); +static grub_video_rect_t term_rect; static grub_gfxmenu_view_t term_view; /* Create a new view object, loading the theme specified by THEME_PATH and @@ -59,28 +58,11 @@ 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); @@ -93,11 +75,7 @@ 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->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_image = 0; view->desktop_color = default_bg_color; view->terminal_box = grub_gfxmenu_create_box (0, 0); view->title_text = grub_strdup (_("GRUB Boot Menu")); @@ -127,15 +105,7 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view) { if (!view) return; - 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); + grub_video_bitmap_destroy (view->desktop_image); if (view->terminal_box) view->terminal_box->destroy (view->terminal_box); grub_free (view->terminal_font_name); @@ -151,9 +121,9 @@ static void redraw_background (grub_gfxmenu_view_t view, const grub_video_rect_t *bounds) { - if (view->scaled_desktop_image) + if (view->desktop_image) { - struct grub_video_bitmap *img = view->scaled_desktop_image; + struct grub_video_bitmap *img = view->desktop_image; grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE, bounds->x, bounds->y, bounds->x - view->screen.x, @@ -213,7 +183,6 @@ 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); } } @@ -226,7 +195,7 @@ grub_gfxmenu_print_timeout (int timeout, void *data) if (view->first_timeout == -1) view->first_timeout = timeout; - update_timeouts (1, -view->first_timeout, -timeout, 0); + update_timeouts (1, -(view->first_timeout + 1), -timeout, 0); redraw_timeouts (view); grub_video_swap_buffers (); if (view->double_repaint) @@ -267,27 +236,6 @@ 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) { @@ -318,15 +266,10 @@ void grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, const grub_video_rect_t *region) { - if (grub_video_have_common_points (&view->terminal_rect, region)) + if (grub_video_have_common_points (&term_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) @@ -334,9 +277,6 @@ 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 @@ -344,8 +284,6 @@ 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, @@ -356,18 +294,12 @@ 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_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); - grub_gfxmenu_view_redraw (view, &view->screen); - } - + grub_gfxmenu_view_redraw (view, &view->screen); } static void @@ -381,7 +313,6 @@ 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); } } @@ -418,167 +349,36 @@ grub_gfxmenu_draw_terminal_box (void) term_box = term_view->terminal_box; if (!term_box) return; - - 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->set_content_size (term_box, term_rect.width, + term_rect.height); term_box->draw (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; + term_rect.x - term_box->get_left_pad (term_box), + term_rect.y - term_box->get_top_pad (term_box)); } static void init_terminal (grub_gfxmenu_view_t view) { - grub_font_t terminal_font; + term_rect.width = view->screen.width * 7 / 10; + term_rect.height = view->screen.height * 7 / 10; - 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_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; 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, - 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_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_decorator_hook = grub_gfxmenu_draw_terminal_box; } -static void -init_background (grub_gfxmenu_view_t view) -{ - if (view->scaled_desktop_image) - return; - - struct grub_video_bitmap *scaled_bitmap; - 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 470597ded..18e2ef469 100644 --- a/grub-core/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -80,25 +80,9 @@ draw (grub_gfxmenu_box_t self, int x, int y) { int height_n; int width_w; - int tmp; - /* 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; + height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); + width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); /* Draw sides. */ blit (self, BOX_PIXMAP_N, x + width_w, y); @@ -303,10 +287,10 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix, box->content_height = 0; box->raw_pixmaps = (struct grub_video_bitmap **) - grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *)); + grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); box->scaled_pixmaps = (struct grub_video_bitmap **) - grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *)); + grub_malloc (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 index 78aa1e64e..6739a6f1c 100644 --- a/grub-core/gmodule.pl.in +++ b/grub-core/gmodule.pl.in @@ -23,7 +23,7 @@ while (<>) { } print " -s $2 $sections{$1}" - if ($sections{$1} ne '0x0' and $sections{$1} ne ''); + if ($sections{$1} ne '0x0'); }; close (READELF); print "\n"; diff --git a/grub-core/gnulib/Makefile.am b/grub-core/gnulib/Makefile.am new file mode 100644 index 000000000..fb1525f00 --- /dev/null +++ b/grub-core/gnulib/Makefile.am @@ -0,0 +1,1359 @@ +## 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 new file mode 100644 index 000000000..75afdb960 --- /dev/null +++ b/grub-core/gnulib/alloca.c @@ -0,0 +1,489 @@ +/* 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 new file mode 100644 index 000000000..44f20b7a1 --- /dev/null +++ b/grub-core/gnulib/alloca.in.h @@ -0,0 +1,56 @@ +/* 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 new file mode 100644 index 000000000..95feabb86 --- /dev/null +++ b/grub-core/gnulib/argp-ba.c @@ -0,0 +1,34 @@ +/* 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 new file mode 100644 index 000000000..115a8cd5d --- /dev/null +++ b/grub-core/gnulib/argp-eexst.c @@ -0,0 +1,30 @@ +/* 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 new file mode 100644 index 000000000..248a09a3b --- /dev/null +++ b/grub-core/gnulib/argp-fmtstream.c @@ -0,0 +1,489 @@ +/* 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 new file mode 100644 index 000000000..8a67817b1 --- /dev/null +++ b/grub-core/gnulib/argp-fmtstream.h @@ -0,0 +1,357 @@ +/* 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 new file mode 100644 index 000000000..2c683f914 --- /dev/null +++ b/grub-core/gnulib/argp-fs-xinl.c @@ -0,0 +1,42 @@ +/* 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 new file mode 100644 index 000000000..c82e38e75 --- /dev/null +++ b/grub-core/gnulib/argp-help.c @@ -0,0 +1,1951 @@ +/* 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 new file mode 100644 index 000000000..24581a626 --- /dev/null +++ b/grub-core/gnulib/argp-namefrob.h @@ -0,0 +1,157 @@ +/* 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 new file mode 100644 index 000000000..9c054653c --- /dev/null +++ b/grub-core/gnulib/argp-parse.c @@ -0,0 +1,952 @@ +/* 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 new file mode 100644 index 000000000..eda4d958e --- /dev/null +++ b/grub-core/gnulib/argp-pin.c @@ -0,0 +1,27 @@ +/* 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 new file mode 100644 index 000000000..e3227d322 --- /dev/null +++ b/grub-core/gnulib/argp-pv.c @@ -0,0 +1,34 @@ +/* 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 new file mode 100644 index 000000000..fb98fc21c --- /dev/null +++ b/grub-core/gnulib/argp-pvh.c @@ -0,0 +1,31 @@ +/* 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 new file mode 100644 index 000000000..6e7e20bba --- /dev/null +++ b/grub-core/gnulib/argp-xinl.c @@ -0,0 +1,42 @@ +/* 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 new file mode 100644 index 000000000..3667224a9 --- /dev/null +++ b/grub-core/gnulib/argp.h @@ -0,0 +1,645 @@ +/* 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 new file mode 100644 index 000000000..3bd2229d5 --- /dev/null +++ b/grub-core/gnulib/asnprintf.c @@ -0,0 +1,35 @@ +/* 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 new file mode 100644 index 000000000..a35ff01c2 --- /dev/null +++ b/grub-core/gnulib/basename-lgpl.c @@ -0,0 +1,75 @@ +/* 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 new file mode 100644 index 000000000..8744602aa --- /dev/null +++ b/grub-core/gnulib/btowc.c @@ -0,0 +1,39 @@ +/* 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 new file mode 100644 index 000000000..aa7d00dba --- /dev/null +++ b/grub-core/gnulib/config.charset @@ -0,0 +1,683 @@ +#! /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 new file mode 100644 index 000000000..d4506e060 --- /dev/null +++ b/grub-core/gnulib/dirname-lgpl.c @@ -0,0 +1,86 @@ +/* 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 new file mode 100644 index 000000000..fb19508f7 --- /dev/null +++ b/grub-core/gnulib/dirname.h @@ -0,0 +1,74 @@ +/* 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 new file mode 100644 index 000000000..140e5d134 --- /dev/null +++ b/grub-core/gnulib/errno.in.h @@ -0,0 +1,160 @@ +/* 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 new file mode 100644 index 000000000..ed9dba0d2 --- /dev/null +++ b/grub-core/gnulib/error.c @@ -0,0 +1,394 @@ +/* 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 new file mode 100644 index 000000000..9deef02d2 --- /dev/null +++ b/grub-core/gnulib/error.h @@ -0,0 +1,65 @@ +/* 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 new file mode 100644 index 000000000..b55e5e6de --- /dev/null +++ b/grub-core/gnulib/float+.h @@ -0,0 +1,148 @@ +/* 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 new file mode 100644 index 000000000..caf822f1d --- /dev/null +++ b/grub-core/gnulib/float.in.h @@ -0,0 +1,62 @@ +/* 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 new file mode 100644 index 000000000..d73e47dae --- /dev/null +++ b/grub-core/gnulib/fnmatch.c @@ -0,0 +1,354 @@ +/* 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 new file mode 100644 index 000000000..8caab1959 --- /dev/null +++ b/grub-core/gnulib/fnmatch.in.h @@ -0,0 +1,68 @@ +/* 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 new file mode 100644 index 000000000..741c993ef --- /dev/null +++ b/grub-core/gnulib/fnmatch_loop.c @@ -0,0 +1,1215 @@ +/* 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 new file mode 100644 index 000000000..66d07b9ae --- /dev/null +++ b/grub-core/gnulib/getdelim.c @@ -0,0 +1,137 @@ +/* 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 new file mode 100644 index 000000000..30c076e87 --- /dev/null +++ b/grub-core/gnulib/getline.c @@ -0,0 +1,29 @@ +/* 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 new file mode 100644 index 000000000..3791f1293 --- /dev/null +++ b/grub-core/gnulib/getopt.c @@ -0,0 +1,1192 @@ +/* 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 new file mode 100644 index 000000000..57a8e8992 --- /dev/null +++ b/grub-core/gnulib/getopt.in.h @@ -0,0 +1,249 @@ +/* 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 new file mode 100644 index 000000000..046d69f94 --- /dev/null +++ b/grub-core/gnulib/getopt1.c @@ -0,0 +1,170 @@ +/* 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 new file mode 100644 index 000000000..980b7507f --- /dev/null +++ b/grub-core/gnulib/getopt_int.h @@ -0,0 +1,135 @@ +/* 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 new file mode 100644 index 000000000..881ae3304 --- /dev/null +++ b/grub-core/gnulib/gettext.h @@ -0,0 +1,280 @@ +/* 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 new file mode 100644 index 000000000..46f4d47d7 --- /dev/null +++ b/grub-core/gnulib/intprops.h @@ -0,0 +1,83 @@ +/* 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 new file mode 100644 index 000000000..3a92647b9 --- /dev/null +++ b/grub-core/gnulib/langinfo.in.h @@ -0,0 +1,173 @@ +/* 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 new file mode 100644 index 000000000..fa2207fe1 --- /dev/null +++ b/grub-core/gnulib/localcharset.c @@ -0,0 +1,548 @@ +/* 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 new file mode 100644 index 000000000..899b3bae7 --- /dev/null +++ b/grub-core/gnulib/localcharset.h @@ -0,0 +1,41 @@ +/* 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 new file mode 100644 index 000000000..4fa38ee41 --- /dev/null +++ b/grub-core/gnulib/malloc.c @@ -0,0 +1,60 @@ +/* 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 new file mode 100644 index 000000000..5c2650e95 --- /dev/null +++ b/grub-core/gnulib/mbrtowc.c @@ -0,0 +1,386 @@ +/* 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 new file mode 100644 index 000000000..066ddfe5b --- /dev/null +++ b/grub-core/gnulib/mbsinit.c @@ -0,0 +1,47 @@ +/* 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 new file mode 100644 index 000000000..35045f657 --- /dev/null +++ b/grub-core/gnulib/mbsrtowcs-state.c @@ -0,0 +1,37 @@ +/* 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 new file mode 100644 index 000000000..c577f36f2 --- /dev/null +++ b/grub-core/gnulib/mbsrtowcs.c @@ -0,0 +1,136 @@ +/* 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 new file mode 100644 index 000000000..6c2b2d6c7 --- /dev/null +++ b/grub-core/gnulib/memchr.c @@ -0,0 +1,172 @@ +/* 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 new file mode 100644 index 000000000..60f247e10 --- /dev/null +++ b/grub-core/gnulib/memchr.valgrind @@ -0,0 +1,14 @@ +# 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 new file mode 100644 index 000000000..b624d69fd --- /dev/null +++ b/grub-core/gnulib/mempcpy.c @@ -0,0 +1,29 @@ +/* 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 new file mode 100644 index 000000000..a3d0d11eb --- /dev/null +++ b/grub-core/gnulib/nl_langinfo.c @@ -0,0 +1,270 @@ +/* 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 new file mode 100644 index 000000000..46c03a21e --- /dev/null +++ b/grub-core/gnulib/printf-args.c @@ -0,0 +1,188 @@ +/* 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 new file mode 100644 index 000000000..2536ebafd --- /dev/null +++ b/grub-core/gnulib/printf-args.h @@ -0,0 +1,155 @@ +/* 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 new file mode 100644 index 000000000..f612beb5b --- /dev/null +++ b/grub-core/gnulib/printf-parse.c @@ -0,0 +1,627 @@ +/* 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 new file mode 100644 index 000000000..0f2b70820 --- /dev/null +++ b/grub-core/gnulib/printf-parse.h @@ -0,0 +1,180 @@ +/* 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 new file mode 100644 index 000000000..1415e6a55 --- /dev/null +++ b/grub-core/gnulib/progname.c @@ -0,0 +1,92 @@ +/* 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 new file mode 100644 index 000000000..5ba303bd0 --- /dev/null +++ b/grub-core/gnulib/progname.h @@ -0,0 +1,62 @@ +/* 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 new file mode 100644 index 000000000..0a88777d9 --- /dev/null +++ b/grub-core/gnulib/rawmemchr.c @@ -0,0 +1,136 @@ +/* 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 new file mode 100644 index 000000000..636392368 --- /dev/null +++ b/grub-core/gnulib/rawmemchr.valgrind @@ -0,0 +1,12 @@ +# 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 new file mode 100644 index 000000000..053208f37 --- /dev/null +++ b/grub-core/gnulib/realloc.c @@ -0,0 +1,91 @@ +/* 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 new file mode 100644 index 000000000..dbb61df3d --- /dev/null +++ b/grub-core/gnulib/ref-add.sin @@ -0,0 +1,30 @@ +# 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 new file mode 100644 index 000000000..4c31a6eaf --- /dev/null +++ b/grub-core/gnulib/ref-del.sin @@ -0,0 +1,25 @@ +# 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 new file mode 100644 index 000000000..ddea3fb65 --- /dev/null +++ b/grub-core/gnulib/regcomp.c @@ -0,0 +1,3877 @@ +/* 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 new file mode 100644 index 000000000..ba0eebee7 --- /dev/null +++ b/grub-core/gnulib/regex.c @@ -0,0 +1,72 @@ +/* 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 new file mode 100644 index 000000000..1c139d680 --- /dev/null +++ b/grub-core/gnulib/regex.h @@ -0,0 +1,679 @@ +/* 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 new file mode 100644 index 000000000..98b8d5d21 --- /dev/null +++ b/grub-core/gnulib/regex_internal.c @@ -0,0 +1,1742 @@ +/* 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 new file mode 100644 index 000000000..e5b6679d1 --- /dev/null +++ b/grub-core/gnulib/regex_internal.h @@ -0,0 +1,869 @@ +/* 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 new file mode 100644 index 000000000..dc449ce52 --- /dev/null +++ b/grub-core/gnulib/regexec.c @@ -0,0 +1,4416 @@ +/* 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 new file mode 100644 index 000000000..56d5a9b1c --- /dev/null +++ b/grub-core/gnulib/size_max.h @@ -0,0 +1,31 @@ +/* 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 new file mode 100644 index 000000000..213e5bd29 --- /dev/null +++ b/grub-core/gnulib/sleep.c @@ -0,0 +1,75 @@ +/* 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 new file mode 100644 index 000000000..574c281a8 --- /dev/null +++ b/grub-core/gnulib/stdbool.in.h @@ -0,0 +1,122 @@ +/* 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 new file mode 100644 index 000000000..08778a233 --- /dev/null +++ b/grub-core/gnulib/stddef.in.h @@ -0,0 +1,86 @@ +/* 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 new file mode 100644 index 000000000..5da5f1788 --- /dev/null +++ b/grub-core/gnulib/stdint.in.h @@ -0,0 +1,568 @@ +/* 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 new file mode 100644 index 000000000..a6a0eb143 --- /dev/null +++ b/grub-core/gnulib/stdio-write.c @@ -0,0 +1,148 @@ +/* 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 new file mode 100644 index 000000000..80b9dbfda --- /dev/null +++ b/grub-core/gnulib/stdio.in.h @@ -0,0 +1,1071 @@ +/* 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 new file mode 100644 index 000000000..f4309ed73 --- /dev/null +++ b/grub-core/gnulib/stdlib.in.h @@ -0,0 +1,715 @@ +/* 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 new file mode 100644 index 000000000..612c80fdc --- /dev/null +++ b/grub-core/gnulib/strcasecmp.c @@ -0,0 +1,63 @@ +/* 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 new file mode 100644 index 000000000..f834d3434 --- /dev/null +++ b/grub-core/gnulib/strchrnul.c @@ -0,0 +1,142 @@ +/* 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 new file mode 100644 index 000000000..b14fa1304 --- /dev/null +++ b/grub-core/gnulib/strchrnul.valgrind @@ -0,0 +1,12 @@ +# 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 new file mode 100644 index 000000000..aa65bb8e1 --- /dev/null +++ b/grub-core/gnulib/streq.h @@ -0,0 +1,176 @@ +/* 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 new file mode 100644 index 000000000..46153abf5 --- /dev/null +++ b/grub-core/gnulib/strerror.c @@ -0,0 +1,350 @@ +/* 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 new file mode 100644 index 000000000..49c711d8f --- /dev/null +++ b/grub-core/gnulib/string.in.h @@ -0,0 +1,945 @@ +/* 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 new file mode 100644 index 000000000..c726a1623 --- /dev/null +++ b/grub-core/gnulib/strings.in.h @@ -0,0 +1,93 @@ +/* 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 new file mode 100644 index 000000000..3a5996fd9 --- /dev/null +++ b/grub-core/gnulib/stripslash.c @@ -0,0 +1,45 @@ +/* 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 new file mode 100644 index 000000000..8c806a6b0 --- /dev/null +++ b/grub-core/gnulib/strncasecmp.c @@ -0,0 +1,63 @@ +/* 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 new file mode 100644 index 000000000..3de3dbc5a --- /dev/null +++ b/grub-core/gnulib/strndup.c @@ -0,0 +1,37 @@ +/* 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 new file mode 100644 index 000000000..f1ec356dc --- /dev/null +++ b/grub-core/gnulib/strnlen.c @@ -0,0 +1,31 @@ +/* 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 new file mode 100644 index 000000000..b8cd2bff0 --- /dev/null +++ b/grub-core/gnulib/strnlen1.c @@ -0,0 +1,35 @@ +/* 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 new file mode 100644 index 000000000..dfaf62dcb --- /dev/null +++ b/grub-core/gnulib/strnlen1.h @@ -0,0 +1,39 @@ +/* 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 new file mode 100644 index 000000000..009fa219b --- /dev/null +++ b/grub-core/gnulib/sys_wait.in.h @@ -0,0 +1,106 @@ +/* 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 new file mode 100644 index 000000000..45255dfa5 --- /dev/null +++ b/grub-core/gnulib/sysexits.in.h @@ -0,0 +1,71 @@ +/* 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 new file mode 100644 index 000000000..26a4cbd6a --- /dev/null +++ b/grub-core/gnulib/unistd.in.h @@ -0,0 +1,1326 @@ +/* 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 new file mode 100644 index 000000000..e618901ba --- /dev/null +++ b/grub-core/gnulib/vasnprintf.c @@ -0,0 +1,5567 @@ +/* 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 new file mode 100644 index 000000000..a689bad25 --- /dev/null +++ b/grub-core/gnulib/vasnprintf.h @@ -0,0 +1,80 @@ +/* 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 new file mode 100644 index 000000000..4ad780c8f --- /dev/null +++ b/grub-core/gnulib/verify.h @@ -0,0 +1,163 @@ +/* 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 new file mode 100644 index 000000000..d447cc2d5 --- /dev/null +++ b/grub-core/gnulib/vsnprintf.c @@ -0,0 +1,71 @@ +/* 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 new file mode 100644 index 000000000..88d47dbc0 --- /dev/null +++ b/grub-core/gnulib/wchar.in.h @@ -0,0 +1,428 @@ +/* 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 new file mode 100644 index 000000000..e7345f698 --- /dev/null +++ b/grub-core/gnulib/wcrtomb.c @@ -0,0 +1,53 @@ +/* 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 new file mode 100644 index 000000000..12c8975fe --- /dev/null +++ b/grub-core/gnulib/wctype.in.h @@ -0,0 +1,392 @@ +/* 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 new file mode 100644 index 000000000..fbd63290d --- /dev/null +++ b/grub-core/gnulib/xsize.h @@ -0,0 +1,108 @@ +/* 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 a458c3aca..2a315e2d8 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, grub_size_t size) +grub_bufio_open (grub_file_t io, int size) { grub_file_t file; grub_bufio_t bufio = 0; - file = (grub_file_t) grub_zalloc (sizeof (*file)); + file = (grub_file_t) grub_malloc (sizeof (*file)); if (! file) return 0; @@ -57,18 +57,11 @@ grub_bufio_open (grub_file_t io, grub_size_t size) else if (size > GRUB_BUFIO_MAX_SIZE) size = GRUB_BUFIO_MAX_SIZE; - if (size > io->size) + if ((size < 0) || ((unsigned) size > io->size)) size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE : io->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); + bufio = grub_malloc (sizeof (struct grub_bufio) + size); if (! bufio) { grub_free (file); @@ -77,10 +70,14 @@ grub_bufio_open (grub_file_t io, grub_size_t 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; @@ -88,11 +85,11 @@ grub_bufio_open (grub_file_t io, grub_size_t size) } grub_file_t -grub_buffile_open (const char *name, enum grub_file_type type, grub_size_t size) +grub_buffile_open (const char *name, int size) { grub_file_t io, file; - io = grub_file_open (name, type); + io = grub_file_open (name); if (! io) return 0; @@ -205,10 +202,10 @@ grub_bufio_close (grub_file_t file) static struct grub_fs grub_bufio_fs = { .name = "bufio", - .fs_dir = 0, - .fs_open = 0, - .fs_read = grub_bufio_read, - .fs_close = grub_bufio_close, - .fs_label = 0, + .dir = 0, + .open = 0, + .read = grub_bufio_read, + .close = grub_bufio_close, + .label = 0, .next = 0 }; diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 43d98a7bd..83c0b64cb 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -43,7 +43,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -95,14 +94,6 @@ 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. */ @@ -149,24 +140,24 @@ eat_field (grub_file_t file, int len) #define OLD_GZIP_MAGIC grub_le_to_cpu16 (0x9E1F) /* Compression methods (see algorithm.doc) */ -#define GRUB_GZ_STORED 0 -#define GRUB_GZ_COMPRESSED 1 -#define GRUB_GZ_PACKED 2 -#define GRUB_GZ_LZHED 3 +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +#define LZHED 3 /* methods 4 to 7 reserved */ -#define GRUB_GZ_DEFLATED 8 -#define GRUB_GZ_MAX_METHODS 9 +#define DEFLATED 8 +#define MAX_METHODS 9 /* gzip flag byte */ -#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 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_UNSUPPORTED_FLAGS (GRUB_GZ_CONTINUATION | GRUB_GZ_ENCRYPTED | GRUB_GZ_RESERVED) +#define UNSUPPORTED_FLAGS (CONTINUATION | ENCRYPTED | RESERVED) /* inflate block codes */ #define INFLATE_STORED 0 @@ -189,7 +180,7 @@ test_gzip_header (grub_file_t file) grub_uint8_t os_type; } hdr; grub_uint16_t extra_len; - grub_uint32_t crc32; + grub_uint32_t orig_len; grub_gzio_t gzio = file->data; if (grub_file_tell (gzio->file) != 0) @@ -210,29 +201,26 @@ 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 != GRUB_GZ_DEFLATED - || (hdr.flags & GRUB_GZ_UNSUPPORTED_FLAGS) - || ((hdr.flags & GRUB_GZ_EXTRA_FIELD) + if (hdr.method != DEFLATED + || (hdr.flags & UNSUPPORTED_FLAGS) + || ((hdr.flags & EXTRA_FIELD) && (grub_file_read (gzio->file, &extra_len, 2) != 2 || eat_field (gzio->file, grub_le_to_cpu16 (extra_len)))) - || ((hdr.flags & GRUB_GZ_ORIG_NAME) && eat_field (gzio->file, -1)) - || ((hdr.flags & GRUB_GZ_COMMENT) && eat_field (gzio->file, -1))) + || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1)) + || ((hdr.flags & 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) - 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) + grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4); + if (grub_file_read (gzio->file, &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 (gzio->orig_len); + file->size = grub_le_to_cpu32 (orig_len); } initialize_tables (gzio); @@ -375,6 +363,8 @@ 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) @@ -554,7 +544,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_calloc (z + 1, sizeof (struct huft)); + q = (struct huft *) grub_malloc ((z + 1) * sizeof (struct huft)); if (! q) { if (h) @@ -1105,25 +1095,9 @@ inflate_window (grub_gzio_t gzio) } } - gzio->saved_offset += gzio->wp; + gzio->saved_offset += WSIZE; - 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); - } - } + /* XXX do CRC calculation here! */ } @@ -1144,11 +1118,6 @@ 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); } @@ -1156,15 +1125,12 @@ initialize_tables (grub_gzio_t gzio) 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. */ static grub_file_t -grub_gzio_open (grub_file_t io, enum grub_file_type type) +grub_gzio_open (grub_file_t io) { grub_file_t file; grub_gzio_t gzio = 0; - if (type & GRUB_FILE_TYPE_NO_DECOMPRESS) - return io; - - file = (grub_file_t) grub_zalloc (sizeof (*file)); + file = (grub_file_t) grub_malloc (sizeof (*file)); if (! file) return 0; @@ -1177,18 +1143,16 @@ grub_gzio_open (grub_file_t io, enum grub_file_type type) 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); @@ -1199,19 +1163,6 @@ grub_gzio_open (grub_file_t io, enum grub_file_type type) 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) { @@ -1221,7 +1172,7 @@ test_zlib_header (grub_gzio_t gzio) flg = get_byte (gzio); /* Check that compression method is DEFLATE. */ - if ((cmf & 0xf) != GRUB_GZ_DEFLATED) + if ((cmf & 0xf) != DEFLATED) { /* TRANSLATORS: It's about given file having some strange format, not complete lack of gzip support. */ @@ -1229,10 +1180,7 @@ test_zlib_header (grub_gzio_t gzio) return 0; } - /* 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) + if ((cmf * 256 + flg) % 31) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format")); return 0; @@ -1273,14 +1221,7 @@ grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset, register char *srcaddr; while (offset >= gzio->saved_offset) - { - inflate_window (gzio); - if (gzio->wp == 0) - goto out; - } - - if (gzio->wp == 0) - goto out; + inflate_window (gzio); srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide); size = gzio->saved_offset - offset; @@ -1295,7 +1236,6 @@ grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset, offset += size; } - out: if (grub_errno != GRUB_ERR_NONE) ret = -1; @@ -1305,15 +1245,7 @@ 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) { - 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; + return grub_gzio_read_real (file->data, file->offset, buf, len); } /* Release everything, including the underlying file object. */ @@ -1325,12 +1257,10 @@ 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; } @@ -1362,38 +1292,16 @@ 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", - .fs_dir = 0, - .fs_open = 0, - .fs_read = grub_gzio_read, - .fs_close = grub_gzio_close, - .fs_label = 0, + .dir = 0, + .open = 0, + .read = grub_gzio_read, + .close = grub_gzio_close, + .label = 0, .next = 0 }; diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index 30144857d..77291d001 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -166,17 +166,15 @@ read_block_data (struct grub_lzopio *lzopio) if (lzopio->ccheck_fun) { - grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8]; - 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); + lzopio->ccheck_fun->init (context); + lzopio->ccheck_fun->write (context, lzopio->block.cdata, + lzopio->block.csize); + lzopio->ccheck_fun->final (context); if (grub_memcmp - (computed_hash, &lzopio->block.ccheck, + (lzopio->ccheck_fun->read (context), &lzopio->block.ccheck, sizeof (lzopio->block.ccheck)) != 0) return -1; } @@ -214,17 +212,15 @@ uncompress_block (struct grub_lzopio *lzopio) if (lzopio->ucheck_fun) { - grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint64_t context[(lzopio->ucheck_fun->contextsize + 7) / 8]; - 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); + lzopio->ucheck_fun->init (context); + lzopio->ucheck_fun->write (context, lzopio->block.udata, + lzopio->block.usize); + lzopio->ucheck_fun->final (context); if (grub_memcmp - (computed_hash, &lzopio->block.ucheck, + (lzopio->ucheck_fun->read (context), &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != 0) return -1; } @@ -290,7 +286,7 @@ struct lzop_header grub_uint32_t mtime_lo; grub_uint32_t mtime_hi; grub_uint8_t name_len; -} GRUB_PACKED; +} __attribute__ ((packed)); static int test_header (grub_file_t file) @@ -384,8 +380,12 @@ test_header (grub_file_t file) sizeof (checksum)) goto CORRUPTED; - if (hcheck && grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) - goto CORRUPTED; + if (hcheck) + { + checksum = checksum; + if (grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) + goto CORRUPTED; + } lzopio->start_block_off = grub_file_tell (lzopio->file); @@ -403,18 +403,17 @@ 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, enum grub_file_type type) +grub_lzopio_open (grub_file_t io) { 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; @@ -429,7 +428,9 @@ grub_lzopio_open (grub_file_t io, enum grub_file_type type) 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; @@ -525,17 +526,16 @@ 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", - .fs_dir = 0, - .fs_open = 0, - .fs_read = grub_lzopio_read, - .fs_close = grub_lzopio_close, - .fs_label = 0, + .dir = 0, + .open = 0, + .read = grub_lzopio_read, + .close = grub_lzopio_close, + .label = 0, .next = 0 }; diff --git a/grub-core/io/offset.c b/grub-core/io/offset.c deleted file mode 100644 index 7e2db4a3a..000000000 --- a/grub-core/io/offset.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 516c4dfca..ae30e6f80 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_bytes; + grub_ssize_t read; grub_size_t dec; - read_bytes = grub_file_read (file, buf, VLI_MAX_DIGITS); - if (read_bytes < 0) + read = grub_file_read (file, buf, VLI_MAX_DIGITS); + if (read < 0) return -1; - dec = decode_vli (buf, read_bytes, num); - grub_file_seek (file, file->offset - (read_bytes - dec)); + dec = decode_vli (buf, read, num); + grub_file_seek (file, file->offset - (read - dec)); return dec; } @@ -169,14 +169,11 @@ ERROR: } static grub_file_t -grub_xzio_open (grub_file_t io, enum grub_file_type type) +grub_xzio_open (grub_file_t io) { 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; @@ -189,9 +186,12 @@ grub_xzio_open (grub_file_t io, enum grub_file_type type) } 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,7 +210,10 @@ grub_xzio_open (grub_file_t io, enum grub_file_type type) } 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. */ @@ -321,17 +324,16 @@ 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", - .fs_dir = 0, - .fs_open = 0, - .fs_read = grub_xzio_read, - .fs_close = grub_xzio_close, - .fs_label = 0, + .dir = 0, + .open = 0, + .read = grub_xzio_read, + .close = grub_xzio_close, + .label = 0, .next = 0 }; diff --git a/grub-core/kern/acpi.c b/grub-core/kern/acpi.c deleted file mode 100644 index 5746ac00c..000000000 --- a/grub-core/kern/acpi.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 - -/* 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; - 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_uint32_t); - for (; s; s--, ptr++) - { - struct grub_acpi_table_header *tbl; -#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; -} - -struct grub_acpi_fadt * -grub_acpi_find_fadt (void) -{ - struct grub_acpi_fadt *fadt = 0; - struct grub_acpi_rsdp_v10 *rsdpv1; - struct grub_acpi_rsdp_v20 *rsdpv2; - rsdpv1 = grub_machine_acpi_get_rsdpv1 (); - if (rsdpv1) - fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *) - (grub_addr_t) rsdpv1->rsdt_addr, - GRUB_ACPI_FADT_SIGNATURE); - if (fadt) - return fadt; - rsdpv2 = grub_machine_acpi_get_rsdpv2 (); - if (rsdpv2) - fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *) - (grub_addr_t) rsdpv2->rsdpv1.rsdt_addr, - GRUB_ACPI_FADT_SIGNATURE); - if (fadt) - return fadt; - if (rsdpv2 -#if GRUB_CPU_SIZEOF_VOID_P != 8 - && !(rsdpv2->xsdt_addr >> 32) -#endif - ) - fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *) - (grub_addr_t) rsdpv2->xsdt_addr, - GRUB_ACPI_FADT_SIGNATURE); - if (fadt) - return fadt; - return 0; -} diff --git a/grub-core/kern/arm/cache.S b/grub-core/kern/arm/cache.S deleted file mode 100644 index 354a069fe..000000000 --- a/grub-core/kern/arm/cache.S +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 deleted file mode 100644 index 6c75193e4..000000000 --- a/grub-core/kern/arm/cache.c +++ /dev/null @@ -1,311 +0,0 @@ -#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 deleted file mode 100644 index dfaded0eb..000000000 --- a/grub-core/kern/arm/cache_armv6.S +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 deleted file mode 100644 index 5ae76a3d8..000000000 --- a/grub-core/kern/arm/cache_armv7.S +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 deleted file mode 100644 index 645b42f50..000000000 --- a/grub-core/kern/arm/compiler-rt.S +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 deleted file mode 100644 index 8a655bb5c..000000000 --- a/grub-core/kern/arm/coreboot/cbtable.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 deleted file mode 100644 index a1104526c..000000000 --- a/grub-core/kern/arm/coreboot/coreboot.S +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 deleted file mode 100644 index 2c2a62789..000000000 --- a/grub-core/kern/arm/coreboot/dma.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 deleted file mode 100644 index 8d8c5b829..000000000 --- a/grub-core/kern/arm/coreboot/init.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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 deleted file mode 100644 index d97b844f8..000000000 --- a/grub-core/kern/arm/coreboot/timer.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 deleted file mode 100644 index eab9d17ff..000000000 --- a/grub-core/kern/arm/dl.c +++ /dev/null @@ -1,280 +0,0 @@ -/* 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 deleted file mode 100644 index 21d77f763..000000000 --- a/grub-core/kern/arm/dl_helper.c +++ /dev/null @@ -1,245 +0,0 @@ -/* 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 deleted file mode 100644 index 40c3b467f..000000000 --- a/grub-core/kern/arm/efi/init.c +++ /dev/null @@ -1,77 +0,0 @@ -/* 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 -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; - - efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, - GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt); - efi_call_3 (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; - - efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); - efi_call_1 (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 deleted file mode 100644 index 9f8265315..000000000 --- a/grub-core/kern/arm/efi/startup.S +++ /dev/null @@ -1,36 +0,0 @@ -/* - * (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 deleted file mode 100644 index 3946fe8e1..000000000 --- a/grub-core/kern/arm/startup.S +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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 deleted file mode 100644 index 2a6aa3fdd..000000000 --- a/grub-core/kern/arm/uboot/init.c +++ /dev/null @@ -1,70 +0,0 @@ -/* 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 deleted file mode 100644 index d128775f1..000000000 --- a/grub-core/kern/arm/uboot/uboot.S +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 deleted file mode 100644 index b84383da1..000000000 --- a/grub-core/kern/arm64/cache.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 deleted file mode 100644 index e064f7ece..000000000 --- a/grub-core/kern/arm64/cache_flush.S +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 deleted file mode 100644 index fb0337319..000000000 --- a/grub-core/kern/arm64/dl.c +++ /dev/null @@ -1,193 +0,0 @@ -/* 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: - 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/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c deleted file mode 100644 index e00c198db..000000000 --- a/grub-core/kern/arm64/dl_helper.c +++ /dev/null @@ -1,134 +0,0 @@ -/* 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%llx\n", - place, offset > 0 ? '+' : '-', - offset < 0 ? (long long) -(unsigned long long) 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 deleted file mode 100644 index 5010caefd..000000000 --- a/grub-core/kern/arm64/efi/init.c +++ /dev/null @@ -1,63 +0,0 @@ -/* 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 deleted file mode 100644 index 666a7ee3c..000000000 --- a/grub-core/kern/arm64/efi/startup.S +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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/compiler-rt.c b/grub-core/kern/compiler-rt.c deleted file mode 100644 index a464200c6..000000000 --- a/grub-core/kern/compiler-rt.c +++ /dev/null @@ -1,464 +0,0 @@ -/* 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 (__clang__) && !defined(GRUB_EMBED_DECOMPRESSOR) -/* clang emits references to abort(). */ -void __attribute__ ((noreturn)) -abort (void) -{ - grub_fatal ("compiler abort"); -} -#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(__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 deleted file mode 100644 index aec63dbd1..000000000 --- a/grub-core/kern/coreboot/cbtable.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 deleted file mode 100644 index caf8f7cef..000000000 --- a/grub-core/kern/coreboot/mmap.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 fc54f43f2..eec575c05 100644 --- a/grub-core/kern/corecmd.c +++ b/grub-core/kern/corecmd.c @@ -36,11 +36,17 @@ 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) { - struct grub_env_var *env; - FOR_SORTED_ENV (env) - grub_printf ("%s=%s\n", env->name, grub_env_get (env->name)); + grub_env_iterate (print_env); return 0; } @@ -90,7 +96,7 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), } static int -grub_mini_print_devices (const char *name, void *data __attribute__ ((unused))) +grub_mini_print_devices (const char *name) { grub_printf ("(%s) ", name); @@ -99,8 +105,7 @@ grub_mini_print_devices (const char *name, void *data __attribute__ ((unused))) static int grub_mini_print_files (const char *filename, - const struct grub_dirhook_info *info, - void *data __attribute__ ((unused))) + const struct grub_dirhook_info *info) { grub_printf ("%s%s ", filename, info->dir ? "/" : ""); @@ -114,7 +119,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), { if (argc < 1) { - grub_device_iterate (grub_mini_print_devices, NULL); + grub_device_iterate (grub_mini_print_devices); grub_xputs ("\n"); grub_refresh (); } @@ -139,13 +144,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; @@ -155,7 +160,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), } else if (fs) { - (fs->fs_dir) (dev, path, grub_mini_print_files, NULL); + (fs->dir) (dev, path, grub_mini_print_files); grub_xputs ("\n"); grub_refresh (); } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 73b8ecc0c..12615647d 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -85,107 +85,94 @@ grub_device_close (grub_device_t device) return grub_errno; } -struct part_ent +int +grub_device_iterate (int (*hook) (const char *name)) { - struct part_ent *next; - char *name; -}; + auto int iterate_disk (const char *disk_name); + auto int iterate_partition (grub_disk_t disk, + const grub_partition_t partition); -/* Context for grub_device_iterate. */ -struct grub_device_iterate_ctx -{ - grub_device_iterate_hook_t hook; - void *hook_data; - struct part_ent *ents; -}; + struct part_ent + { + struct part_ent *next; + char *name; + } *ents; -/* 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) + int iterate_disk (const char *disk_name) { - return 1; - } + grub_device_t dev; - 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; - } + if (hook (disk_name)) + return 1; - p->next = ctx->ents; - ctx->ents = p; + dev = grub_device_open (disk_name); + if (! dev) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } - return 0; -} + if (dev->disk) + { + struct part_ent *p; + int ret = 0; -/* 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; + ents = NULL; + (void) grub_partition_iterate (dev->disk, iterate_partition); + grub_device_close (dev); - if (ctx->hook (disk_name, ctx->hook_data)) - return 1; + grub_errno = GRUB_ERR_NONE; - dev = grub_device_open (disk_name); - if (! dev) - { - grub_errno = GRUB_ERR_NONE; + 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); return 0; } - if (dev->disk) + int iterate_partition (grub_disk_t disk, const grub_partition_t partition) { struct part_ent *p; - int ret = 0; + char *part_name; - ctx->ents = NULL; - (void) grub_partition_iterate (dev->disk, iterate_partition, ctx); - grub_device_close (dev); - - grub_errno = GRUB_ERR_NONE; - - p = ctx->ents; - while (p != NULL) + p = grub_malloc (sizeof (*p)); + if (!p) { - struct part_ent *next = p->next; - - if (!ret) - ret = ctx->hook (p->name, ctx->hook_data); - grub_free (p->name); - grub_free (p); - p = next; + return 1; } - return ret; + 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; + } + + p->next = ents; + ents = p; + + return 0; } - 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); + return grub_disk_dev_iterate (iterate_disk); } diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index ffb09c8ee..1f55f90a8 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -31,7 +31,18 @@ /* The last time the disk was used. */ static grub_uint64_t grub_last_time = 0; -struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; + +/* 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]; void (*grub_disk_firmware_fini) (void); int grub_disk_firmware_is_tainted; @@ -48,12 +59,35 @@ grub_disk_cache_get_performance (unsigned long *hits, unsigned long *misses) } #endif -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" +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; + } +} void grub_disk_cache_invalidate_all (void) @@ -77,10 +111,10 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector) { struct grub_disk_cache *cache; - unsigned cache_index; + unsigned index; - cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + cache_index; + 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) @@ -104,10 +138,10 @@ grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector) { struct grub_disk_cache *cache; - unsigned cache_index; + unsigned index; - cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + cache_index; + 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) @@ -118,11 +152,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 cache_index; + unsigned index; struct grub_disk_cache *cache; - cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + cache_index; + index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + index; cache->lock = 1; grub_free (cache->data); @@ -199,9 +233,6 @@ 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) @@ -223,7 +254,7 @@ grub_disk_open (const char *name) for (dev = grub_disk_dev_list; dev; dev = dev->next) { - if ((dev->disk_open) (raw, disk) == GRUB_ERR_NONE) + if ((dev->open) (raw, disk) == GRUB_ERR_NONE) break; else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) grub_errno = GRUB_ERR_NONE; @@ -294,8 +325,8 @@ grub_disk_close (grub_disk_t disk) grub_partition_t part; grub_dprintf ("disk", "Closing `%s'.\n", disk->name); - if (disk->dev && disk->dev->disk_close) - (disk->dev->disk_close) (disk); + if (disk->dev && disk->dev->close) + (disk->dev->close) (disk); /* Reset the timer. */ grub_last_time = grub_get_time_ms (); @@ -310,12 +341,59 @@ 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_real (grub_disk_t disk, grub_disk_addr_t sector, - grub_off_t offset, grub_size_t size, void *buf) +grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) { char *data; char *tmp_buf; @@ -341,10 +419,10 @@ grub_disk_read_small_real (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->disk_read) (disk, transform_sector (disk, sector), - 1U << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS - - disk->log_sector_size), tmp_buf); + err = (disk->dev->read) (disk, transform_sector (disk, sector), + 1 << (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. */ @@ -366,19 +444,19 @@ grub_disk_read_small_real (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 & ~((1ULL << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); - num = ((size + offset + (1ULL << (disk->log_sector_size)) + num = ((size + offset + (1 << (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->disk_read) (disk, transform_sector (disk, aligned_sector), - num, tmp_buf)) + if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector), + num, tmp_buf)) { grub_error_push (); grub_dprintf ("disk", "%s read failed\n", disk->name); @@ -392,27 +470,15 @@ grub_disk_read_small_real (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) - (disk->read_hook) (sector + (offset >> GRUB_DISK_SECTOR_BITS), - offset & (GRUB_DISK_SECTOR_SIZE - 1), - size, disk->read_hook_data); - return GRUB_ERR_NONE; -} - /* 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; + /* First of all, check if the region is within the disk. */ if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) { @@ -423,6 +489,10 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } + real_sector = sector; + real_offset = offset; + real_size = size; + /* First read until first cache boundary. */ if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1))) { @@ -431,7 +501,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_err_t err; grub_size_t len; - start_sector = sector & ~((grub_disk_addr_t) GRUB_DISK_CACHE_SIZE - 1); + start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1); pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS; len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS) - pos - offset); @@ -457,8 +527,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, /* agglomerate read until we find a first cached entry. */ for (agglomerate = 0; agglomerate - < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)) - && agglomerate < disk->max_agglomerate; + < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)); agglomerate++) { data = grub_disk_cache_fetch (disk->dev->id, disk->id, @@ -483,11 +552,11 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, { grub_disk_addr_t i; - err = (disk->dev->disk_read) (disk, transform_sector (disk, sector), - agglomerate << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS - - disk->log_sector_size), - buf); + err = (disk->dev->read) (disk, transform_sector (disk, sector), + agglomerate << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), + buf); if (err) return err; @@ -498,11 +567,6 @@ 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), - disk->read_hook_data); - sector += agglomerate << GRUB_DISK_CACHE_BITS; size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); buf = (char *) buf @@ -511,9 +575,6 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, if (data) { - if (disk->read_hook) - (disk->read_hook) (sector, 0, (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS), - 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); @@ -529,6 +590,103 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return err; } + /* 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; + + 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; } diff --git a/grub-core/kern/disk_common.c b/grub-core/kern/disk_common.c deleted file mode 100644 index 2ca12b5f8..000000000 --- a/grub-core/kern/disk_common.c +++ /dev/null @@ -1,65 +0,0 @@ -/* 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. - Treat unknown as 1EiB disk. While on it, clamp the size to 1EiB. - Just one condition is enough since GRUB_DISK_UNKNOWN_SIZE << ls is always - above 9EiB. - */ - if (total_sectors > (1ULL << 51)) - total_sectors = (1ULL << 51); - - 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 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); -} - -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 48eb5e7b6..5b0aa6582 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -38,6 +38,10 @@ #define GRUB_MODULES_MACHINE_READONLY #endif +#ifdef GRUB_MACHINE_EMU +#include +#endif + #pragma GCC diagnostic ignored "-Wcast-align" @@ -47,7 +51,6 @@ 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) { @@ -55,6 +58,9 @@ 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; } @@ -71,6 +77,18 @@ 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 @@ -223,28 +241,27 @@ static grub_err_t grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) { unsigned i; - const Elf_Shdr *s; + Elf_Shdr *s; grub_size_t tsize = 0, talign = 1; -#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) +#if defined (__ia64__) || defined (__powerpc__) grub_size_t tramp; grub_size_t got; - grub_err_t err; #endif char *ptr; - for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); + for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); i < e->e_shnum; - i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) + i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) { tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; if (talign < s->sh_addralign) talign = s->sh_addralign; } -#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) - err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got); - if (err) - return err; +#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; @@ -254,15 +271,21 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) #endif #ifdef GRUB_MACHINE_EMU - mod->base = grub_osdep_dl_memalign (talign, tsize); -#else - mod->base = grub_memalign (talign, tsize); + if (talign < 8192 * 16) + talign = 8192 * 16; + tsize = ALIGN_UP (tsize, 8192 * 16); #endif + + mod->base = grub_memalign (talign, tsize); 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)) @@ -304,14 +327,12 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) mod->segment = seg; } } -#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) +#if defined (__ia64__) || defined (__powerpc__) ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN); mod->tramp = ptr; - mod->trampptr = ptr; ptr += tramp; ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN); mod->got = ptr; - mod->gotptr = ptr; ptr += got; #endif @@ -333,21 +354,15 @@ 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_ERR_NONE; + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); #ifdef GRUB_MODULES_MACHINE_READONLY mod->symtab = grub_malloc (s->sh_size); - if (!mod->symtab) - return grub_errno; - grub_memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size); + 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; @@ -430,22 +445,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) return GRUB_ERR_NONE; } -static Elf_Shdr * -grub_dl_find_section (Elf_Ehdr *e, const char *name) +static void +grub_dl_call_init (grub_dl_t 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; + if (mod->init) + (mod->init) (mod); } /* Me, Vladimir Serbinenko, hereby I add this module check as per new @@ -459,11 +463,24 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name) static grub_err_t grub_dl_check_license (Elf_Ehdr *e) { - Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); - if (s && (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + 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, ".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; + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); } @@ -471,14 +488,25 @@ static grub_err_t grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e) { Elf_Shdr *s; + const char *str; + unsigned i; - s = grub_dl_find_section (e, ".modname"); - if (!s) + 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) 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; } @@ -487,36 +515,42 @@ static grub_err_t grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e) { Elf_Shdr *s; + const char *str; + unsigned i; - s = grub_dl_find_section (e, ".moddeps"); + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); + str = (char *) e + s->sh_offset; - if (!s) - return GRUB_ERR_NONE; + 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; - const char *name = (char *) e + s->sh_offset; - const char *max = name + s->sh_size; + while ((name < max) && (*name)) + { + grub_dl_t m; + grub_dl_dep_t dep; - while ((name < max) && (*name)) - { - grub_dl_t m; - grub_dl_dep_t dep; + m = grub_dl_load (name); + if (! m) + return grub_errno; - m = grub_dl_load (name); - if (! m) - return grub_errno; + grub_dl_ref (m); - grub_dl_ref (m); + dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep)); + if (! dep) + return grub_errno; - dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep)); - if (! dep) - return grub_errno; + dep->mod = m; + dep->next = mod->dep; + mod->dep = dep; - dep->mod = m; - dep->next = mod->dep; - mod->dep = dep; - - name += grub_strlen (name) + 1; - } + name += grub_strlen (name) + 1; + } + } return GRUB_ERR_NONE; } @@ -557,43 +591,9 @@ 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; - - /* 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; -} - /* Load a module from core memory. */ grub_dl_t -grub_dl_load_core_noinit (void *addr, grub_size_t size) +grub_dl_load_core (void *addr, grub_size_t size) { Elf_Ehdr *e; grub_dl_t mod; @@ -611,7 +611,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) } /* Make sure that every section is within the core. */ - if (size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum) + if (size < e->e_shoff + e->e_shentsize * e->e_shnum) { grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core"); return 0; @@ -637,7 +637,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) || grub_dl_resolve_dependencies (mod, e) || grub_dl_load_segments (mod, e) || grub_dl_resolve_symbols (mod, e) - || grub_dl_relocate_symbols (mod, e)) + || grub_arch_dl_relocate_symbols (mod, e)) { mod->fini = 0; grub_dl_unload (mod); @@ -648,6 +648,7 @@ grub_dl_load_core_noinit (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)) { @@ -658,25 +659,6 @@ grub_dl_load_core_noinit (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) @@ -686,9 +668,7 @@ grub_dl_load_file (const char *filename) void *core = 0; grub_dl_t mod = 0; - grub_boot_time ("Loading module %s", filename); - - file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE); + file = grub_file_open (filename); if (! file) return 0; @@ -733,9 +713,6 @@ 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; @@ -782,11 +759,7 @@ 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); diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index e0165e74c..02d2f9a00 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -27,7 +27,6 @@ #include #include #include -#include /* The handle of GRUB itself. Filled in by the startup code. */ grub_efi_handle_t grub_efi_image_handle; @@ -154,20 +153,10 @@ 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); - efi_call_4 (grub_efi_system_table->runtime_services->reset_system, - GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); - for (;;) ; -} - void grub_exit (void) { - grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + grub_efi_fini (); efi_call_4 (grub_efi_system_table->boot_services->exit, grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); for (;;) ; @@ -192,37 +181,6 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed"); } -grub_err_t -grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, - void *data, grub_size_t datasize) -{ - grub_efi_status_t status; - grub_efi_runtime_services_t *r; - grub_efi_char16_t *var16; - grub_size_t len, len16; - - len = grub_strlen (var); - len16 = len * GRUB_MAX_UTF16_PER_UTF8; - var16 = grub_calloc (len16 + 1, sizeof (var16[0])); - if (!var16) - return grub_errno; - len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL); - var16[len16] = 0; - - r = grub_efi_system_table->runtime_services; - - status = efi_call_5 (r->set_variable, var16, guid, - (GRUB_EFI_VARIABLE_NON_VOLATILE - | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS - | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), - 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); -} - void * grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, grub_size_t *datasize_out) @@ -238,7 +196,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, len = grub_strlen (var); len16 = len * GRUB_MAX_UTF16_PER_UTF8; - var16 = grub_calloc (len16 + 1, sizeof (var16[0])); + 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); @@ -248,11 +206,8 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); - if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize) - { - grub_free (var16); - return NULL; - } + if (!datasize) + return NULL; data = grub_malloc (datasize); if (!data) @@ -309,75 +264,24 @@ grub_efi_modules_addr (void) } if (i == coff_header->num_sections) - { - grub_dprintf("sections", "section %d is last section; invalid.\n", i); - return 0; - } + return 0; info = (struct grub_module_info *) ((char *) image->image_base + section->virtual_address); - 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; - } + if (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 *dp0) +grub_efi_get_filename (grub_efi_device_path_t *dp) { - char *name = 0, *p, *pi; - grub_size_t filesize = 0; - grub_efi_device_path_t *dp; + char *name = 0; - 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) + while (1) { grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); @@ -389,54 +293,45 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0) { grub_efi_file_path_device_path_t *fp; grub_efi_uint16_t len; - grub_efi_char16_t *dup_name; + char *p; + grub_size_t size; - *p++ = '/'; - - len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); - if (len < 4) + if (name) { - grub_error (GRUB_ERR_OUT_OF_RANGE, - "malformed EFI Device Path node has length=%d", len); - return NULL; + size = grub_strlen (name); + name[size] = '/'; + size++; } + else + size = 0; - 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) + len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) + / sizeof (grub_efi_char16_t)); + p = grub_realloc (name, size + len * 4 + 1); + if (! p) { grub_free (name); - return NULL; + return 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); + + 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'; } dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); } - *p = '\0'; - - for (pi = name, p = name; *pi;) + if (name) { /* EFI breaks paths with backslashes. */ - if (*pi == '\\' || *pi == '/') - { - *p++ = '/'; - while (*pi == '\\' || *pi == '/') - pi++; - continue; - } - *p++ = *pi++; + char *p; + + for (p = name; *p; p++) + if (*p == '\\') + *p = '/'; } - *p = '\0'; return name; } @@ -448,99 +343,11 @@ 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=%d", 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(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)[%x: ", - type, - (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], - 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 (GRUB_EFI_DEVICE_PATH_VALID (dp)) + while (1) { grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); @@ -570,40 +377,54 @@ 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_efi_pci_device_path_t *) dp; + grub_efi_pci_device_path_t pci; + grub_memcpy (&pci, dp, len); 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_efi_pccard_device_path_t *) dp; + grub_efi_pccard_device_path_t pccard; + grub_memcpy (&pccard, dp, len); 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_efi_memory_mapped_device_path_t *) dp; + grub_efi_memory_mapped_device_path_t mmapped; + grub_memcpy (&mmapped, dp, len); 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: - dump_vendor_path ("Hardware", - (grub_efi_vendor_device_path_t *) dp); + { + 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]); + } break; case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE: { - grub_efi_controller_device_path_t *controller - = (grub_efi_controller_device_path_t *) dp; + grub_efi_controller_device_path_t controller; + grub_memcpy (&controller, dp, len); grub_printf ("/Ctrl(%x)", - (unsigned) controller->controller_number); + (unsigned) controller.controller_number); } break; default: @@ -617,31 +438,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_efi_acpi_device_path_t *) dp; + grub_efi_acpi_device_path_t acpi; + grub_memcpy (&acpi, dp, len); 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_efi_expanded_acpi_device_path_t *) dp; + grub_efi_expanded_acpi_device_path_t eacpi; + grub_memcpy (&eacpi, dp, sizeof (eacpi)); 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)); } @@ -657,164 +478,166 @@ 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_efi_atapi_device_path_t *) dp; + grub_efi_atapi_device_path_t atapi; + grub_memcpy (&atapi, dp, len); 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_efi_scsi_device_path_t *) dp; + grub_efi_scsi_device_path_t scsi; + grub_memcpy (&scsi, dp, len); 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_efi_fibre_channel_device_path_t *) dp; + grub_efi_fibre_channel_device_path_t fc; + grub_memcpy (&fc, dp, len); 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_efi_1394_device_path_t *) dp; - grub_printf ("/1394(%llx)", - (unsigned long long) firewire->guid); + grub_efi_1394_device_path_t firewire; + grub_memcpy (&firewire, dp, len); + 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_efi_usb_device_path_t *) dp; + grub_efi_usb_device_path_t usb; + grub_memcpy (&usb, dp, len); grub_printf ("/USB(%x,%x)", - (unsigned) usb->parent_port_number, - (unsigned) usb->usb_interface); + (unsigned) usb.parent_port_number, + (unsigned) usb.interface); } break; case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE: { - grub_efi_usb_class_device_path_t *usb_class - = (grub_efi_usb_class_device_path_t *) dp; + grub_efi_usb_class_device_path_t usb_class; + grub_memcpy (&usb_class, dp, len); 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_efi_i2o_device_path_t *) dp; - grub_printf ("/I2O(%x)", (unsigned) i2o->tid); + grub_efi_i2o_device_path_t i2o; + grub_memcpy (&i2o, dp, len); + 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_efi_mac_address_device_path_t *) dp; + grub_efi_mac_address_device_path_t mac; + grub_memcpy (&mac, dp, len); 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_efi_ipv4_device_path_t *) dp; + grub_efi_ipv4_device_path_t ipv4; + grub_memcpy (&ipv4, dp, len); 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_efi_ipv6_device_path_t *) dp; + grub_efi_ipv6_device_path_t ipv6; + grub_memcpy (&ipv6, dp, len); 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_efi_infiniband_device_path_t *) dp; + grub_efi_infiniband_device_path_t ib; + grub_memcpy (&ib, dp, len); 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_efi_uart_device_path_t *) dp; + grub_efi_uart_device_path_t uart; + grub_memcpy (&uart, dp, len); 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_SATA_DEVICE_PATH_SUBTYPE: - { - 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_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE: - dump_vendor_path ("Messaging", - (grub_efi_vendor_device_path_t *) dp); + { + 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]); + } break; default: grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype); @@ -827,80 +650,79 @@ 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_efi_hard_drive_device_path_t *) dp; + grub_efi_hard_drive_device_path_t hd; + grub_memcpy (&hd, dp, len); 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->partmap_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.mbr_type, + (unsigned) hd.signature_type); } break; case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: { - grub_efi_cdrom_device_path_t *cd - = (grub_efi_cdrom_device_path_t *) dp; + grub_efi_cdrom_device_path_t cd; + grub_memcpy (&cd, dp, len); 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: - dump_vendor_path ("Media", - (grub_efi_vendor_device_path_t *) dp); + { + 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]); + } break; case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE: { grub_efi_file_path_device_path_t *fp; - grub_uint8_t *buf; + grub_uint8_t buf[(len - 4) * 2 + 1]; fp = (grub_efi_file_path_device_path_t *) dp; - 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_utf16_to_utf8 (buf, fp->path_name, + (len - 4) / sizeof (grub_efi_char16_t)) + = '\0'; grub_printf ("/File(%s)", buf); - grub_free (buf); } break; case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE: { - grub_efi_protocol_device_path_t *proto - = (grub_efi_protocol_device_path_t *) dp; + 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]); + (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]); } break; default: @@ -914,11 +736,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_efi_bios_device_path_t *) dp; + grub_efi_bios_device_path_t bios; + grub_memcpy (&bios, dp, sizeof (bios)); 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; @@ -952,10 +774,7 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, /* Return non-zero. */ return 1; - if (dp1 == dp2) - return 0; - - while (GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2)) + while (1) { grub_efi_uint8_t type1, type2; grub_efi_uint8_t subtype1, subtype2; @@ -991,14 +810,5 @@ 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; } diff --git a/grub-core/kern/efi/fdt.c b/grub-core/kern/efi/fdt.c deleted file mode 100644 index 30100c61c..000000000 --- a/grub-core/kern/efi/fdt.c +++ /dev/null @@ -1,43 +0,0 @@ -/* 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) -{ - grub_efi_configuration_table_t *tables; - grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; - void *firmware_fdt = NULL; - unsigned int i; - - /* Look for FDT in UEFI config tables. */ - tables = grub_efi_system_table->configuration_table; - - for (i = 0; i < grub_efi_system_table->num_table_entries; i++) - if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0) - { - firmware_fdt = tables[i].vendor_table; - grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt); - break; - } - - return firmware_fdt; -} diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 2c31847bf..942ab0256 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -59,20 +59,14 @@ grub_machine_get_bootlocation (char **device, char **path) if (!image) return; *device = grub_efidisk_get_device_name (image->device_handle); - if (!*device && grub_efi_net_config) - { - grub_efi_net_config (image->device_handle, device, path); - return; - } - *path = grub_efi_get_filename (image->file_path); - if (*path) - { - /* Get the directory. */ - p = grub_strrchr (*path, '/'); - if (p) - *p = '\0'; - } + if (!*device && grub_efi_net_config) + grub_efi_net_config (image->device_handle, device, 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 457772d57..a2edc84b3 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -21,7 +21,6 @@ #include #include #include -#include #if defined (__i386__) || defined (__x86_64__) #include @@ -31,7 +30,6 @@ ((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 @@ -49,133 +47,55 @@ 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 = efi_call_3 (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 || ea->pages != pages) - continue; - - /* 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. */ - efi_call_1 (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_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_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) { + 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 > GRUB_EFI_MAX_USABLE_ADDRESS) + if (address > 0xffffffff) + return 0; +#endif + +#if 1 + if (address == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("invalid memory address (0x%llx > 0x%llx)"), - address, GRUB_EFI_MAX_USABLE_ADDRESS); - return NULL; + type = GRUB_EFI_ALLOCATE_MAX_ADDRESS; + address = 0xffffffff; } + 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, alloctype, memtype, pages, &address); + status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); if (status != GRUB_EFI_SUCCESS) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); - return NULL; - } + return 0; if (address == 0) { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ - address = GRUB_EFI_MAX_USABLE_ADDRESS; - status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address); + address = 0xffffffff; + status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); - return NULL; - } + return 0; } - 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, @@ -185,42 +105,41 @@ grub_efi_free_pages (grub_efi_physical_address_t address, b = grub_efi_system_table->boot_services; efi_call_2 (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) { - grub_pci_iterate (find_card, NULL); + 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); } #endif @@ -242,41 +161,27 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, apple, sizeof (apple)) == 0); #endif - 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 (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) - { - grub_free (finish_mmap_buf); - 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) + 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) - break; + 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"); - if (status != GRUB_EFI_INVALID_PARAMETER) - { - grub_free (finish_mmap_buf); - return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services"); - } - - grub_free (finish_mmap_buf); - grub_printf ("Trying to terminate EFI services again\n"); - } grub_efi_is_finished = 1; if (outbuf_size) *outbuf_size = finish_mmap_size; @@ -297,30 +202,6 @@ 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 @@ -334,7 +215,6 @@ 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) { @@ -364,14 +244,10 @@ 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, 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) @@ -430,7 +306,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, { if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY #if 1 - && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS + && desc->physical_start <= 0xffffffff #endif && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 && desc->num_pages != 0) @@ -448,9 +324,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_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)) + > BYTES_TO_PAGES (0x100000000LL)) filtered_desc->num_pages - = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS) + = (BYTES_TO_PAGES (0x100000000LL) - BYTES_TO_PAGES (filtered_desc->physical_start)); #endif @@ -506,9 +382,7 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, pages = required_pages; } - addr = grub_efi_allocate_pages_real (start, pages, - GRUB_EFI_ALLOCATE_ADDRESS, - GRUB_EFI_LOADER_CODE); + addr = grub_efi_allocate_pages (start, pages); if (! addr) grub_fatal ("cannot allocate conventional memory %p with %u pages", (void *) ((grub_addr_t) start), @@ -525,20 +399,6 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, grub_fatal ("too little memory"); } -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 /* Print the memory map. */ static void @@ -574,7 +434,8 @@ grub_efi_mm_init (void) int mm_status; /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + memory_map = grub_efi_allocate_pages (0, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); if (! memory_map) grub_fatal ("cannot allocate memory"); @@ -592,7 +453,7 @@ grub_efi_mm_init (void) /* Freeing/allocating operations may increase memory map size. */ map_size += desc_size * 32; - memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); + memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size)); if (! memory_map) grub_fatal ("cannot allocate memory"); @@ -637,41 +498,10 @@ 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_fatal ("Debug. "); + grub_abort (); #endif /* Release the memory maps. */ grub_efi_free_pages ((grub_addr_t) memory_map, 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); } - -#if defined (__aarch64__) || defined (__arm__) || defined (__riscv) -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 diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c index 9d7149b38..682cfbdb2 100644 --- a/grub-core/kern/elf.c +++ b/grub-core/kern/elf.c @@ -28,25 +28,6 @@ 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) @@ -57,25 +38,8 @@ 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) - 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) + || e->e_ident[EI_VERSION] != EV_CURRENT + || e->e_version != EV_CURRENT) return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic")); return GRUB_ERR_NONE; @@ -87,7 +51,6 @@ 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) @@ -122,26 +85,21 @@ 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, enum grub_file_type type) +grub_elf_open (const char *name) { grub_file_t file; grub_elf_t elf; - file = grub_file_open (name, type); + file = grub_file_open (name); if (! file) return 0; @@ -153,60 +111,382 @@ grub_elf_open (const char *name, enum grub_file_type type) } -#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 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 -#include "elfXX.c" +int +grub_elf_is_elf32 (grub_elf_t elf) +{ + return elf->ehdr.ehdr32.e_ident[EI_CLASS] == ELFCLASS32; +} -#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 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 +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; +} /* 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 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 -#include "elfXX.c" +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; +} diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c deleted file mode 100644 index 1859d1880..000000000 --- a/grub-core/kern/elfXX.c +++ /dev/null @@ -1,207 +0,0 @@ -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; -} diff --git a/grub-core/kern/emu/argp_common.c b/grub-core/kern/emu/argp_common.c index 166885870..d6080ba25 100644 --- a/grub-core/kern/emu/argp_common.c +++ b/grub-core/kern/emu/argp_common.c @@ -18,10 +18,6 @@ */ #include -#include - -#pragma GCC diagnostic ignored "-Wmissing-prototypes" -#pragma GCC diagnostic ignored "-Wmissing-declarations" #define _GNU_SOURCE 1 #include diff --git a/grub-core/kern/emu/cache.c b/grub-core/kern/emu/cache.c index 113682cc4..543e457e5 100644 --- a/grub-core/kern/emu/cache.c +++ b/grub-core/kern/emu/cache.c @@ -1,35 +1,13 @@ -#ifndef GRUB_MACHINE_EMU -#error "This source is only meant for grub-emu platform" -#endif - -#include #if defined(__ia64__) -#include "../ia64/cache.c" -#elif defined (__arm__) || defined (__aarch64__) +#include -void __clear_cache (void *beg, void *end); +void __clear_cache (char *beg, char *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 2245cddc3..8ca695c28 100644 --- a/grub-core/kern/emu/cache_s.S +++ b/grub-core/kern/emu/cache_s.S @@ -6,10 +6,24 @@ /* 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__) || defined(__arm__) || defined(__aarch64__) || \ - defined(__mips__) || defined(__riscv) +#elif defined(__ia64__) #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 e8d63b1f5..b167a141b 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -24,8 +24,6 @@ #include #include -const int grub_no_modules = 1; - void grub_register_exported_symbols (void) { @@ -39,24 +37,25 @@ grub_arch_dl_check_header (void *ehdr) } grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, - Elf_Shdr *s, grub_dl_segment_t seg) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { (void) mod; (void) ehdr; - (void) s; - (void) seg; return GRUB_ERR_BAD_MODULE; } -#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) +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) { *tramp = 0; *got = 0; - return GRUB_ERR_BAD_MODULE; } #endif @@ -67,3 +66,7 @@ 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 d975265b2..b8c376643 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -17,8 +17,6 @@ * along with GRUB. If not, see . */ -#include - #include #include #include @@ -46,11 +44,77 @@ #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; @@ -58,6 +122,58 @@ 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) { @@ -99,7 +215,7 @@ find_free_slot (void) { unsigned int i; - for (i = 0; i < ARRAY_SIZE (map); i++) + for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) if (! map[i].drive) return i; @@ -107,7 +223,7 @@ find_free_slot (void) } static int -grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, +grub_util_biosdisk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { unsigned i; @@ -115,120 +231,735 @@ grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, if (pull != GRUB_DISK_PULL_NONE) return 0; - for (i = 0; i < ARRAY_SIZE (map); i++) - if (map[i].drive && hook (map[i].drive, hook_data)) + for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) + if (map[i].drive && hook (map[i].drive)) 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 grub_util_hostdisk_data *data; + struct stat st; + struct grub_util_biosdisk_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_hostdisk_data)); + disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); data->dev = NULL; data->access_mode = 0; - data->fd = GRUB_UTIL_FD_INVALID; + data->fd = -1; data->is_disk = 0; data->device_map = map[drive].device_map; /* Get the size. */ +#if defined(__MINGW32__) { - grub_util_fd_t fd; + grub_uint64_t size; - fd = grub_util_fd_open (map[drive].device, GRUB_UTIL_FD_O_RDONLY); + size = grub_util_get_disk_size (map[drive].device); - if (!GRUB_UTIL_FD_IS_VALID(fd)) + 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) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"), - map[drive].device, grub_util_fd_strerror ()); + map[drive].device, strerror (errno)); 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 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)) +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) + 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; - } -#endif + data->is_disk = 1; - grub_util_fd_close (fd); + close (fd); - grub_util_info ("the size of %s is %" GRUB_HOST_PRIuLONG_LONG, - name, (unsigned long long) disk->total_sectors); + grub_util_info ("the size of %s is %" PRIuGRUB_UINT64_T, + name, 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, canon) == 0) - { - free (canon); - return map[i].drive; - } + else if (strcmp (map[i].device, os_disk) == 0) + return map[i].drive; if (!add) - { - free (canon); - return NULL; - } + 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 = canon; + map[i].device = xstrdup (os_disk); 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; - grub_hostdisk_flush_initial_buffer (os_disk); + flush_initial_buffer (os_disk); return map[i].drive; } -#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) +static int +open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, + grub_disk_addr_t *max) { - grub_util_fd_t fd; - struct grub_util_hostdisk_data *data = disk->data; + int fd; + struct grub_util_biosdisk_data *data = disk->data; *max = ~0ULL; - flags |= GRUB_UTIL_FD_O_SYNC; +#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 if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 && data->access_mode == (flags & O_ACCMODE)) @@ -240,16 +971,22 @@ grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int f { free (data->dev); data->dev = 0; - if (GRUB_UTIL_FD_IS_VALID(data->fd)) + if (data->fd != -1) { if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) - grub_util_fd_sync (data->fd); - grub_util_fd_close (data->fd); - data->fd = GRUB_UTIL_FD_INVALID; + { + fsync (data->fd); +#ifdef __linux__ + if (data->is_disk) + ioctl (data->fd, BLKFLSBUF, 0); +#endif + } + close (data->fd); + data->fd = -1; } - fd = grub_util_fd_open (map[disk->id].device, flags); - if (GRUB_UTIL_FD_IS_VALID(fd)) + fd = open (map[disk->id].device, flags); + if (fd >= 0) { data->dev = xstrdup (map[disk->id].device); data->access_mode = (flags & O_ACCMODE); @@ -257,26 +994,94 @@ grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int f } } - if (!GRUB_UTIL_FD_IS_VALID(data->fd)) +#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) { grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - map[disk->id].device, grub_util_fd_strerror ()); - return GRUB_UTIL_FD_INVALID; + map[disk->id].device, strerror (errno)); + return -1; } +#endif /* ! __linux__ */ - if (grub_util_fd_seek (fd, sector << disk->log_sector_size)) +#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)) { - 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; + close (fd); + return -1; } 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, @@ -284,10 +1089,10 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, { while (size) { - grub_util_fd_t fd; + int fd; grub_disk_addr_t max = ~0ULL; - fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_RDONLY, &max); - if (!GRUB_UTIL_FD_IS_VALID (fd)) + fd = open_device (disk, sector, O_RDONLY, &max); + if (fd < 0) return grub_errno; #ifdef __linux__ @@ -305,7 +1110,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, grub_util_fd_strerror ()); + map[disk->id].device, strerror (errno)); size -= max; buf += (max << disk->log_sector_size); sector += max; @@ -319,10 +1124,10 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { while (size) { - grub_util_fd_t fd; + int fd; grub_disk_addr_t max = ~0ULL; - fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_WRONLY, &max); - if (!GRUB_UTIL_FD_IS_VALID (fd)) + fd = open_device (disk, sector, O_WRONLY, &max); + if (fd < 0) return grub_errno; #ifdef __linux__ @@ -340,7 +1145,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, grub_util_fd_strerror ()); + map[disk->id].device, strerror (errno)); size -= max; buf += (max << disk->log_sector_size); } @@ -350,18 +1155,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_hostdisk_data *data = disk->data; + struct grub_util_biosdisk_data *data = disk->data; if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID) return GRUB_ERR_NONE; - if (!GRUB_UTIL_FD_IS_VALID (data->fd)) + if (data->fd == -1) { grub_disk_addr_t max; - data->fd = grub_util_fd_open_device (disk, 0, GRUB_UTIL_FD_O_RDONLY, &max); - if (!GRUB_UTIL_FD_IS_VALID (data->fd)) + data->fd = open_device (disk, 0, O_RDONLY, &max); + if (data->fd < 0) return grub_errno; } - grub_util_fd_sync (data->fd); + fsync (data->fd); #ifdef __linux__ if (data->is_disk) ioctl (data->fd, BLKFLSBUF, 0); @@ -372,14 +1177,14 @@ grub_util_biosdisk_flush (struct grub_disk *disk) static void grub_util_biosdisk_close (struct grub_disk *disk) { - struct grub_util_hostdisk_data *data = disk->data; + struct grub_util_biosdisk_data *data = disk->data; free (data->dev); - if (GRUB_UTIL_FD_IS_VALID (data->fd)) + if (data->fd != -1) { if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) grub_util_biosdisk_flush (disk); - grub_util_fd_close (data->fd); + close (data->fd); } free (data); } @@ -388,47 +1193,36 @@ static struct grub_disk_dev grub_util_biosdisk_dev = { .name = "hostdisk", .id = GRUB_DISK_DEVICE_HOSTDISK_ID, - .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, + .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, .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; - if (!dev_map || dev_map[0] == '\0') + 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') { grub_util_info ("no device.map"); return; } - fp = grub_util_fopen (dev_map, "r"); + fp = fopen (dev_map, "r"); if (! fp) { grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno)); @@ -456,14 +1250,14 @@ read_device_map (const char *dev_map) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), '('); - grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); + show_error (tmp); } p++; /* Find a free slot. */ drive = find_free_slot (); if (drive < 0) - grub_util_error ("%s:%d: %s", dev_map, lineno, _("device count exceeds limit")); + show_error (_("device count exceeds limit")); e = p; p = strchr (p, ')'); @@ -471,7 +1265,7 @@ read_device_map (const char *dev_map) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), ')'); - grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); + show_error (tmp); } map[drive].drive = 0; @@ -516,7 +1310,7 @@ read_device_map (const char *dev_map) p++; if (*p == '\0') - grub_util_error ("%s:%d: %s", dev_map, lineno, _("filename expected")); + show_error (_("filename expected")); /* NUL-terminate the filename. */ e = p; @@ -524,7 +1318,12 @@ read_device_map (const char *dev_map) e++; *e = '\0'; - if (!grub_util_check_file_presence (p)) +#ifdef __MINGW32__ + (void) st; + if (grub_util_get_disk_size (p) == -1LL) +#else + if (stat (p, &st) == -1) +#endif { free (map[drive].drive); map[drive].drive = NULL; @@ -532,13 +1331,19 @@ 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. */ - map[drive].device = grub_canonicalize_file_name (p); - if (! map[drive].device) - map[drive].device = xstrdup (p); - + 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); if (!map[drive].drive) { char c; @@ -560,10 +1365,7 @@ read_device_map (const char *dev_map) *drive_p = c; } - grub_util_info ("adding `%s' -> `%s' from device.map", map[drive].drive, - map[drive].device); - - grub_hostdisk_flush_initial_buffer (map[drive].device); + flush_initial_buffer (map[drive].device); } fclose (fp); @@ -581,7 +1383,7 @@ grub_util_biosdisk_fini (void) { unsigned i; - for (i = 0; i < ARRAY_SIZE(map); i++) + for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) { if (map[i].drive) free (map[i].drive); @@ -609,78 +1411,3 @@ 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 cb532105e..3cb089c3f 100644 --- a/grub-core/kern/emu/hostfs.c +++ b/grub-core/kern/emu/hostfs.c @@ -16,9 +16,7 @@ * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ - -#include - +#define _BSD_SOURCE #include #include #include @@ -29,8 +27,13 @@ #include #include +#include #include #include + + +/* dirent.d_type is a BSD extension, not part of POSIX */ +#include #include static int @@ -38,9 +41,8 @@ is_dir (const char *path, const char *name) { int len1 = strlen(path); int len2 = strlen(name); - int ret; - char *pathname = xmalloc (len1 + 1 + len2 + 1 + 13); + char pathname[len1 + 1 + len2 + 1 + 13]; strcpy (pathname, path); /* Avoid UNC-path "//name" on Cygwin. */ @@ -49,49 +51,51 @@ is_dir (const char *path, const char *name) strcat (pathname, name); - ret = grub_util_is_directory (pathname); - free (pathname); - return ret; + struct stat st; + if (stat (pathname, &st)) + return 0; + return S_ISDIR (st.st_mode); } struct grub_hostfs_data { char *filename; - grub_util_fd_t f; + FILE *f; }; static grub_err_t grub_hostfs_dir (grub_device_t device, const char *path, - grub_fs_dir_hook_t hook, void *hook_data) + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) { - grub_util_fd_dir_t dir; + DIR *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 = grub_util_fd_opendir (path); + dir = opendir (path); if (! dir) return grub_error (GRUB_ERR_BAD_FILENAME, N_("can't open `%s': %s"), path, - grub_util_fd_strerror ()); + strerror (errno)); while (1) { - grub_util_fd_dirent_t de; + struct dirent *de; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); - de = grub_util_fd_readdir (dir); + de = readdir (dir); if (! de) break; info.dir = !! is_dir (path, de->d_name); - hook (de->d_name, &info, hook_data); + hook (de->d_name, &info); } - grub_util_fd_closedir (dir); + closedir (dir); return GRUB_ERR_NONE; } @@ -100,25 +104,25 @@ grub_hostfs_dir (grub_device_t device, const char *path, static grub_err_t grub_hostfs_open (struct grub_file *file, const char *name) { - grub_util_fd_t f; + FILE *f; struct grub_hostfs_data *data; - f = grub_util_fd_open (name, GRUB_UTIL_FD_O_RDONLY); - if (! GRUB_UTIL_FD_IS_VALID (f)) + f = fopen (name, "rb"); + if (! f) return grub_error (GRUB_ERR_BAD_FILENAME, N_("can't open `%s': %s"), name, strerror (errno)); data = grub_malloc (sizeof (*data)); if (!data) { - grub_util_fd_close (f); + fclose (f); return grub_errno; } data->filename = grub_strdup (name); if (!data->filename) { grub_free (data); - grub_util_fd_close (f); + fclose (f); return grub_errno; } @@ -126,7 +130,11 @@ grub_hostfs_open (struct grub_file *file, const char *name) file->data = data; - file->size = grub_util_get_fd_size (f, name, NULL); +#ifdef __MINGW32__ + file->size = grub_util_get_disk_size (name); +#else + file->size = grub_util_get_fd_size (fileno (f), name, NULL); +#endif return GRUB_ERR_NONE; } @@ -137,17 +145,17 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hostfs_data *data; data = file->data; - if (grub_util_fd_seek (data->f, file->offset) != 0) + if (fseeko (data->f, file->offset, SEEK_SET) != 0) { grub_error (GRUB_ERR_OUT_OF_RANGE, N_("cannot seek `%s': %s"), - data->filename, grub_util_fd_strerror ()); + data->filename, strerror (errno)); return -1; } - unsigned int s = grub_util_fd_read (data->f, buf, len); + unsigned int s = fread (buf, 1, len, data->f); if (s != len) grub_error (GRUB_ERR_FILE_READ_ERROR, N_("cannot read `%s': %s"), - data->filename, grub_util_fd_strerror ()); + data->filename, strerror (errno)); return (signed) s; } @@ -158,7 +166,7 @@ grub_hostfs_close (grub_file_t file) struct grub_hostfs_data *data; data = file->data; - grub_util_fd_close (data->f); + fclose (data->f); grub_free (data->filename); grub_free (data); @@ -173,17 +181,14 @@ 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", - .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, + .dir = grub_hostfs_dir, + .open = grub_hostfs_open, + .read = grub_hostfs_read, + .close = grub_hostfs_close, + .label = grub_hostfs_label, .next = 0 }; diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c index b327d4e41..947c669aa 100644 --- a/grub-core/kern/emu/lite.c +++ b/grub-core/kern/emu/lite.c @@ -16,22 +16,11 @@ #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 @@ -45,3 +34,14 @@ 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 425bb9603..0418aae64 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -16,16 +16,15 @@ * along with GRUB. If not, see . */ -#include -#include - #include #include #include #include +#include #include #include #include +#include #include #include @@ -41,10 +40,6 @@ #include #include #include -#include -#include - -#pragma GCC diagnostic ignored "-Wmissing-prototypes" #include "progname.h" #include @@ -57,19 +52,14 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ static char *root_dev = NULL, *dir = NULL; +int grub_no_autoload; + grub_addr_t grub_modbase = 0; void grub_reboot (void) { longjmp (main_env, 1); - grub_fatal ("longjmp failed"); -} - -void -grub_exit (void) -{ - grub_reboot (); } void @@ -85,24 +75,18 @@ grub_machine_get_bootlocation (char **device, char **path) } void -grub_machine_fini (int flags) +grub_machine_fini (void) { - if (flags & GRUB_LOADER_FLAG_NORETURN) - grub_console_fini (); + 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}, @@ -110,8 +94,6 @@ static struct argp_option options[] = { { 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))) { @@ -126,12 +108,9 @@ 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; }; @@ -144,9 +123,6 @@ 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); @@ -188,7 +164,11 @@ static struct argp argp = { -#pragma GCC diagnostic ignored "-Wmissing-prototypes" +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); int main (int argc, char *argv[]) @@ -196,15 +176,11 @@ main (int argc, char *argv[]) struct arguments arguments = { .dev_map = DEFAULT_DEVICE_MAP, - .hold = 0, - .mem_disk = 0, + .hold = 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; - grub_util_host_init (&argc, &argv); + set_program_name (argv[0]); dir = xstrdup (DEFAULT_DIRECTORY); @@ -214,33 +190,6 @@ 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) @@ -256,6 +205,7 @@ main (int argc, char *argv[]) } signal (SIGINT, SIG_IGN); + grub_emu_init (); grub_console_init (); grub_host_init (); @@ -266,6 +216,8 @@ 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"); @@ -280,7 +232,29 @@ main (int argc, char *argv[]) grub_hostfs_fini (); grub_host_fini (); - grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + grub_machine_fini (); 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 dfd8a8ec4..21954ed50 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -16,18 +16,22 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_BUILD #include -#endif #include #include +#include #include #include #include #include #include #include +#include +#include +#ifdef HAVE_LIMITS_H +#include +#endif #include #include @@ -38,6 +42,27 @@ #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; void @@ -85,18 +110,6 @@ grub_util_error (const char *fmt, ...) exit (1); } -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 * xmalloc (grub_size_t size) { @@ -132,7 +145,36 @@ xstrdup (const char *str) return newstr; } -#if !defined (GRUB_MKFONT) && !defined (GRUB_BUILD) +#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 + char * xasprintf (const char *fmt, ...) { @@ -140,22 +182,21 @@ xasprintf (const char *fmt, ...) char *result; va_start (ap, fmt); - result = grub_xvasprintf (fmt, ap); - va_end (ap); - if (!result) - grub_util_error ("%s", _("out of memory")); + if (vasprintf (&result, fmt, ap) < 0) + { + if (errno == ENOMEM) + grub_util_error ("%s", _("out of memory")); + return NULL; + } return result; } -#endif -#if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL) void grub_exit (void) { exit (1); } -#endif grub_uint64_t grub_get_time_ms (void) @@ -167,50 +208,67 @@ grub_get_time_ms (void) return (tv.tv_sec * 1000 + tv.tv_usec / 1000); } -size_t -grub_util_get_image_size (const char *path) +grub_uint32_t +grub_get_rtc (void) { - FILE *f; - size_t ret; - off_t sz; + struct timeval tv; - f = grub_util_fopen (path, "rb"); + gettimeofday (&tv, 0); - 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); + return (tv.tv_sec * GRUB_TICKS_PER_SECOND + + (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec) + * GRUB_TICKS_PER_SECOND / 1000000)); +} +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; } -void -grub_util_load_image (const char *path, char *buf) +#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)), + ...) { - 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); } + +int +grub_device_mapper_supported (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; +} +#endif /* HAVE_DEVICE_MAPPER */ diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c index 4d1046a21..0461ea51c 100644 --- a/grub-core/kern/emu/mm.c +++ b/grub-core/kern/emu/mm.c @@ -25,16 +25,6 @@ #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) { @@ -60,8 +50,7 @@ grub_zalloc (grub_size_t size) void grub_free (void *ptr) { - if (ptr) - free (ptr); + free (ptr); } void * @@ -73,3 +62,27 @@ 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 c40862642..7bfa238e1 100644 --- a/grub-core/kern/env.c +++ b/grub-core/kern/env.c @@ -166,10 +166,11 @@ grub_env_unset (const char *name) grub_free (var); } -struct grub_env_var * -grub_env_update_get_sorted (void) +void +grub_env_iterate (int (*func) (struct grub_env_var *var)) { - struct grub_env_var *sorted_list = 0; + struct grub_env_sorted_var *sorted_list = 0; + struct grub_env_sorted_var *sorted_var; int i; /* Add variables associated with this context into a sorted list. */ @@ -179,20 +180,40 @@ grub_env_update_get_sorted (void) for (var = grub_current_context->vars[i]; var; var = var->next) { - struct grub_env_var *p, **q; + struct grub_env_sorted_var *p, **q; - for (q = &sorted_list, p = *q; p; q = &((*q)->sorted_next), 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) { - if (grub_strcmp (p->name, var->name) > 0) + if (grub_strcmp (p->var->name, var->name) > 0) break; } - var->sorted_next = *q; - *q = var; + sorted_var->next = *q; + *q = sorted_var; } } - return sorted_list; + /* 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; + } } grub_err_t diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c index 53c734de7..52ba6de62 100644 --- a/grub-core/kern/err.c +++ b/grub-core/kern/err.c @@ -47,6 +47,18 @@ 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 58454458c..495326f12 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -28,7 +28,8 @@ void (*EXPORT_VAR (grub_grubnet_fini)) (void); -grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX]; +grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; +grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX]; /* Get the device part of the filename NAME. It is enclosed by parentheses. */ char * @@ -58,12 +59,12 @@ grub_file_get_device_name (const char *name) } grub_file_t -grub_file_open (const char *name, enum grub_file_type type) +grub_file_open (const char *name) { grub_device_t device = 0; grub_file_t file = 0, last_file = 0; char *device_name; - const char *file_name; + char *file_name; grub_file_filter_id_t filter; device_name = grub_file_get_device_name (name); @@ -75,7 +76,7 @@ grub_file_open (const char *name, enum grub_file_type type) if (file_name) file_name++; else - file_name = name; + file_name = (char *) name; device = grub_device_open (device_name); grub_free (device_name); @@ -88,16 +89,7 @@ grub_file_open (const char *name, enum grub_file_type type) file->device = device; - /* 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 - ) + if (device->disk && file_name[0] != '/') /* This is a block list. */ file->fs = &grub_fs_blocklist; else @@ -107,26 +99,21 @@ grub_file_open (const char *name, enum grub_file_type type) goto fail; } - if ((file->fs->fs_open) (file, file_name) != GRUB_ERR_NONE) + if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE) goto fail; - file->name = grub_strdup (name); - grub_errno = GRUB_ERR_NONE; - - for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters); + for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters_enabled); filter++) - if (grub_file_filters[filter]) + if (grub_file_filters_enabled[filter]) { last_file = file; - file = grub_file_filters[filter] (file, type); - if (file && file != last_file) - { - file->name = grub_strdup (name); - grub_errno = GRUB_ERR_NONE; - } + file = grub_file_filters_enabled[filter] (file); } if (!file) grub_file_close (last_file); + + grub_memcpy (grub_file_filters_enabled, grub_file_filters_all, + sizeof (grub_file_filters_enabled)); return file; @@ -138,17 +125,16 @@ grub_file_open (const char *name, enum grub_file_type type) 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) { @@ -169,17 +155,7 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; - 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; + res = (file->fs->read) (file, buf, len); if (res > 0) file->offset += res; @@ -189,12 +165,11 @@ 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->fs_close) - (file->fs->fs_close) (file); + if (file->fs->close) + (file->fs->close) (file); if (file->device) grub_device_close (file->device); - grub_free (file->name); grub_free (file); return grub_errno; } diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index fb30da9f4..51d89d1b8 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -32,19 +32,18 @@ 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) { @@ -64,13 +63,13 @@ grub_fs_probe (grub_device_t device) if (grub_strcmp (p->name, "btrfs") == 0) { char *label = 0; - p->fs_uuid (device, &label); + p->uuid (device, &label); if (label) grub_free (label); } else #endif - (p->fs_dir) (device, "/", probe_dummy_iter, NULL); + (p->dir) (device, "/", dummy_func); if (grub_errno == GRUB_ERR_NONE) return p; @@ -94,7 +93,7 @@ grub_fs_probe (grub_device_t device) { p = grub_fs_list; - (p->fs_dir) (device, "/", probe_dummy_iter, NULL); + (p->dir) (device, "/", dummy_func); if (grub_errno == GRUB_ERR_NONE) { count--; @@ -134,7 +133,7 @@ struct grub_fs_block static grub_err_t grub_fs_blocklist_open (grub_file_t file, const char *name) { - const char *p = name; + char *p = (char *) name; unsigned num = 0; unsigned i; grub_disk_t disk = file->device->disk; @@ -151,7 +150,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) while (p); /* Allocate a block list. */ - blocks = grub_calloc (num + 1, sizeof (struct grub_fs_block)); + blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1)); if (! blocks) return 0; @@ -243,9 +242,9 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len) struct grub_fs grub_fs_blocklist = { .name = "blocklist", - .fs_dir = 0, - .fs_open = grub_fs_blocklist_open, - .fs_read = grub_fs_blocklist_read, - .fs_close = 0, + .dir = 0, + .open = grub_fs_blocklist_open, + .read = grub_fs_blocklist_read, + .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 3e39c8fe1..49f2acac9 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 ? : 1000, 0); + return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND, 0); } diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c deleted file mode 100644 index 34a2b59be..000000000 --- a/grub-core/kern/i386/coreboot/cbtable.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 3314f027f..52fbba4e8 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,2013 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,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 @@ -34,7 +34,9 @@ #include #include #include -#include +#ifdef GRUB_MACHINE_QEMU +#include +#endif extern grub_uint8_t _start[]; extern grub_uint8_t _end[]; @@ -49,85 +51,64 @@ grub_exit (void) grub_cpu_idle (); } -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) -{ - modend = grub_modules_get_end (); - - grub_video_coreboot_fb_early_init (); - - grub_vga_text_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 (); - - grub_tsc_init (); -} - +#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); +#endif void grub_machine_init (void) { - modend = grub_modules_get_end (); +#ifdef GRUB_MACHINE_QEMU + grub_modbase = grub_core_entry_addr + (_edata - _start); + 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 + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* 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 (); - grub_machine_mmap_iterate (heap_init, NULL); +#endif + grub_machine_mmap_iterate (heap_init); grub_tsc_init (); } -#endif - void grub_machine_get_bootlocation (char **device __attribute__ ((unused)), char **path __attribute__ ((unused))) @@ -135,9 +116,8 @@ grub_machine_get_bootlocation (char **device __attribute__ ((unused)), } void -grub_machine_fini (int flags) +grub_machine_fini (void) { - if (flags & GRUB_LOADER_FLAG_NORETURN) - grub_vga_text_fini (); + 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 new file mode 100644 index 000000000..8b0b20265 --- /dev/null +++ b/grub-core/kern/i386/coreboot/mmap.c @@ -0,0 +1,108 @@ +/* + * 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 c8486548d..dc2c62a25 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -17,6 +17,8 @@ */ #include +/* For stack parameters. */ +#include #include #include #include @@ -61,3 +63,10 @@ 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 1346da5cc..c5539cb05 100644 --- a/grub-core/kern/i386/dl.c +++ b/grub-core/kern/i386/dl.c @@ -40,42 +40,75 @@ grub_arch_dl_check_header (void *ehdr) /* 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_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { - Elf_Rel *rel, *max; + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; - 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; + /* 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) - 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 = (Elf_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf_Sym *) ((char *) mod->symtab - + mod->symsize * ELF_R_SYM (rel->r_info)); + entsize = s->sh_entsize; - switch (ELF_R_TYPE (rel->r_info)) - { - case R_386_32: - *addr += sym->st_value; - break; + 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; - 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)); - } - } + /* 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)); + } + } + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c index 46476e27e..6bd8f3e87 100644 --- a/grub-core/kern/i386/efi/init.c +++ b/grub-core/kern/i386/efi/init.c @@ -26,7 +26,6 @@ #include #include #include -#include void grub_machine_init (void) @@ -36,13 +35,7 @@ grub_machine_init (void) } void -grub_machine_fini (int flags) +grub_machine_fini (void) { - 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 deleted file mode 100644 index 4b93ba8e1..000000000 --- a/grub-core/kern/i386/efi/tsc.c +++ /dev/null @@ -1,40 +0,0 @@ -/* 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 (); - efi_call_1 (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/int.S b/grub-core/kern/i386/int.S index 862a54202..7edace404 100644 --- a/grub-core/kern/i386/int.S +++ b/grub-core/kern/i386/int.S @@ -44,13 +44,6 @@ 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 @@ -99,10 +92,6 @@ 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 e8f4f34b9..1cb422fef 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, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { 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, hook_data)) + if (hook (entry->addr, entry->len, entry->type)) break; entry = (void *) ((grub_addr_t) entry + entry->size + sizeof (entry->size)); diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 27bc68b8a..0841d8bb1 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -53,8 +52,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_uint64_t -grub_rtc_get_time_ms (void) +grub_uint32_t +grub_get_rtc (void) { struct grub_bios_int_registers regs; @@ -62,7 +61,7 @@ grub_rtc_get_time_ms (void) regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x1a, ®s); - return ((regs.ecx << 16) | (regs.edx & 0xffff)) * 55ULL; + return (regs.ecx << 16) | (regs.edx & 0xffff); } void @@ -155,56 +154,6 @@ 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; - 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; - - grub_bios_via_workaround1 = 0x090f; - grub_bios_via_workaround2 = 0x090f; - asm volatile ("wbinvd"); -} - void grub_machine_init (void) { @@ -212,10 +161,6 @@ 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); @@ -243,29 +188,48 @@ grub_machine_init (void) grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif - grub_machine_mmap_iterate (mmap_iterate_hook, NULL); + 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); compact_mem_regions (); - modend = grub_modules_get_end (); for (i = 0; i < num_regions; i++) - { - 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_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size); grub_tsc_init (); } void -grub_machine_fini (int flags) +grub_machine_fini (void) { - if (flags & GRUB_LOADER_FLAG_NORETURN) - grub_console_fini (); + 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 c0c3c3585..480ffa949 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; -} GRUB_PACKED; +} __attribute__((packed)); /* @@ -139,54 +139,51 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { - grub_uint32_t cont = 0; + grub_uint32_t cont; struct grub_machine_mmap_entry *entry = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - int e820_works = 0; - while (1) - { - grub_memset (entry, 0, sizeof (*entry)); + grub_memset (entry, 0, sizeof (entry)); - cont = grub_get_mmap_entry (entry, cont); + /* Check if grub_get_mmap_entry works. */ + cont = grub_get_mmap_entry (entry, 0); - if (!entry->size) - break; + 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->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; + if (! cont) + break; - if (! cont) - break; - } + grub_memset (entry, 0, sizeof (entry)); - if (!e820_works) + cont = grub_get_mmap_entry (entry, cont); + } + while (entry->size); + else { grub_uint32_t eisa_mmap = grub_get_eisa_mmap (); if (hook (0x0, ((grub_uint32_t) grub_get_conv_memsize ()) << 10, - GRUB_MEMORY_AVAILABLE, hook_data)) + GRUB_MEMORY_AVAILABLE)) return 0; if (eisa_mmap) { if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, - GRUB_MEMORY_AVAILABLE, hook_data) == 0) - hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE, - hook_data); + GRUB_MEMORY_AVAILABLE) == 0) + hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE); } else hook (0x100000, ((grub_uint32_t) grub_get_ext_memsize ()) << 10, - GRUB_MEMORY_AVAILABLE, hook_data); + GRUB_MEMORY_AVAILABLE); } return 0; diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index b8a9b33b4..6bb36c603 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 - calll *%eax + DATA32 call *%ax .endm /* diff --git a/grub-core/kern/i386/pit.c b/grub-core/kern/i386/pit.c new file mode 100644 index 000000000..82a17d3e0 --- /dev/null +++ b/grub-core/kern/i386/pit.c @@ -0,0 +1,56 @@ +/* + * 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 deleted file mode 100644 index 271b6fbfa..000000000 --- a/grub-core/kern/i386/qemu/init.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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_SUBCLASS_VGA) - cmd |= GRUB_PCI_COMMAND_IO_ENABLED - | GRUB_PCI_COMMAND_MEM_ENABLED; - - if (class == GRUB_PCI_CLASS_SUBCLASS_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 f449637ef..ffb61a47a 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, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { if (hook (0x0, (grub_addr_t) _start, - GRUB_MEMORY_AVAILABLE, hook_data)) + GRUB_MEMORY_AVAILABLE)) return 1; if (hook ((grub_addr_t) _end, 0xa0000 - (grub_addr_t) _end, - GRUB_MEMORY_AVAILABLE, hook_data)) + GRUB_MEMORY_AVAILABLE)) return 1; if (hook (GRUB_MEMORY_MACHINE_UPPER, 0x100000 - GRUB_MEMORY_MACHINE_UPPER, - GRUB_MEMORY_RESERVED, hook_data)) + GRUB_MEMORY_RESERVED)) return 1; /* Everything else is free. */ if (hook (0x100000, min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MEMORY_AVAILABLE, hook_data)) + GRUB_MEMORY_AVAILABLE)) 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, hook_data)) + GRUB_MEMORY_RESERVED)) return 1; if (above_4g != 0 && hook (0x100000000ULL, above_4g, - GRUB_MEMORY_AVAILABLE, hook_data)) + GRUB_MEMORY_AVAILABLE)) return 1; return 0; diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S index 0d89858d9..0761807ed 100644 --- a/grub-core/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -28,7 +29,7 @@ _start: jmp codestart - .org GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR + . = _start + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR VARIABLE(grub_core_entry_addr) .long 0 @@ -73,3 +74,5 @@ 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 998fdc756..6403b9699 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 - calll real_to_prot + DATA32 call real_to_prot .endm /* @@ -137,22 +137,7 @@ real_to_prot: /* load the GDT register */ xorw %ax, %ax movw %ax, %ds -#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 + DATA32 ADDR32 lgdt gdtdesc /* turn on protected mode */ movl %cr0, %eax @@ -160,7 +145,7 @@ real_to_prot: movl %eax, %cr0 /* jump to relocation, flush prefetch queue, and reload %cs */ - ljmpl $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg + DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg .code32 protcseg: @@ -193,9 +178,6 @@ 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. @@ -214,6 +196,8 @@ protcseg: * along with GRUB. If not, see . */ +#include + prot_to_real: /* just in case, set GDT */ lgdt gdtdesc @@ -255,7 +239,7 @@ tmpcseg: movl %eax, %cr0 /* flush prefetch queue, reload %cs */ - ljmpl $0, $realcseg + DATA32 ljmp $0, $realcseg realcseg: /* we are in real mode now @@ -276,6 +260,6 @@ realcseg: #endif /* return on new stack! */ - retl -#endif + DATA32 ret + .code32 diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c index 9293b161d..c4645f043 100644 --- a/grub-core/kern/i386/tsc.c +++ b/grub-core/kern/i386/tsc.c @@ -1,6 +1,7 @@ /* kern/i386/tsc.c - x86 TSC time source implementation * Requires Pentium or better x86 CPU that supports the RDTSC instruction. - * This module calibrates the TSC to real time. + * This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to + * real time. * * GRUB -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. @@ -23,56 +24,55 @@ #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 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; +/* Calibrated TSC rate. (In TSC ticks per millisecond.) */ +static grub_uint64_t tsc_ticks_per_ms; -static grub_uint64_t + +grub_uint64_t grub_tsc_get_time_ms (void) { - 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; + return tsc_boot_time + grub_divmod64 (grub_get_tsc (), tsc_ticks_per_ms, 0); } -static int -calibrate_tsc_hardcode (void) + +/* 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) { - grub_tsc_rate = 5368;/* 800 MHz */ - return 1; + /* 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); } void grub_tsc_init (void) { - if (!grub_cpu_is_tsc_supported ()) + 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 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 deleted file mode 100644 index 67990bfa6..000000000 --- a/grub-core/kern/i386/tsc_pit.c +++ /dev/null @@ -1,84 +0,0 @@ -/* 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 deleted file mode 100644 index c9c361699..000000000 --- a/grub-core/kern/i386/tsc_pmtimer.c +++ /dev/null @@ -1,88 +0,0 @@ -/* 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_uint32_t last; - grub_uint32_t cur, end; - grub_uint64_t start_tsc; - grub_uint64_t end_tsc; - int num_iter = 0; - - start = grub_inl (pmtimer) & 0xffffff; - last = start; - end = start + num_pm_ticks; - start_tsc = grub_get_tsc (); - while (1) - { - cur = grub_inl (pmtimer) & 0xffffff; - if (cur < last) - cur |= 0x1000000; - num_iter++; - if (cur >= end) - { - end_tsc = grub_get_tsc (); - return end_tsc - start_tsc; - } - /* Check for broken PM timer. - 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz) - if after this time we still don't have 1 ms on pmtimer, then - pmtimer is broken. - */ - if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) { - 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) - return 0; - pmtimer = fadt->pmtimer; - if (!pmtimer) - 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); - return 1; -} diff --git a/grub-core/kern/i386/xen/hypercall.S b/grub-core/kern/i386/xen/hypercall.S deleted file mode 100644 index 09d75c3a5..000000000 --- a/grub-core/kern/i386/xen/hypercall.S +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 deleted file mode 100644 index 91fbca859..000000000 --- a/grub-core/kern/i386/xen/pvh.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * 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 deleted file mode 100644 index fbe8300a7..000000000 --- a/grub-core/kern/i386/xen/startup.S +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 deleted file mode 100644 index 363c31858..000000000 --- a/grub-core/kern/i386/xen/startup_pvh.S +++ /dev/null @@ -1,81 +0,0 @@ -/* 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 deleted file mode 100644 index 8792b308d..000000000 --- a/grub-core/kern/i386/xen/tsc.c +++ /dev/null @@ -1,40 +0,0 @@ -/* 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 deleted file mode 100644 index 13efd308f..000000000 --- a/grub-core/kern/ia64/cache.c +++ /dev/null @@ -1,35 +0,0 @@ -/* 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 ebcf31629..7c22b0b06 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -23,10 +23,6 @@ #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 @@ -45,101 +41,239 @@ 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, - Elf_Shdr *s, grub_dl_segment_t seg) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { - Elf_Rela *rel, *max; + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + grub_uint64_t *gp, *gpptr; + struct ia64_trampoline *tr; - 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; + gp = (grub_uint64_t *) mod->base; + gpptr = (grub_uint64_t *) mod->got; + tr = mod->tramp; - if (seg->size < (rel->r_offset & ~3)) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); + /* 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; - addr = (grub_addr_t) seg->addr + rel->r_offset; - sym = (Elf_Sym *) ((char *) mod->symtab - + mod->symsize * ELF_R_SYM (rel->r_info)); + if (i == e->e_shnum) + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); - /* On the PPC the value does not have an explicit - addend, add it. */ - value = sym->st_value + rel->r_addend; + entsize = s->sh_entsize; - switch (ELF_R_TYPE (rel->r_info)) - { - case R_IA64_PCREL21B: - { - grub_int64_t noff; - if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) - { - 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; + 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; - 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; + /* 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++) + { + 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)); + } + } } - /* 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)); - } - } + } + return GRUB_ERR_NONE; } diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index c60159573..9394e32e2 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -22,206 +22,39 @@ #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; - for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu64 (e->e_shoff)); + /* Find a symbol table. */ + 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 (s->sh_type == grub_cpu_to_le32_compile_time (SHT_RELA)) - { - const Elf64_Rela *rel, *max; + if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) + break; - 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))) + 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) + { + 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))) { case R_IA64_PCREL21B: cntt++; @@ -233,9 +66,7 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, break; } } - *tramp = cntt * sizeof (struct grub_ia64_trampoline); - *got = cntg * sizeof (grub_uint64_t); - - return GRUB_ERR_NONE; + *tramp = cntt; + *got = cntg; } diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index f1965571b..7fa6fbf71 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; @@ -68,13 +68,20 @@ grub_machine_init (void) } void -grub_machine_fini (int flags) +grub_machine_fini (void) { - if (!(flags & GRUB_LOADER_FLAG_NORETURN)) - return; - grub_efi_fini (); - - if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) - grub_efi_memory_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;;"); } diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index 20cbbd761..dd04d3976 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 *) GRUB_IEEE1275_ENTRY_FN_ATTRIBUTE; +int (*grub_ieee1275_entry_fn) (void *); grub_ieee1275_phandle_t grub_ieee1275_chosen; grub_ieee1275_ihandle_t grub_ieee1275_mmu; @@ -43,6 +43,9 @@ 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) { @@ -73,8 +76,7 @@ grub_ieee1275_find_options (void) rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright", tmp, sizeof (tmp), 0); - if (rc >= 0 && !grub_strncmp (tmp, "SmartFirmware(tm)", - sizeof ("SmartFirmware(tm)") - 1)) + if (rc >= 0 && !grub_strncmp (tmp, SF, sizeof (SF) - 1)) is_smartfirmware = 1; rc = grub_ieee1275_get_property (root, "architecture", @@ -84,10 +86,8 @@ grub_ieee1275_find_options (void) rc = grub_ieee1275_get_property (root, "model", tmp, sizeof (tmp), 0); - if (rc >= 0 && (!grub_strcmp (tmp, "Emulated PC") - || !grub_strcmp (tmp, "IBM pSeries (emulated by qemu)"))) { + if (rc >= 0 && !grub_strcmp (tmp, "Emulated PC")) 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,9 +108,6 @@ 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 @@ -120,7 +117,6 @@ 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; } } @@ -191,12 +187,10 @@ grub_ieee1275_find_options (void) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); } - if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom) - || ! grub_ieee1275_finddevice ("/boot-rom", &bootrom)) + 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, "PPC Open Hack'Ware", - sizeof ("PPC Open Hack'Ware") - 1)) + 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); @@ -207,6 +201,9 @@ grub_ieee1275_find_options (void) } } +#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 86f81a3c4..98217029f 100644 --- a/grub-core/kern/ieee1275/ieee1275.c +++ b/grub-core/kern/ieee1275/ieee1275.c @@ -19,7 +19,6 @@ #include #include -#include #define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1) #define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0) @@ -483,91 +482,6 @@ 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) @@ -693,117 +607,3 @@ 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 d483e35ee..7d03a8aac 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -30,17 +30,10 @@ #include #include #include -#ifdef __sparc__ -#include -#endif #include #include #include #include -#include -#ifdef __i386__ -#include -#endif #ifdef __sparc__ #include #endif @@ -49,19 +42,11 @@ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) /* The maximum heap size we're going to claim */ -#ifdef __i386__ -#define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) -#else #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 */ -#ifdef __i386__ -#define HEAP_MAX_ADDR (unsigned long) (64 * 1024 * 1024) -#else #define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) -#endif extern char _start[]; extern char _end[]; @@ -91,18 +76,23 @@ grub_translate_ieee1275_path (char *filepath) } } -void (*grub_ieee1275_net_config) (const char *dev, char **device, char **path, - char *bootpath); +void (*grub_ieee1275_net_config) (const char *dev, + char **device, + char **path); void grub_machine_get_bootlocation (char **device, char **path) { - char *bootpath; + char bootpath[64]; /* XXX check length */ char *filename; char *type; - - bootpath = grub_ieee1275_get_boot_dev (); - if (! bootpath) - return; + + if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, + sizeof (bootpath), 0)) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + return; + } /* Transform an OF device path to a GRUB path. */ @@ -113,8 +103,6 @@ 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--; @@ -122,7 +110,7 @@ grub_machine_get_bootlocation (char **device, char **path) *ptr = 0; if (grub_ieee1275_net_config) - grub_ieee1275_net_config (canon, device, path, bootpath); + grub_ieee1275_net_config (canon, device, path); grub_free (dev); grub_free (canon); } @@ -144,7 +132,6 @@ grub_machine_get_bootlocation (char **device, char **path) *path = filename; } } - grub_free (bootpath); } /* Claim some available memory in the first /memory node. */ @@ -156,77 +143,74 @@ grub_claim_heap (void) + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); } #else -/* Helper for grub_claim_heap. */ -static int -heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, - void *data) -{ - unsigned long *total = 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; - } - } - len -= 1; /* Required for some firmware. */ - - /* Never exceed HEAP_MAX_SIZE */ - if (*total + len > HEAP_MAX_SIZE) - len = HEAP_MAX_SIZE - *total; - - /* 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; -} - static void grub_claim_heap (void) { unsigned long total = 0; - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) - heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, - 1, &total); + 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; + + 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; + } + } + len -= 1; /* Required for some firmware. */ + + /* Never exceed HEAP_MAX_SIZE */ + if (total + len > HEAP_MAX_SIZE) + len = HEAP_MAX_SIZE - total; + + /* 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, &total); + grub_machine_mmap_iterate (heap_init); } #endif @@ -270,6 +254,8 @@ grub_parse_cmdline (void) } } +static grub_uint64_t ieee1275_get_time_ms (void); + grub_addr_t grub_modbase; void @@ -283,36 +269,22 @@ 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 (); -#ifdef __i386__ - grub_tsc_init (); -#else - grub_install_get_time_ms (grub_rtc_get_time_ms); -#endif + grub_install_get_time_ms (ieee1275_get_time_ms); } void -grub_machine_fini (int flags) +grub_machine_fini (void) { - if (flags & GRUB_LOADER_FLAG_NORETURN) - { -#ifdef __sparc__ - grub_obdisk_fini (); -#else - grub_ofdisk_fini (); -#endif - grub_console_fini (); - } + grub_ofdisk_fini (); + grub_console_fini (); } -grub_uint64_t -grub_rtc_get_time_ms (void) +static grub_uint64_t +ieee1275_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 bf325eadf..2e4e085bb 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, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t memory; - grub_uint32_t available[128]; + grub_uint32_t available[32]; grub_ssize_t available_size; grub_uint32_t address_cells = 1; grub_uint32_t size_cells = 1; @@ -49,9 +49,6 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) 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)) { @@ -75,7 +72,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) if (size_cells == 2) size = (size << 32) | available[i++]; - if (hook (address, size, GRUB_MEMORY_AVAILABLE, hook_data)) + if (hook (address, size, GRUB_MEMORY_AVAILABLE)) break; } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 4d493ab76..40abaa373 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -32,231 +32,184 @@ enum grub_ieee1275_parse_type GRUB_PARSE_DEVICE_TYPE }; -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) +/* Walk children of 'devpath', calling hook for each. */ +int +grub_children_iterate (const char *devpath, + int (*hook) (struct grub_ieee1275_devalias *alias)) { grub_ieee1275_phandle_t dev; - - 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; - - if (grub_ieee1275_child (dev, &alias->phandle)) - return; - - 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 (alias->type); - return; - } - alias->parent_path = grub_strdup (devpath); - if (!alias->parent_path) - { - grub_free (alias->path); - grub_free (alias->type); - return; - } - - alias->name = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!alias->name) - { - grub_free (alias->path); - grub_free (alias->type); - grub_free (alias->parent_path); - return; - } - if (!fill_alias (alias)) - grub_ieee1275_children_peer (alias); -} - -static int -iterate_recursively (const char *path, - int (*hook) (struct grub_ieee1275_devalias *alias)) -{ - struct grub_ieee1275_devalias alias; + grub_ieee1275_phandle_t child; + char *childtype, *childpath; + char *childname; int ret = 0; - FOR_IEEE1275_DEVCHILDREN(path, alias) + if (grub_ieee1275_finddevice (devpath, &dev)) + return 0; + + if (grub_ieee1275_child (dev, &child)) + return 0; + + childtype = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!childtype) + return 0; + childpath = grub_malloc (IEEE1275_MAX_PATH_LEN); + if (!childpath) { + grub_free (childtype); + return 0; + } + childname = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!childname) + { + grub_free (childpath); + grub_free (childtype); + return 0; + } + + do + { + struct grub_ieee1275_devalias alias; + grub_ssize_t actual; + + if (grub_ieee1275_get_property (child, "device_type", childtype, + IEEE1275_MAX_PROP_LEN, &actual)) + childtype[0] = 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; ret = hook (&alias); if (ret) break; - ret = iterate_recursively (alias.path, hook); - if (ret) - break; } - grub_ieee1275_devalias_free (&alias); + while (grub_ieee1275_peer (child, &child) != -1); + + grub_free (childname); + grub_free (childpath); + grub_free (childtype); + return ret; } int grub_ieee1275_devices_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) { - return iterate_recursively ("/", hook); + 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); } -void -grub_ieee1275_devalias_init_iterator (struct grub_ieee1275_devalias *alias) +/* 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)) { - alias->name = 0; - alias->path = 0; - alias->parent_path = 0; - alias->type = 0; + grub_ieee1275_phandle_t aliases; + char *aliasname, *devtype; + grub_ssize_t actual; + struct grub_ieee1275_devalias alias; + int ret = 0; - grub_dprintf ("devalias", "iterating aliases\n"); + if (grub_ieee1275_finddevice ("/aliases", &aliases)) + return 0; - 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) + aliasname = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!aliasname) + return 0; + devtype = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!devtype) { - grub_free (alias->name); - alias->name = 0; - return; + grub_free (aliasname); + return 0; } - alias->name[0] = '\0'; -} + /* Find the first property. */ + aliasname[0] = '\0'; -int -grub_ieee1275_devalias_next (struct grub_ieee1275_devalias *alias) -{ - if (!alias->name) - return 0; - while (1) + while (grub_ieee1275_next_property (aliases, aliasname, aliasname) > 0) { + grub_ieee1275_phandle_t dev; grub_ssize_t pathlen; - grub_ssize_t actual; - char *tmp; + char *devpath; - 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_dprintf ("devalias", "devalias name = %s\n", aliasname); - grub_dprintf ("devalias", "devalias name = %s\n", alias->name); - - grub_ieee1275_get_property_length (alias->parent_dev, alias->name, &pathlen); + grub_ieee1275_get_property_length (aliases, aliasname, &pathlen); /* The property `name' is a special case we should skip. */ - if (grub_strcmp (alias->name, "name") == 0) + if (!grub_strcmp (aliasname, "name")) 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; - alias->path = grub_malloc (pathlen + 1); - if (! alias->path) + devpath = grub_malloc (pathlen + 1); + if (! devpath) { - grub_ieee1275_devalias_free (alias); + grub_free (devtype); + grub_free (aliasname); return 0; } - if (grub_ieee1275_get_property (alias->parent_dev, alias->name, alias->path, - pathlen, &actual) || actual < 0) + if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen, + &actual) || actual < 0) { - grub_dprintf ("devalias", "get_property (%s) failed\n", alias->name); - grub_free (alias->path); - continue; + grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname); + goto nextprop; } if (actual > pathlen) actual = pathlen; - alias->path[actual] = '\0'; - alias->path[pathlen] = '\0'; + devpath[actual] = '\0'; + devpath[pathlen] = '\0'; - if (grub_ieee1275_finddevice (alias->path, &alias->phandle)) + if (grub_ieee1275_finddevice (devpath, &dev)) { - grub_dprintf ("devalias", "finddevice (%s) failed\n", alias->path); - grub_free (alias->path); - alias->path = 0; - continue; + grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath); + goto nextprop; } - if (grub_ieee1275_get_property (alias->phandle, "device_type", alias->type, + if (grub_ieee1275_get_property (dev, "device_type", devtype, IEEE1275_MAX_PROP_LEN, &actual)) { /* NAND device don't have device_type property. */ - alias->type[0] = 0; + devtype[0] = 0; } - return 1; + + alias.name = aliasname; + alias.path = devpath; + alias.type = devtype; + ret = hook (&alias); + +nextprop: + grub_free (devpath); + if (ret) + break; } + + grub_free (devtype); + grub_free (aliasname); + return ret; } /* Call the "map" method of /chosen/mmu. */ @@ -271,7 +224,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 __sparc__ +#ifdef GRUB_MACHINE_SPARC64 grub_ieee1275_cell_t phys_high; #endif grub_ieee1275_cell_t phys_low; @@ -279,7 +232,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 __sparc__ +#ifdef GRUB_MACHINE_SPARC64 7, #else 6, @@ -287,7 +240,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 __sparc__ +#ifdef GRUB_MACHINE_SPARC64 args.phys_high = 0; #endif args.phys_low = phys; @@ -333,28 +286,37 @@ grub_ieee1275_get_devargs (const char *path) } /* Get the device path of the Open Firmware node name `path'. */ -char * +static char * grub_ieee1275_get_devname (const char *path) { char *colon = grub_strchr (path, ':'); + char *newpath = 0; int pathlen = grub_strlen (path); - struct grub_ieee1275_devalias curalias; + 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; + } + if (colon) pathlen = (int)(colon - path); /* Try to find an alias for this device. */ - 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; - } + grub_devalias_iterate (match_alias); - return grub_strndup (path, pathlen); + if (! newpath) + newpath = grub_strndup (path, pathlen); + + return newpath; } static char * @@ -479,9 +441,6 @@ 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) @@ -564,30 +523,3 @@ 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/main.c b/grub-core/kern/main.c index 9cad0c448..326244419 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -30,10 +30,8 @@ #include #include -#ifdef GRUB_MACHINE_PCBIOS -#include -#endif - +/* 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) { @@ -47,6 +45,7 @@ grub_modules_get_end (void) return grub_modbase + modinfo->size; } +#endif /* Load all modules in core. */ static void @@ -68,8 +67,6 @@ grub_load_modules (void) } } -static char *load_config; - static void grub_load_config (void) { @@ -79,17 +76,9 @@ grub_load_config (void) /* Not an embedded config, skip. */ if (header->type != OBJ_TYPE_CONFIG) continue; - - 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; + + grub_parser_execute ((char *) header + + sizeof (struct grub_module_header)); break; } } @@ -125,21 +114,6 @@ 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; @@ -157,6 +131,8 @@ 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; @@ -192,16 +168,7 @@ grub_set_prefix_and_root (void) else grub_free (fwdevice); if (fwpath && !path) - { - 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; - } + path = fwpath; else grub_free (fwpath); if (device) @@ -236,30 +203,6 @@ grub_load_normal_mode (void) grub_command_execute ("normal", 0, 0); } -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) @@ -267,17 +210,11 @@ grub_main (void) /* First of all, initialize the machine. */ grub_machine_init (); - grub_boot_time ("After machine init."); - /* Hello. */ grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); grub_printf ("Welcome to GRUB!\n\n"); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); - 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 @@ -285,28 +222,15 @@ grub_main (void) #endif grub_load_modules (); - grub_boot_time ("After loading embedded modules."); - /* 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_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_config (); 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 3834a1490..44b417147 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -34,8 +34,6 @@ #include #include #include -#include -#include const char *type_names[] = { #ifdef GRUB_CPU_WORDS_BIGENDIAN @@ -45,16 +43,13 @@ 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", -#ifndef GRUB_CPU_WORDS_BIGENDIAN - "other", -#endif - "line", "network", NULL + "keyboard", "term", "other", "line", "network", NULL }; static int iterate_rec (const char *prefix, const struct grub_arc_component *parent, - grub_arc_iterate_devs_hook_t hook, void *hook_data, + int (*hook) (const char *name, + const struct grub_arc_component *comp), int alt_names) { const struct grub_arc_component *comp; @@ -72,13 +67,12 @@ 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, hook_data)) + if (hook (name, comp)) { grub_free (name); return 1; } - if (iterate_rec ((parent ? name : prefix), comp, hook, hook_data, - alt_names)) + if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names)) { grub_free (name); return 1; @@ -89,15 +83,15 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent, } int -grub_arc_iterate_devs (grub_arc_iterate_devs_hook_t hook, void *hook_data, +grub_arc_iterate_devs (int (*hook) (const char *name, + const struct grub_arc_component *comp), int alt_names) { - return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, hook_data, - alt_names); + return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names); } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { struct grub_arc_memory_descriptor *cur = NULL; while (1) @@ -126,105 +120,20 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) break; } if (hook (((grub_uint64_t) cur->start_page) << 12, - ((grub_uint64_t) cur->num_pages) << 12, type, hook_data)) + ((grub_uint64_t) cur->num_pages) << 12, type)) 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_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_modbase = GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size; grub_console_init_early (); /* FIXME: measure this. */ @@ -244,10 +153,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) start < (modend & 0x1fffffff)) - start = (modend & 0x1fffffff); - if ((grub_uint64_t) end > 0x20000000) - end = 0x20000000; + 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 (end > start) grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000), end - start); @@ -259,7 +168,7 @@ grub_machine_init (void) } void -grub_machine_fini (int flags __attribute__ ((unused))) +grub_machine_fini (void) { } @@ -287,177 +196,3 @@ 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_get_size (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 fa331eca1..141c030e9 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_op 1, 0($t0) + cache 1, 0($t0) #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache_op 1, 1($t0) - cache_op 1, 2($t0) - cache_op 1, 3($t0) + cache 1, 1($t0) + cache 1, 2($t0) + cache 1, 3($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 1b @@ -34,37 +34,36 @@ FUNCTION (grub_arch_sync_dma_caches) bne $t1, $zero, 1b addiu $t0, $t0, 0x4 #endif - sync_op + sync move $t0, $t2 subu $t1, $t3, $t2 2: #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache_op 0, 0($t0) + cache 0, 0($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 2b addiu $t0, $t0, 0x20 #else - cache_op 0, 0($t0) + cache 0, 0($t0) addiu $t1, $t1, -4 bne $t1, $zero, 2b addiu $t0, $t0, 0x4 #endif - sync_op + sync move $t0, $t2 subu $t1, $t3, $t2 2: #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache_op 23, 0($t0) + cache 23, 0($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 2b addiu $t0, $t0, 0x20 #else - cache_op 23, 0($t0) + cache 23, 0($t0) addiu $t1, $t1, -0x4 bne $t1, $zero, 2b addiu $t0, $t0, 0x4 #endif - sync_op + sync - jr $ra - nop + jr $ra \ No newline at end of file diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index 89961a0f7..a5435cf51 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -1,17 +1,3 @@ -#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 @@ -22,12 +8,12 @@ move $t0, $t2 subu $t1, $t3, $t2 1: - cache_op 1, 0($t0) + cache 1, 0($t0) /* All four ways. */ #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache_op 1, 1($t0) - cache_op 1, 2($t0) - cache_op 1, 3($t0) + cache 1, 1($t0) + cache 1, 2($t0) + cache 1, 3($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 1b addiu $t0, $t0, 0x20 @@ -37,11 +23,11 @@ bne $t1, $zero, 1b addiu $t0, $t0, 0x4 #endif - sync_op + sync move $t0, $t2 subu $t1, $t3, $t2 2: - cache_op 0, 0($t0) + cache 0, 0($t0) #ifdef GRUB_MACHINE_MIPS_LOONGSON addiu $t1, $t1, -0x20 bne $t1, $zero, 2b @@ -51,4 +37,4 @@ bne $t1, $zero, 2b addiu $t0, $t0, 0x4 #endif - sync_op + sync diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c index 5d7d299c7..ee65c9d18 100644 --- a/grub-core/kern/mips/dl.c +++ b/grub-core/kern/mips/dl.c @@ -27,7 +27,6 @@ /* 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 @@ -52,215 +51,199 @@ grub_arch_dl_check_header (void *ehdr) #pragma GCC diagnostic ignored "-Wcast-align" +/* Relocate symbols. */ grub_err_t -grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, - grub_size_t *got) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { - const Elf_Ehdr *e = ehdr; - const Elf_Shdr *s; - /* FIXME: suboptimal. */ - grub_size_t gp_size = 0; + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; unsigned i; + grub_size_t gp_size = 0; + /* FIXME: suboptimal. */ + grub_uint32_t *gp, *gpptr; + grub_uint32_t gp0; - *tramp = 0; - *got = 0; - - for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); + /* Find a symbol table. */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); i < e->e_shnum; - i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) + 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)) if (s->sh_type == SHT_REL) { - const Elf_Rel *rel, *max; + grub_dl_segment_t seg; - 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; - } + /* 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; + } + } } if (gp_size > 0x08000) return grub_error (GRUB_ERR_OUT_OF_RANGE, "__gnu_local_gp is too big\n"); - *got = gp_size; + gpptr = gp = grub_malloc (gp_size); + if (!gp) + return grub_errno; - return GRUB_ERR_NONE; -} + 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; -/* 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; + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; - 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: + if (seg) { - grub_uint32_t value; - Elf_Rel *rel2; + Elf_Rel *rel, *max; -#ifdef GRUB_CPU_WORDS_BIGENDIAN - addr += 2; -#endif + 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; - /* 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; + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); - 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) + 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)) { - sym_value += *(grub_int16_t *) - ((char *) seg->addr + rel2->r_offset + case R_MIPS_HI16: + { + grub_uint32_t value; + Elf_Rel *rel2; + #ifdef GRUB_CPU_WORDS_BIGENDIAN - + 2 + 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; } - 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; } @@ -269,6 +252,5 @@ 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 14b8752ec..353f679e6 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -36,3 +36,9 @@ 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 7b96531b9..19f2d639b 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -40,57 +40,54 @@ #include grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, - GRUB_MEMORY_AVAILABLE, hook_data); + GRUB_MEMORY_AVAILABLE); hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, - GRUB_MEMORY_AVAILABLE, hook_data); + GRUB_MEMORY_AVAILABLE); 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; @@ -113,7 +110,7 @@ init_pci (void) *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_ADDRESS_REG1)) = 0; - grub_pci_iterate (set_card, NULL); + grub_pci_iterate (set_card); } void @@ -129,19 +126,12 @@ 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; } @@ -210,13 +200,11 @@ 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 - || grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG_3A) + if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) grub_at_keyboard_init (); grub_terminfo_init (); @@ -226,49 +214,16 @@ grub_machine_init (void) } void -grub_machine_fini (int flags __attribute__ ((unused))) +grub_machine_fini (void) { } -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: { @@ -289,13 +244,6 @@ 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")); @@ -309,12 +257,6 @@ 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 be88b77d2..782f17fbf 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -49,7 +49,7 @@ grub_machine_init (void) } /* FIXME: measure this. */ - grub_arch_cpuclock = 200000000; + grub_arch_cpuclock = 64000000; modend = grub_modules_get_end (); grub_mm_init_region ((void *) modend, grub_arch_memsize @@ -57,6 +57,8 @@ grub_machine_init (void) grub_install_get_time_ms (grub_rtc_get_time_ms); + grub_font_init (); + grub_keylayouts_init (); grub_at_keyboard_init (); @@ -67,10 +69,12 @@ grub_machine_init (void) grub_serial_init (); grub_boot_init (); + + grub_gfxterm_init (); } void -grub_machine_fini (int flags __attribute__ ((unused))) +grub_machine_fini (void) { } @@ -88,18 +92,12 @@ grub_halt (void) } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { - hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE, hook_data); + hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE); 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 1fdb58aca..2476038bc 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -22,7 +22,6 @@ #include #include #include -#include #define BASE_ADDR 8 @@ -37,7 +36,7 @@ start: bal cont nop - .org GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE + . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE VARIABLE(grub_total_modules_size) .long 0 @@ -74,6 +73,7 @@ cont: #endif /* Move the modules out of BSS. */ +#ifndef GRUB_MACHINE_ARC lui $t2, %hi(__bss_start) addiu $t2, %lo(__bss_start) @@ -96,13 +96,14 @@ cont: modulesmovcont: beq $t3, $0, modulesmovdone nop - lb GRUB_ASM_T4, 0($t2) - sb GRUB_ASM_T4, 0($t1) + lb $t4, 0($t2) + sb $t4, 0($t1) addiu $t2, $t2, -1 addiu $t1, $t1, -1 b modulesmovcont addiu $t3, $t3, -1 modulesmovdone: +#endif /* Clean BSS. */ @@ -117,10 +118,10 @@ bsscont: bne $t3, $0, bsscont nop - lui $t9, %hi(grub_main) - addiu $t9, %lo(grub_main) + lui $t1, %hi(grub_main) + addiu $t1, %lo(grub_main) lui $sp, %hi(GRUB_MACHINE_MEMORY_STACK_HIGH) - jr $t9 + jr $t1 addiu $sp, $sp, %lo(GRUB_MACHINE_MEMORY_STACK_HIGH) diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index a278e069b..95d46245e 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -25,39 +25,8 @@ #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 - } 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 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); -} +grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args); static int grub_iswordseparator (int c) @@ -95,6 +64,25 @@ 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) { @@ -106,6 +94,17 @@ 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, ...) { @@ -158,28 +157,17 @@ int grub_err_printf (const char *fmt, ...) __attribute__ ((alias("grub_printf"))); #endif -int -grub_debug_enabled (const char * condition) -{ - const char *debug; - - debug = grub_env_get ("debug"); - if (!debug) - return 0; - - if (grub_strword (debug, "all") || grub_strword (debug, condition)) - return 1; - - return 0; -} - 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 (grub_debug_enabled (condition)) + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, condition)) { grub_printf ("%s:%d: ", file, line); va_start (args, fmt); @@ -192,16 +180,15 @@ grub_real_dprintf (const char *file, const int line, const char *condition, #define PREALLOC_SIZE 255 int -grub_vprintf (const char *fmt, va_list ap) +grub_vprintf (const char *fmt, va_list args) { grub_size_t s; static char buf[PREALLOC_SIZE + 1]; char *curbuf = buf; - struct printf_args args; + va_list ap2; + va_copy (ap2, args); - parse_printf_args (fmt, &args, ap); - - s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, &args); + s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args); if (s > PREALLOC_SIZE) { curbuf = grub_malloc (s + 1); @@ -215,16 +202,16 @@ grub_vprintf (const char *fmt, va_list ap) curbuf = buf; } else - s = grub_vsnprintf_real (curbuf, s, fmt, &args); + s = grub_vsnprintf_real (curbuf, s, fmt, ap2); } - free_printf_args (&args); + va_end (ap2); grub_xputs (curbuf); if (curbuf != buf) grub_free (curbuf); - + return s; } @@ -245,6 +232,16 @@ 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) @@ -350,9 +347,15 @@ 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 * restrict str, const char ** const restrict end, - int base) +grub_strtoul (const char *str, char **end, int base) { unsigned long long num; @@ -369,15 +372,13 @@ grub_strtoul (const char * restrict str, const char ** const restrict end, } unsigned long long -grub_strtoull (const char * restrict str, const char ** const restrict end, - int base) +grub_strtoull (const char *str, char **end, int base) { unsigned long long num = 0; int found = 0; /* Skip white spaces. */ - /* grub_isspace checks that *str != '\0'. */ - while (grub_isspace (*str)) + while (*str && grub_isspace (*str)) str++; /* Guess the base, if not specified. The prefix `0x' means 16, and @@ -404,13 +405,12 @@ grub_strtoull (const char * restrict str, const char ** const restrict end, unsigned long digit; digit = grub_tolower (*str) - '0'; - if (digit >= 'a' - '0') - digit += '0' - 'a' + 10; - else if (digit > 9) - break; - - if (digit >= (unsigned long) base) - break; + if (digit > 9) + { + digit += '0' - 'a' + 10; + if (digit >= (unsigned long) base) + break; + } found = 1; @@ -471,15 +471,6 @@ 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) { @@ -496,13 +487,13 @@ grub_memset (void *s, int c, grub_size_t len) while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1))) { - *(VOLATILE_CLANG grub_uint8_t *) p = pattern8; + *(grub_uint8_t *) p = pattern8; p = (grub_uint8_t *) p + 1; len--; } while (len >= sizeof (unsigned long)) { - *(VOLATILE_CLANG unsigned long *) p = patternl; + *(unsigned long *) p = patternl; p = (unsigned long *) p + 1; len -= sizeof (unsigned long); } @@ -510,13 +501,23 @@ grub_memset (void *s, int c, grub_size_t len) while (len > 0) { - *(VOLATILE_CLANG grub_uint8_t *) p = pattern8; + *(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) @@ -558,11 +559,6 @@ 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) { @@ -571,7 +567,6 @@ 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--) { @@ -598,10 +593,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 inline char * +static char * grub_lltoa (char *str, int c, unsigned long long n) { - unsigned base = ((c == 'x') || (c == 'X')) ? 16 : 10; + unsigned base = (c == 'x') ? 16 : 10; char *p; if ((long long) n < 0 && c == 'd') @@ -616,7 +611,7 @@ grub_lltoa (char *str, int c, unsigned long long n) do { unsigned d = (unsigned) (n & 0xf); - *p++ = (d > 9) ? d + ((c == 'x') ? 'a' : 'A') - 10 : d + '0'; + *p++ = (d > 9) ? d + 'a' - 10 : d + '0'; } while (n >>= 4); else @@ -636,21 +631,38 @@ grub_lltoa (char *str, int c, unsigned long long n) return p; } -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 max_len, const char *fmt0, va_list args_in) { - 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); - args->count = 0; + void write_char (unsigned char ch) + { + if (count < max_len) + *str++ = 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 *)); + 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); + } fmt = fmt0; while ((c = *fmt++) != 0) @@ -658,68 +670,66 @@ parse_printf_args (const char *fmt0, struct printf_args *args, if (c != '%') continue; - if (*fmt =='-') + if (*fmt && *fmt =='-') fmt++; - while (grub_isdigit (*fmt)) + while (*fmt && grub_isdigit (*fmt)) fmt++; - if (*fmt == '$') + if (*fmt && *fmt == '$') fmt++; - if (*fmt =='-') + if (*fmt && *fmt =='-') fmt++; - while (grub_isdigit (*fmt)) + while (*fmt && grub_isdigit (*fmt)) fmt++; - if (*fmt =='.') + if (*fmt && *fmt =='.') fmt++; - while (grub_isdigit (*fmt)) + while (*fmt && 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': case 'x': - case 'X': case 'u': case 'd': case 'c': case 'C': case 's': - args->count++; + count_args++; break; } } - 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) - { - grub_errno = GRUB_ERR_NONE; - args->ptr = args->prealloc; - args->count = ARRAY_SIZE (args->prealloc); - } - } + 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]; - grub_memset (args->ptr, 0, args->count * sizeof (args->ptr[0])); + grub_memset (types, 0, sizeof (types)); fmt = fmt0; n = 0; while ((c = *fmt++) != 0) { int longfmt = 0; + int longlongfmt = 0; grub_size_t curn; const char *p; @@ -728,128 +738,106 @@ parse_printf_args (const char *fmt0, struct printf_args *args, curn = n++; - if (*fmt =='-') + if (*fmt && *fmt =='-') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + + if (*fmt && *fmt =='.') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) fmt++; p = fmt; - while (grub_isdigit (*fmt)) - fmt++; - - if (*fmt == '$') + if (*fmt && *fmt == '$') { curn = grub_strtoull (p, 0, 10) - 1; fmt++; } - if (*fmt =='-') - fmt++; - - while (grub_isdigit (*fmt)) - fmt++; - - if (*fmt =='.') - fmt++; - - while (grub_isdigit (*fmt)) + while (*fmt && 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 (c == 'l') - { - c = *fmt++; - longfmt = 2; - } - if (curn >= args->count) + if (curn >= count_args) continue; switch (c) { case 'x': - case 'X': case 'u': - args->ptr[curn].type = UNSIGNED_INT + longfmt; - break; case 'd': - args->ptr[curn].type = INT + longfmt; + if (longlongfmt) + types[curn] = LONGLONG; + else if (longfmt) + types[curn] = LONG; + else + types[curn] = INT; break; case 'p': case 's': - if (sizeof (void *) == sizeof (long long)) - args->ptr[curn].type = UNSIGNED_LONGLONG; - else - args->ptr[curn].type = UNSIGNED_INT; + types[curn] = POINTER; + break; + case 'c': + types[curn] = INT; break; case 'C': - case 'c': - args->ptr[curn].type = INT; + types[curn] = WCHAR; break; } } - for (n = 0; n < args->count; n++) - switch (args->ptr[n].type) + for (n = 0; n < count_args; n++) + switch (types[n]) { + 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->ptr[n].ll = va_arg (args_in, int); + args[n].i = va_arg (args_in, int); break; case 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); + args[n].l = va_arg (args_in, long); break; case LONGLONG: - case UNSIGNED_LONGLONG: - args->ptr[n].ll = va_arg (args_in, long long); + args[n].ll = va_arg (args_in, long long); 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 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 = ' '; - char rightfill = 0; + int rightfill = 0; + int longfmt = 0; + int longlongfmt = 0; + int unsig = 0; grub_size_t curn; - + if (c != '%') { - write_char (str, &count, max_len,c); + write_char (c); continue; } @@ -857,26 +845,44 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, rescan:; - if (*fmt =='-') + if (*fmt && *fmt =='-') { rightfill = 1; fmt++; } + p = (char *) fmt; /* Read formatting parameters. */ - if (grub_isdigit (*fmt)) + while (*p && grub_isdigit (*p)) + p++; + + if (p > fmt) { - if (fmt[0] == '0') + char s[p - fmt + 1]; + grub_strncpy (s, fmt, p - fmt); + s[p - fmt] = 0; + if (s[0] == '0') zerofill = '0'; - format1 = grub_strtoul (fmt, &fmt, 10); + format1 = grub_strtoul (s, 0, 10); + fmt = p; } - if (*fmt == '.') - fmt++; - - if (grub_isdigit (*fmt)) - format2 = grub_strtoul (fmt, &fmt, 10); + if (*p && *p == '.') + { + p++; + fmt++; + while (*p && grub_isdigit (*p)) + p++; + 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 == '$') { curn = format1 - 1; @@ -891,59 +897,55 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, c = *fmt++; if (c == 'l') - c = *fmt++; - if (c == 'l') - c = *fmt++; - - if (c == '%') { - write_char (str, &count, max_len,c); - n--; - continue; + longfmt = 1; + c = *fmt++; + if (c == 'l') + { + longlongfmt = 1; + c = *fmt++; + } } - if (curn >= args->count) + if (curn >= count_args) continue; - long long curarg = args->ptr[curn].ll; - switch (c) { case 'p': - write_char (str, &count, max_len, '0'); - write_char (str, &count, max_len, 'x'); + write_str ("0x"); c = 'x'; + longlongfmt |= (sizeof (void *) == sizeof (long long)); /* Fall through. */ case 'x': - case 'X': case 'u': + unsig = 1; + /* Fall through. */ case 'd': - { - char tmp[32]; - const char *p = tmp; - grub_size_t len; - grub_size_t fill; - - len = grub_lltoa (tmp, c, curarg) - 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); - } + 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)); break; case 'c': - write_char (str, &count, max_len,curarg & 0xff); + write_char (args[curn].i & 0xff); break; case 'C': { - grub_uint32_t code = curarg; + grub_uint32_t code = args[curn].w; int shift; unsigned mask; @@ -962,11 +964,21 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, shift = 12; mask = 0xe0; } - else if (code <= 0x10ffff) + else if (code <= 0x1fffff) { shift = 18; mask = 0xf0; } + else if (code <= 0x3ffffff) + { + shift = 24; + mask = 0xf8; + } + else if (code <= 0x7fffffff) + { + shift = 30; + mask = 0xfc; + } else { code = '?'; @@ -974,49 +986,44 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, mask = 0; } - write_char (str, &count, max_len,mask | (code >> shift)); + write_char (mask | (code >> shift)); for (shift -= 6; shift >= 0; shift -= 6) - write_char (str, &count, max_len,0x80 | (0x3f & (code >> shift))); + write_char (0x80 | (0x3f & (code >> shift))); } break; case 's': - { - grub_size_t len = 0; - grub_size_t fill; - const char *p = ((char *) (grub_addr_t) curarg) ? : "(null)"; - grub_size_t i; + p = args[curn].p; + if (p) + { + grub_size_t len = 0; + while (len < format2 && p[len]) + len++; - while (len < format2 && p[len]) - len++; + if (!rightfill && len < format1) + write_fill (zerofill, format1 - len); - fill = len < format1 ? format1 - len : 0; + grub_size_t i; + for (i = 0; i < len; i++) + write_char (*p++); - 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); - } + if (rightfill && len < format1) + write_fill (zerofill, format1 - len); + } + else + write_str ("(null)"); break; default: - write_char (str, &count, max_len,c); + write_char (c); break; } } - if (count < max_len) - str[count] = '\0'; - else - str[max_len] = '\0'; + *str = '\0'; + return count; } @@ -1024,18 +1031,13 @@ 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--; - parse_printf_args (fmt, &args, ap); - - ret = grub_vsnprintf_real (str, n, fmt, &args); - - free_printf_args (&args); + ret = grub_vsnprintf_real (str, n, fmt, ap); return ret < n ? ret : n; } @@ -1058,26 +1060,22 @@ 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) - { - free_printf_args (&args); - return NULL; - } + return NULL; - s = grub_vsnprintf_real (ret, as, fmt, &args); + va_copy (ap2, ap); + + s = grub_vsnprintf_real (ret, as, fmt, ap2); + + va_end (ap2); if (s <= as) - { - free_printf_args (&args); - return ret; - } + return ret; grub_free (ret); as = s; @@ -1098,7 +1096,7 @@ grub_xasprintf (const char *fmt, ...) } /* Abort GRUB. This function does not return. */ -static void __attribute__ ((noreturn)) +void grub_abort (void) { grub_printf ("\nAborted."); @@ -1114,56 +1112,26 @@ grub_abort (void) grub_exit (); } -void -grub_fatal (const char *fmt, ...) +#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))) { - va_list ap; - - va_start (ap, fmt); - grub_vprintf (_(fmt), ap); - va_end (ap); - - grub_refresh (); - - grub_abort (); -} - -#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 + +#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL) +void __register_frame_info (void) +{ +} + +void __deregister_frame_info (void) +{ +} +#endif + diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index f2822a836..9f08e05bf 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -67,10 +67,8 @@ #include #include #include -#include #ifdef MM_DEBUG -# undef grub_calloc # undef grub_malloc # undef grub_zalloc # undef grub_realloc @@ -119,45 +117,14 @@ grub_mm_init_region (void *addr, grub_size_t size) grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size); #endif - /* 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; - - for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) - if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) - { - r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); - *r = *q; - r->pre_size += size; - - if (r->pre_size >> GRUB_MM_ALIGN_LOG2) - { - h = (grub_mm_header_t) (r + 1); - h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); - h->magic = GRUB_MM_ALLOC_MAGIC; - r->size += h->size << GRUB_MM_ALIGN_LOG2; - r->pre_size &= (GRUB_MM_ALIGN - 1); - *p = r; - grub_free (h + 1); - } - *p = r; - return; - } - /* 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 + (char *) r - (char *) addr + sizeof (*r)) + if (size < GRUB_MM_ALIGN) return; - size -= (char *) r - (char *) addr + sizeof (*r); - h = (grub_mm_header_t) (r + 1); h->next = h; h->magic = GRUB_MM_FREE_MAGIC; @@ -196,7 +163,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) { grub_off_t extra; - extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); + extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) % align; if (extra) extra = align - extra; @@ -300,10 +267,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) /* 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. */ - /* So do it only for chunks under 64K. */ - if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) - || *first == p) - *first = q; + *first = q; return p + 1; } @@ -327,15 +291,6 @@ grub_memalign (grub_size_t align, grub_size_t size) if (!grub_mm_base) goto fail; - if (size > ~(grub_size_t) align) - goto fail; - - /* We currently assume at least a 32-bit grub_size_t, - so limiting allocations to - 1MiB - in name of sanity is beneficial. */ - if ((size + align) > ~(grub_size_t) 0x100000) - goto fail; - align = (align >> GRUB_MM_ALIGN_LOG2); if (align == 0) align = 1; @@ -377,30 +332,6 @@ 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) @@ -521,8 +452,7 @@ grub_realloc (void *ptr, grub_size_t size) if (! q) return q; - /* We've already checked that p->size < n. */ - grub_memcpy (q, ptr, p->size << GRUB_MM_ALIGN_LOG2); + grub_memcpy (q, ptr, size); grub_free (ptr); return q; } @@ -587,20 +517,6 @@ 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, 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) { diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c index 619db3122..9213caa76 100644 --- a/grub-core/kern/parser.c +++ b/grub-core/kern/parser.c @@ -96,42 +96,8 @@ 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 void -add_var (char *varname, char **bp, char **vp, - 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; - - *((*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; -} - grub_err_t -grub_parser_split_cmdline (const char *cmdline, - grub_reader_getline_t getline, void *getline_data, +grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, int *argc, char ***argv) { grub_parser_state_t state = GRUB_PARSER_STATE_TEXT; @@ -145,13 +111,45 @@ grub_parser_split_cmdline (const char *cmdline, char *args; 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; do { if (!rd || !*rd) { if (getline) - getline (&rd, 1, getline_data); + getline (&rd, 1); else break; } @@ -169,7 +167,7 @@ grub_parser_split_cmdline (const char *cmdline, /* If a variable was being processed and this character does not describe the variable anymore, write the variable to the buffer. */ - add_var (varname, &bp, &vp, state, newstate); + add_var (newstate); if (check_varstate (newstate)) { @@ -199,7 +197,7 @@ grub_parser_split_cmdline (const char *cmdline, /* A special case for when the last character was part of a variable. */ - add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT); + add_var (GRUB_PARSER_STATE_TEXT); if (bp != buffer && *(bp - 1)) { @@ -213,7 +211,7 @@ grub_parser_split_cmdline (const char *cmdline, return grub_errno; grub_memcpy (args, buffer, bp - buffer); - *argv = grub_calloc (*argc + 1, sizeof (char *)); + *argv = grub_malloc (sizeof (char *) * (*argc + 1)); if (!*argv) { grub_free (args); @@ -234,41 +232,37 @@ grub_parser_split_cmdline (const char *cmdline, return 0; } -/* 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; - grub_parser_execute_getline (&line, 0, &source); - grub_rescue_parse_line (line, grub_parser_execute_getline, &source); + getline (&line, 0); + grub_rescue_parse_line (line, getline); grub_free (line); - grub_print_error (); } return grub_errno; diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c index 2c401b866..82ae9c8c2 100644 --- a/grub-core/kern/partition.c +++ b/grub-core/kern/partition.c @@ -59,50 +59,39 @@ 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) { - struct grub_partition_map_probe_ctx ctx = { - .partnum = partnum, - .p = 0 - }; + grub_partition_t p = 0; - partmap->iterate (disk, probe_iter, &ctx); + 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); if (grub_errno) goto fail; - return ctx.p; + return p; fail: - grub_free (ctx.p); + grub_free (p); return 0; } @@ -126,7 +115,7 @@ grub_partition_probe (struct grub_disk *disk, const char *str) while (*ptr && grub_isalpha (*ptr)) ptr++; partname_end = ptr; - num = grub_strtoul (ptr, &ptr, 0) - 1; + num = grub_strtoul (ptr, (char **) &ptr, 0) - 1; curpart = 0; /* Use the first partition map type found. */ @@ -173,71 +162,62 @@ 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; - err = partmap->iterate (dsk, part_iterate, ctx); - 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, - grub_partition_iterate_hook_t hook, void *hook_data) + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) { - struct grub_partition_iterate_ctx ctx = { - .ret = 0, - .hook = hook, - .hook_data = hook_data - }; - const struct grub_partition_map *partmap; + 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; + } - FOR_PARTITION_MAPS(partmap) { - grub_err_t err; - err = partmap->iterate (disk, part_iterate, &ctx); - if (err) - grub_errno = GRUB_ERR_NONE; - if (ctx.ret) - break; + 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; + } } - return ctx.ret; + return ret; } char * diff --git a/grub-core/kern/powerpc/compiler-rt.S b/grub-core/kern/powerpc/compiler-rt.S deleted file mode 100644 index b3b912db6..000000000 --- a/grub-core/kern/powerpc/compiler-rt.S +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 cdd61b305..4057fee5a 100644 --- a/grub-core/kern/powerpc/dl.c +++ b/grub-core/kern/powerpc/dl.c @@ -38,6 +38,46 @@ grub_arch_dl_check_header (void *ehdr) return GRUB_ERR_NONE; } +void +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; + + /* 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) + (*tramp)++; + + } + + return; +} + /* For low-endian reverse lis and addr_high as well as ori and addr_low. */ struct trampoline { @@ -55,115 +95,113 @@ static const struct trampoline trampoline_template = 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) -{ - const Elf_Ehdr *e = ehdr; - const Elf_Shdr *s; - unsigned i; - - *tramp = 0; - *got = 0; - - 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 - || ELF_R_TYPE (rel->r_info) == GRUB_ELF_R_PPC_PLTREL24) - (*tramp)++; - - } - - *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) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { - Elf_Rela *rel, *max; + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + struct trampoline *tptr = 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)) - { - Elf_Word *addr; - Elf_Sym *sym; - grub_uint32_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) - 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 = (Elf_Word *) ((char *) 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; - switch (ELF_R_TYPE (rel->r_info)) - { - case GRUB_ELF_R_PPC_ADDR16_LO: - *(Elf_Half *) addr = value; - break; + 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; - 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); + /* 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)); + } + } } - - 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 21c884b43..b26c47edb 100644 --- a/grub-core/kern/powerpc/ieee1275/startup.S +++ b/grub-core/kern/powerpc/ieee1275/startup.S @@ -34,31 +34,14 @@ _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 633836699..656342d27 100644 --- a/grub-core/kern/rescue_parser.c +++ b/grub-core/kern/rescue_parser.c @@ -26,16 +26,14 @@ #include grub_err_t -grub_rescue_parse_line (char *line, - grub_reader_getline_t getline, void *getline_data) +grub_rescue_parse_line (char *line, grub_reader_getline_t getline) { char *name; int n; grub_command_t cmd; char **args; - if (grub_parser_split_cmdline (line, getline, getline_data, &n, &args) - || n < 0) + if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0) return grub_errno; if (n == 0) @@ -43,17 +41,13 @@ grub_rescue_parse_line (char *line, /* In case of an assignment set the environment accordingly instead of calling a function. */ - if (n == 1) + if (n == 1 && grub_strchr (line, '=')) { char *val = grub_strchr (args[0], '='); - - if (val) - { - val[0] = 0; - grub_env_set (args[0], val + 1); - val[0] = '='; - goto quit; - } + val[0] = 0; + grub_env_set (args[0], val + 1); + val[0] = '='; + goto quit; } /* Get the command name. */ @@ -76,7 +70,6 @@ grub_rescue_parse_line (char *line, } 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 dcd7d4439..4587b944f 100644 --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -30,8 +30,7 @@ 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, - void *data __attribute__ ((unused))) +grub_rescue_read_line (char **line, int cont) { int c; int pos = 0; @@ -88,11 +87,11 @@ grub_rescue_run (void) grub_print_error (); grub_errno = GRUB_ERR_NONE; - grub_rescue_read_line (&line, 0, NULL); + grub_rescue_read_line (&line, 0); if (! line || line[0] == '\0') continue; - grub_rescue_parse_line (line, grub_rescue_read_line, NULL); + grub_rescue_parse_line (line, grub_rescue_read_line); grub_free (line); } } diff --git a/grub-core/kern/riscv/cache.c b/grub-core/kern/riscv/cache.c deleted file mode 100644 index 47777a033..000000000 --- a/grub-core/kern/riscv/cache.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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/dl.c b/grub-core/kern/riscv/dl.c deleted file mode 100644 index 6fb8385ef..000000000 --- a/grub-core/kern/riscv/dl.c +++ /dev/null @@ -1,340 +0,0 @@ -/* 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: - { - 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: - 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/riscv/efi/init.c b/grub-core/kern/riscv/efi/init.c deleted file mode 100644 index 38795fe67..000000000 --- a/grub-core/kern/riscv/efi/init.c +++ /dev/null @@ -1,79 +0,0 @@ -/* 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 ("rdcycle %0" : "=r" (tmr)); -#else - grub_uint32_t lo, hi, tmp; - asm volatile ( - "1:\n" - "rdcycleh %0\n" - "rdcycle %1\n" - "rdcycleh %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 deleted file mode 100644 index f2a7b2b1e..000000000 --- a/grub-core/kern/riscv/efi/startup.S +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 739be4717..d188c4f23 100644 --- a/grub-core/kern/sparc64/dl.c +++ b/grub-core/kern/sparc64/dl.c @@ -40,147 +40,108 @@ grub_arch_dl_check_header (void *ehdr) #pragma GCC diagnostic ignored "-Wcast-align" -struct trampoline -{ - 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 */ -}; - +/* Relocate symbols. */ grub_err_t -grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, - grub_size_t *got) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { - const Elf_Ehdr *e = ehdr; - const Elf_Shdr *s; + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; unsigned i; - *tramp = 0; - *got = 0; - - for (i = 0, s = (const Elf_Shdr *) ((grub_addr_t) e + e->e_shoff); + /* Find a symbol table. */ + for (i = 0, s = (Elf_Shdr *) ((char *) 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 || s->sh_type == SHT_RELA) - { - const Elf_Rel *rel, *max; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; - 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: + 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++) { - *tramp += sizeof (struct trampoline); - break; + 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)); + } } - } + } } 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: - 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/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index 03b916f05..9d91fba48 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 - .org GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE + . = EXT_C(_start) + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE VARIABLE(grub_total_module_size) .word 0 @@ -36,14 +36,10 @@ codestart: /* Copy the modules past the end of the kernel image. * They are currently sitting in the BSS. */ - 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(__bss_start), %o2 + or %o2, %lo(__bss_start), %o2 + sethi %hi(_end), %o3 + or %o3, %lo(_end), %o3 sethi %hi(grub_total_module_size), %o4 lduw [%o4 + %lo(grub_total_module_size)], %o4 @@ -71,34 +67,16 @@ codestart: /* Now it's safe to clear out the BSS. */ sethi %hi(__bss_start), %o2 or %o2, %lo(__bss_start), %o2 -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 + sethi %hi(_end), %o3 + or %o3, %lo(_end), %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 5a59aaf06..53be692c3 100644 --- a/grub-core/kern/sparc64/ieee1275/ieee1275.c +++ b/grub-core/kern/sparc64/ieee1275/ieee1275.c @@ -89,59 +89,3 @@ 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 14d596498..5014caf62 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -28,11 +28,7 @@ struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; -/* 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_term_poll_usb) (void) = NULL; void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ @@ -46,6 +42,7 @@ grub_putcode_dumb (grub_uint32_t code, .variant = 0, .attributes = 0, .ncomb = 0, + .combining = 0, .estimated_width = 1 }; @@ -53,7 +50,7 @@ grub_putcode_dumb (grub_uint32_t code, { int n; - n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term).x) + n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term) >> 8) % GRUB_TERM_TAB_WIDTH); while (n--) grub_putcode_dumb (' ', term); @@ -89,7 +86,7 @@ grub_getkey_noblock (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (0); + grub_term_poll_usb (); if (grub_net_poll_cards_idle) grub_net_poll_cards_idle (); @@ -120,45 +117,6 @@ 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 deleted file mode 100644 index 272b83bd7..000000000 --- a/grub-core/kern/uboot/hw.c +++ /dev/null @@ -1,112 +0,0 @@ -/* 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 deleted file mode 100644 index 3e338645c..000000000 --- a/grub-core/kern/uboot/init.c +++ /dev/null @@ -1,172 +0,0 @@ -/* 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 deleted file mode 100644 index aac8f9ae1..000000000 --- a/grub-core/kern/uboot/uboot.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * 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/vga_init.c b/grub-core/kern/vga_init.c index 3fe2f16de..889d0128e 100644 --- a/grub-core/kern/vga_init.c +++ b/grub-core/kern/vga_init.c @@ -18,7 +18,6 @@ #ifndef __mips__ #include -#include #endif #include #include @@ -46,7 +45,11 @@ 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 @@ -87,6 +90,37 @@ 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 3a73e6e6c..65f09ef53 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -40,77 +40,83 @@ grub_arch_dl_check_header (void *ehdr) /* 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_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { - Elf64_Rela *rel, *max; + Elf64_Ehdr *e = ehdr; + Elf64_Shdr *s; + Elf64_Word entsize; + unsigned i; - 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; + /* 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; - if (seg->size < rel->r_offset) - 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")); - 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)); + entsize = s->sh_entsize; - switch (ELF_R_TYPE (rel->r_info)) - { - case R_X86_64_64: - *addr64 += rel->r_addend + sym->st_value; - break; + 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; - case R_X86_64_PC32: - case R_X86_64_PLT32: + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) { - 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; + Elf64_Rela *rel, *max; - case R_X86_64_PC64: - { - *addr64 += rel->r_addend + sym->st_value - - (Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset; - } - break; + 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; - 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; + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } - } + 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)); + } + } + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S index 1337fd9fc..2df95dda1 100644 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ b/grub-core/kern/x86_64/efi/callwrap.S @@ -36,94 +36,94 @@ .text FUNCTION(efi_wrap_0) - subq $40, %rsp + subq $48, %rsp call *%rdi - addq $40, %rsp + addq $48, %rsp ret FUNCTION(efi_wrap_1) - subq $40, %rsp + subq $48, %rsp mov %rsi, %rcx call *%rdi - addq $40, %rsp + addq $48, %rsp ret FUNCTION(efi_wrap_2) - subq $40, %rsp + subq $48, %rsp mov %rsi, %rcx call *%rdi - addq $40, %rsp + addq $48, %rsp ret FUNCTION(efi_wrap_3) - subq $40, %rsp + subq $48, %rsp mov %rcx, %r8 mov %rsi, %rcx call *%rdi - addq $40, %rsp + addq $48, %rsp ret FUNCTION(efi_wrap_4) - subq $40, %rsp + subq $48, %rsp mov %r8, %r9 mov %rcx, %r8 mov %rsi, %rcx call *%rdi - addq $40, %rsp + addq $48, %rsp ret FUNCTION(efi_wrap_5) - subq $40, %rsp + subq $48, %rsp mov %r9, 32(%rsp) mov %r8, %r9 mov %rcx, %r8 mov %rsi, %rcx call *%rdi - addq $40, %rsp + addq $48, %rsp ret FUNCTION(efi_wrap_6) - subq $56, %rsp - mov 56+8(%rsp), %rax + 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 $56, %rsp + addq $64, %rsp ret FUNCTION(efi_wrap_7) - subq $88, %rsp - mov 88+16(%rsp), %rax + subq $96, %rsp + mov 96+16(%rsp), %rax mov %rax, 48(%rsp) - mov 88+8(%rsp), %rax + 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 $88, %rsp + addq $96, %rsp ret FUNCTION(efi_wrap_10) - subq $88, %rsp - mov 88+40(%rsp), %rax + subq $96, %rsp + mov 96+40(%rsp), %rax mov %rax, 72(%rsp) - mov 88+32(%rsp), %rax + mov 96+32(%rsp), %rax mov %rax, 64(%rsp) - mov 88+24(%rsp), %rax + mov 96+24(%rsp), %rax mov %rax, 56(%rsp) - mov 88+16(%rsp), %rax + mov 96+16(%rsp), %rax mov %rax, 48(%rsp) - mov 88+8(%rsp), %rax + 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 $88, %rsp + 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 9357e5c5d..f86f01969 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) - /* Doesn't return. */ + ret + diff --git a/grub-core/kern/x86_64/xen/hypercall.S b/grub-core/kern/x86_64/xen/hypercall.S deleted file mode 100644 index 9b04db6a0..000000000 --- a/grub-core/kern/x86_64/xen/hypercall.S +++ /dev/null @@ -1,53 +0,0 @@ -/* 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 deleted file mode 100644 index 21a139f40..000000000 --- a/grub-core/kern/x86_64/xen/startup.S +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 deleted file mode 100644 index 782ca7295..000000000 --- a/grub-core/kern/xen/init.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * 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 952edb346..62ebee686 100644 --- a/grub-core/lib/LzmaDec.c +++ b/grub-core/lib/LzmaDec.c @@ -26,9 +26,7 @@ #include -#pragma GCC diagnostic ignored "-Wshadow" -#include -#define memcpy grub_memcpy +#include #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) @@ -720,7 +718,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) p->needFlush = 0; } -static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +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 753e56a95..f2ec04a8c 100644 --- a/grub-core/lib/LzmaEnc.c +++ b/grub-core/lib/LzmaEnc.c @@ -1877,19 +1877,13 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize } else { - UInt32 posSlot, lenToPosState; + UInt32 posSlot; 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); - lenToPosState = GetLenToPosState(len); - if (lenToPosState >= kNumLenToPosStates) - { - p->result = SZ_ERROR_DATA; - return CheckErrors(p); - } - RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index 8439a0062..b34188528 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -23,7 +23,6 @@ #include #include #include -#include /* Built-in parser for default options. */ static const struct grub_arg_option help_options[] = @@ -35,37 +34,36 @@ static const struct grub_arg_option help_options[] = {0, 0, 0, 0, 0, 0} }; -/* 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 * +static struct grub_arg_option * find_short (const struct grub_arg_option *options, char c) { - const struct grub_arg_option *found = 0; + 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; + } if (options) - found = fnd_short (options, c); + found = fnd_short (options); if (! found) { switch (c) { case 'h': - found = help_options; + found = (struct grub_arg_option *) help_options; break; case 'u': - found = (help_options + 1); + found = (struct grub_arg_option *) (help_options + 1); break; default: @@ -76,30 +74,29 @@ find_short (const struct grub_arg_option *options, char c) return found; } -/* 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 * +static struct grub_arg_option * find_long (const struct grub_arg_option *options, const char *s, int len) { - const struct grub_arg_option *found = 0; + 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; + } if (options) - found = fnd_long (options, s, len); + found = fnd_long (options); if (! found) - found = fnd_long (help_options, s, len); + found = fnd_long (help_options); return found; } @@ -110,70 +107,69 @@ 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; - const struct grub_arg_option *opt; + + 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; + } + } + } 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, h_is_used, u_is_used); - showargs (help_options, h_is_used, u_is_used); + showargs (cmd->options); + showargs (help_options); #if 0 grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT); #endif @@ -213,28 +209,6 @@ 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) @@ -243,18 +217,34 @@ 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]; - const struct grub_arg_option *opt; + 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 (&argl, &num, arg) != 0) + if (add_arg (arg) != 0) goto fail; continue; @@ -273,7 +263,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (*curshort) { - if (add_arg (&argl, &num, arg) != 0) + if (add_arg (arg) != 0) goto fail; continue; } @@ -326,7 +316,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 (&argl, &num, argv[curarg]) != 0) + if (add_arg (argv[curarg]) != 0) goto fail; break; } @@ -348,7 +338,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) { - if (add_arg (&argl, &num, arg) != 0) + if (add_arg (arg) != 0) goto fail; continue; } @@ -382,7 +372,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, case ARG_TYPE_INT: { - const char * tail; + char *tail; grub_strtoull (option, &tail, 0); if (tail == 0 || tail == option || *tail != '\0' || grub_errno) @@ -435,10 +425,9 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, { int i; char **args; - grub_size_t argcnt; + unsigned argcnt; struct grub_arg_list *list; const struct grub_arg_option *options; - grub_size_t sz0, sz1; options = extcmd->options; if (! options) @@ -448,18 +437,10 @@ 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 += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ + argcnt += (argc + 1) / 2 + 1; /* max possible for any option */ } - 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); + list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); if (! list) return 0; @@ -472,7 +453,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) { list[i].args = args; - args += (grub_size_t) argc / 2 + 1; + args += argc / 2 + 1; } } return list; diff --git a/grub-core/lib/arm/setjmp.S b/grub-core/lib/arm/setjmp.S deleted file mode 100644 index a5373d3a9..000000000 --- a/grub-core/lib/arm/setjmp.S +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 deleted file mode 100644 index ffcabf6e4..000000000 --- a/grub-core/lib/arm64/setjmp.S +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 825a8800e..32945d9f8 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_size_t) ((grub_uint8_t *) addr - (grub_uint8_t *) segment->addr)); + (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 ed0b149dc..a702e6487 100644 --- a/grub-core/lib/cmdline.c +++ b/grub-core/lib/cmdline.c @@ -56,19 +56,15 @@ unsigned int grub_loader_cmdline_size (int argc, char *argv[]) size++; /* Separator space or NULL. */ } - if (size == 0) - size = 1; - return 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 grub_create_loader_cmdline (int argc, char *argv[], char *buf, + grub_size_t size) { int i, space; unsigned int arg_size; - char *c, *orig_buf = buf; + char *c; for (i = 0; i < argc; i++) { @@ -105,5 +101,5 @@ grub_create_loader_cmdline (int argc, char *argv[], char *buf, *buf = 0; - return grub_verify_string (orig_buf, type); + return i; } diff --git a/grub-core/lib/crc.c b/grub-core/lib/crc.c index bf97cc63a..ffc3ef3b5 100644 --- a/grub-core/lib/crc.c +++ b/grub-core/lib/crc.c @@ -22,26 +22,25 @@ 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 4960f3f89..4b1c92cf0 100644 --- a/grub-core/lib/crc64.c +++ b/grub-core/lib/crc64.c @@ -25,26 +25,25 @@ 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 ca334d5a4..f4b13ed3d 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -23,7 +23,13 @@ #include #include #include -#include + +#ifdef GRUB_UTIL +#include +#include +#include +#include +#endif GRUB_MOD_LICENSE ("GPLv3+"); @@ -50,38 +56,6 @@ grub_burn_stack (grub_size_t size) grub_burn_stack (size - sizeof (buf)); } -void -_gcry_burn_stack (int size) -{ - grub_burn_stack (size); -} - -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) @@ -125,10 +99,7 @@ void grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, grub_size_t inlen) { - GRUB_PROPERLY_ALIGNED_ARRAY (ctx, GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); - - if (hash->contextsize > sizeof (ctx)) - grub_fatal ("Too large md context"); + grub_uint8_t ctx[hash->contextsize]; hash->init (&ctx); hash->write (&ctx, in, inlen); hash->final (&ctx); @@ -203,18 +174,15 @@ 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, *end; - grub_uint8_t *outptr; - grub_size_t blocksize; + const grub_uint8_t *inptr; + grub_uint8_t *outptr, *end; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - blocksize = cipher->cipher->blocksize; - if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) - || ((size & (blocksize - 1)) != 0)) + if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; - end = (const grub_uint8_t *) in + size; + end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += blocksize, outptr += blocksize) + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) cipher->cipher->decrypt (cipher->ctx, outptr, inptr); return GPG_ERR_NO_ERROR; } @@ -223,47 +191,40 @@ 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, *end; - grub_uint8_t *outptr; - grub_size_t blocksize; + const grub_uint8_t *inptr; + grub_uint8_t *outptr, *end; if (!cipher->cipher->encrypt) return GPG_ERR_NOT_SUPPORTED; - blocksize = cipher->cipher->blocksize; - if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) - || ((size & (blocksize - 1)) != 0)) + if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; - end = (const grub_uint8_t *) in + size; + end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += blocksize, outptr += blocksize) + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->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, const void *in, grub_size_t size, + void *out, void *in, grub_size_t size, void *iv_in) { - grub_uint8_t *outptr; - const grub_uint8_t *inptr, *end; + grub_uint8_t *inptr, *outptr, *end; void *iv; - grub_size_t blocksize; - if (!cipher->cipher->encrypt) + if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - blocksize = cipher->cipher->blocksize; - if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) - || ((size & (blocksize - 1)) != 0)) + if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; - end = (const grub_uint8_t *) in + size; + end = (grub_uint8_t *) in + size; iv = iv_in; for (inptr = in, outptr = out; inptr < end; - inptr += blocksize, outptr += blocksize) + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) { - grub_crypto_xor (outptr, inptr, iv, blocksize); + grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize); cipher->cipher->encrypt (cipher->ctx, outptr, outptr); iv = outptr; } - grub_memcpy (iv_in, iv, blocksize); + grub_memcpy (iv_in, iv, cipher->cipher->blocksize); return GPG_ERR_NO_ERROR; } @@ -272,26 +233,21 @@ 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, *end; - grub_uint8_t *outptr; - grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; - grub_size_t blocksize; + const grub_uint8_t *inptr; + grub_uint8_t *outptr, *end; + grub_uint8_t ivt[cipher->cipher->blocksize]; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - blocksize = cipher->cipher->blocksize; - if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) - || ((size & (blocksize - 1)) != 0)) + if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; - if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) - return GPG_ERR_INV_ARG; - end = (const grub_uint8_t *) in + size; + end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += blocksize, outptr += blocksize) + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) { - grub_memcpy (ivt, inptr, blocksize); + grub_memcpy (ivt, inptr, cipher->cipher->blocksize); cipher->cipher->decrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (outptr, outptr, iv, blocksize); - grub_memcpy (iv, ivt, blocksize); + grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); + grub_memcpy (iv, ivt, cipher->cipher->blocksize); } return GPG_ERR_NO_ERROR; } @@ -448,11 +404,43 @@ 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; @@ -462,7 +450,7 @@ grub_password_get (char buf[], unsigned buf_size) if (key == '\n' || key == '\r') break; - if (key == GRUB_TERM_ESC) + if (key == '\e') { cur_len = 0; break; @@ -470,8 +458,7 @@ grub_password_get (char buf[], unsigned buf_size) if (key == '\b') { - if (cur_len) - cur_len--; + cur_len--; continue; } @@ -487,7 +474,6 @@ grub_password_get (char buf[], unsigned buf_size) grub_xputs ("\n"); grub_refresh (); - return (key != GRUB_TERM_ESC); -} + return (key != '\e'); #endif - +} diff --git a/grub-core/lib/disk.c b/grub-core/lib/disk.c deleted file mode 100644 index b4eb064a8..000000000 --- a/grub-core/lib/disk.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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, transform_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, transform_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 deleted file mode 100644 index 35606fea7..000000000 --- a/grub-core/lib/division.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 deleted file mode 100644 index cf693fc6b..000000000 --- a/grub-core/lib/dummy/datetime.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 deleted file mode 100644 index 378d50f3f..000000000 --- a/grub-core/lib/dummy/halt.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 deleted file mode 100644 index b8cbed8f8..000000000 --- a/grub-core/lib/dummy/reboot.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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/halt.c b/grub-core/lib/efi/halt.c index 29d413641..5ebf2cd1d 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -23,15 +23,12 @@ #include #include #include -#include void grub_halt (void) { - grub_machine_fini (GRUB_LOADER_FLAG_NORETURN | - GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY); -#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \ - !defined(__riscv) + grub_machine_fini (); +#ifndef __ia64__ grub_acpi_halt (); #endif efi_call_4 (grub_efi_system_table->runtime_services->reset_system, diff --git a/grub-core/lib/xen/reboot.c b/grub-core/lib/efi/reboot.c similarity index 79% rename from grub-core/lib/xen/reboot.c rename to grub-core/lib/efi/reboot.c index fd7609a7d..9382370f7 100644 --- a/grub-core/lib/xen/reboot.c +++ b/grub-core/lib/efi/reboot.c @@ -16,17 +16,17 @@ * along with GRUB. If not, see . */ +#include +#include #include #include #include -#include void grub_reboot (void) { - struct sched_shutdown arg; - - arg.reason = SHUTDOWN_reboot; - grub_xen_sched_op (SCHEDOP_shutdown, &arg); - for (;;); + grub_machine_fini (); + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, + GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); + for (;;) ; } diff --git a/grub-core/lib/efi/relocator.c b/grub-core/lib/efi/relocator.c index 319b69eeb..0d346bea3 100644 --- a/grub-core/lib/efi/relocator.c +++ b/grub-core/lib/efi/relocator.c @@ -96,10 +96,10 @@ 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); diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c index 2e4e78b13..311927bd8 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,8 +225,7 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name) void grub_envblk_iterate (grub_envblk_t envblk, - void *hook_data, - int hook (const char *name, const char *value, void *hook_data)) + int hook (const char *name, const char *value)) { char *p, *pend; @@ -286,7 +285,7 @@ grub_envblk_iterate (grub_envblk_t envblk, } *q = '\0'; - ret = hook (name, value, hook_data); + ret = hook (name, value); grub_free (name); if (ret) return; diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c deleted file mode 100644 index 0d371c563..000000000 --- a/grub-core/lib/fdt.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * 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 deleted file mode 100644 index edb8e9ffe..000000000 --- a/grub-core/lib/getline.c +++ /dev/null @@ -1,92 +0,0 @@ -/* 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-base64.patch b/grub-core/lib/gnulib-patches/fix-base64.patch deleted file mode 100644 index 985db1279..000000000 --- a/grub-core/lib/gnulib-patches/fix-base64.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/lib/base64.h b/lib/base64.h -index 9cd0183b8..185a2afa1 100644 ---- a/lib/base64.h -+++ b/lib/base64.h -@@ -21,8 +21,14 @@ - /* Get size_t. */ - # include - --/* Get bool. */ --# include -+#ifndef GRUB_POSIX_BOOL_DEFINED -+typedef enum { false = 0, true = 1 } bool; -+#define GRUB_POSIX_BOOL_DEFINED 1 -+#endif -+ -+#ifndef _GL_ATTRIBUTE_CONST -+# define _GL_ATTRIBUTE_CONST /* empty */ -+#endif - - # ifdef __cplusplus - extern "C" { diff --git a/grub-core/lib/gnulib-patches/fix-null-deref.patch b/grub-core/lib/gnulib-patches/fix-null-deref.patch deleted file mode 100644 index 8fafa153a..000000000 --- a/grub-core/lib/gnulib-patches/fix-null-deref.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/argp-parse.c b/lib/argp-parse.c -index 6dec57310..900adad54 100644 ---- a/lib/argp-parse.c -+++ b/lib/argp-parse.c -@@ -940,7 +940,7 @@ weak_alias (__argp_parse, argp_parse) - void * - __argp_input (const struct argp *argp, const struct argp_state *state) - { -- if (state) -+ if (state && state->pstate) - { - struct group *group; - struct parser *parser = state->pstate; diff --git a/grub-core/lib/gnulib-patches/fix-width.patch b/grub-core/lib/gnulib-patches/fix-width.patch deleted file mode 100644 index 0a208ad08..000000000 --- a/grub-core/lib/gnulib-patches/fix-width.patch +++ /dev/null @@ -1,217 +0,0 @@ -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 -@@ -51,6 +51,7 @@ - #include "argp.h" - #include "argp-fmtstream.h" - #include "argp-namefrob.h" -+#include "mbswidth.h" - - #ifndef SIZE_MAX - # define SIZE_MAX ((size_t) -1) -@@ -1432,7 +1433,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 -@@ -45,6 +45,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/gnulib-patches/no-abort.patch b/grub-core/lib/gnulib-patches/no-abort.patch deleted file mode 100644 index e469c4762..000000000 --- a/grub-core/lib/gnulib-patches/no-abort.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/lib/regcomp.c b/lib/regcomp.c -index cc85f35ac..de45ebb5c 100644 ---- a/lib/regcomp.c -+++ b/lib/regcomp.c -@@ -528,9 +528,9 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, - 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. */ -- abort (); -- -- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); -+ msg = gettext ("unknown regexp error"); -+ else -+ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - -@@ -1136,7 +1136,7 @@ optimize_utf8 (re_dfa_t *dfa) - } - break; - default: -- abort (); -+ break; - } - - if (mb_chars || has_period) diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c index c3e03c727..7a7796a12 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" - "callq *%%rax": :"a"(grub_backtrace_pointer)); + asm volatile ("movq %rbp, %rdi\n" + "call " EXT_C("grub_backtrace_pointer")); #else - asm volatile ("movl %%ebp, %%eax\n" - "calll *%%ecx": :"c"(grub_backtrace_pointer)); + asm volatile ("movl %ebp, %eax\n" + "call " EXT_C("grub_backtrace_pointer")); #endif } diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c index 2364fe4d7..bd878c9bf 100644 --- a/grub-core/lib/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -20,8 +20,6 @@ #include #include #include -#include -#include const char bochs_shutdown[] = "Shutdown"; @@ -39,23 +37,6 @@ 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) { @@ -66,14 +47,12 @@ grub_halt (void) #endif /* Disable interrupts. */ - asm volatile ("cli"); + __asm__ __volatile__ ("cli"); - /* Bochs, QEMU, etc. Removed in newer QEMU releases. */ + /* Bochs, QEMU, etc. */ 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 deleted file mode 100644 index cd83d2f8f..000000000 --- a/grub-core/lib/i386/random.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 dce0b563d..0587f1477 100644 --- a/grub-core/lib/i386/reboot.c +++ b/grub-core/lib/i386/reboot.c @@ -16,8 +16,6 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MACHINE_EFI - #include #include #include @@ -61,4 +59,3 @@ grub_reboot (void) while (1); } -#endif /* GRUB_MACHINE_EFI */ diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 34cbe834f..df25b30fa 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -28,6 +28,19 @@ #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; @@ -41,7 +54,6 @@ 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; @@ -64,6 +76,7 @@ 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; @@ -71,6 +84,75 @@ 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, @@ -80,13 +162,11 @@ grub_relocator32_boot (struct grub_relocator *rel, void *relst; grub_relocator_chunk_t ch; - /* 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); + 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); if (err) return err; @@ -124,10 +204,13 @@ 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_safe (rel, &ch, 0x8010, 0xa0000, - RELOCATOR_SIZEOF (16) + - GRUB_RELOCATOR16_STACK_SIZE, 16, - GRUB_RELOCATOR_PREFERENCE_NONE, 0); + 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); if (err) return err; @@ -142,7 +225,6 @@ 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; @@ -179,9 +261,11 @@ grub_relocator64_boot (struct grub_relocator *rel, void *relst; grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr, - RELOCATOR_SIZEOF (64), 16, - GRUB_RELOCATOR_PREFERENCE_NONE, 0); + err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr, + max_addr - RELOCATOR_SIZEOF (64), + 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 e9238119b..e79d87551 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -38,21 +38,15 @@ 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 @@ -94,15 +88,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)) - lidt (LOCAL(idt_offset)) + movw %ax, LOCAL(segment_offset) (%esi, 1) + lidt LOCAL(idt_offset) (%esi, 1) /* jump to a 16 bit segment */ ljmp $PSEUDO_REAL_CSEG, $(LOCAL(cont2_offset)) #else - movw %ax, (LOCAL (segment) - LOCAL (base)) + movw %ax, (LOCAL (segment) - LOCAL (base)) (%esi, 1) - lidt (EXT_C(grub_relocator16_idt) - LOCAL (base)) + lidt (EXT_C(grub_relocator16_idt) - LOCAL (base)) (%esi, 1) /* jump to a 16 bit segment */ ljmp $PSEUDO_REAL_CSEG, $(LOCAL (cont2) - LOCAL(base)) @@ -210,9 +204,8 @@ LOCAL(gate_a20_check_state): ret LOCAL(gate_a20_done): - /* - * 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. + /* we are in real mode now + * set up the real mode segment registers : DS, SS, ES */ /* movw imm16, %ax. */ .byte 0xb8 @@ -266,11 +259,6 @@ 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 @@ -305,7 +293,7 @@ LOCAL(gdt): .byte 0, 0x92, 0xCF, 0 /* -- 16 bit real mode CS -- - * base = filled by code, limit 0x0FFFF (1 B Granularity), present + * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present * type = 16 bit code execute/read only/conforming, DPL = 0 */ .word 0xFFFF @@ -317,17 +305,11 @@ LOCAL(cs_base_byte3): .byte 0x9E, 0, 0 /* -- 16 bit real mode DS -- - * base = filled by code, limit 0x0FFFF (1 B Granularity), present + * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present * type = 16 bit data read/write, DPL = 0 */ - .word 0xFFFF -LOCAL(ds_base_bytes12): - .word 0 -LOCAL(ds_base_byte3): - .byte 0 - - .byte 0x92, 0, 0 - + .word 0xFFFF, 0 + .byte 0, 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 148f38adb..e4648d818 100644 --- a/grub-core/lib/i386/relocator64.S +++ b/grub-core/lib/i386/relocator64.S @@ -73,22 +73,6 @@ VARIABLE(grub_relocator64_rsp) movq %rax, %rsp -#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. */ - andq $~15, %rsp - -LOCAL(skip_efi_stack_align): -#endif /* mov imm64, %rax */ .byte 0x48 .byte 0xb8 @@ -136,11 +120,6 @@ 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 1b5210dd3..b9d99e10e 100644 --- a/grub-core/lib/i386/relocator_common.S +++ b/grub-core/lib/i386/relocator_common.S @@ -29,6 +29,8 @@ #endif .macro DISABLE_PAGING +#ifdef GRUB_MACHINE_IEEE1275 +#endif movl %cr0, %eax andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax @@ -40,9 +42,7 @@ LOCAL(base): /* %rax contains now our new 'base'. */ mov RAX, RSI -#if defined (__APPLE__) && defined (__x86_64__) - leaq LOCAL(cont0) (%rip), RAX -#elif defined (__APPLE__) +#ifdef __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 deleted file mode 100644 index 7be609b73..000000000 --- a/grub-core/lib/i386/relocator_common_c.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 deleted file mode 100644 index 96e51b59a..000000000 --- a/grub-core/lib/i386/xen/relocator.S +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 $PAGE_SHIFT, %ebx /* virtual address (1:1 mapping) */ - movl %ecx, %edx - shll $PAGE_SHIFT, %ecx /* prepare pte low part */ - shrl $(32 - 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 38afb2243..729bdc76e 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 - - .proc EXT_C(grub_longjmp) -FUNCTION(grub_longjmp) + .text + .global longjmp + .proc longjmp +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 @@ FUNCTION(grub_longjmp) invala // virt. -> phys. regnum mapping may change mov pr=r24,-1 br.ret.dptk.few rp - .endp EXT_C(grub_longjmp) + .endp longjmp diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S index a0382d83d..dc19be0ce 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 - - .proc EXT_C(grub_setjmp) -FUNCTION(grub_setjmp) + .global setjmp + .proc setjmp +setjmp: alloc r8=ar.pfs,2,0,0,0 mov in1=1 br.cond.sptk.many __sigsetjmp - .endp EXT_C(grub_setjmp) + .endp setjmp /* __sigsetjmp(__jmp_buf buf, int savemask) */ diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c index 328d70a0c..fa57db9e7 100644 --- a/grub-core/lib/ieee1275/cmos.c +++ b/grub-core/lib/ieee1275/cmos.c @@ -23,53 +23,51 @@ #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) { - grub_ieee1275_devices_iterate (grub_cmos_find_port_iter); + 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); if (!grub_cmos_port) return grub_error (GRUB_ERR_IO, "no cmos found"); diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c index b81fba2ed..1947135fe 100644 --- a/grub-core/lib/ieee1275/datetime.c +++ b/grub-core/lib/ieee1275/datetime.c @@ -30,23 +30,22 @@ 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) { - grub_ieee1275_devices_iterate (find_rtc_iter); + 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); if (!rtc) no_ieee1275_rtc = 1; } @@ -90,12 +89,12 @@ grub_get_datetime (struct grub_datetime *datetime) grub_ieee1275_close (ihandle); - if (status == -1 || args.catch_result) + if (status == -1) return grub_error (GRUB_ERR_IO, "get-time failed"); datetime->year = args.year; datetime->month = args.month; - datetime->day = args.day + 1; + datetime->day = args.day; datetime->hour = args.hour; datetime->minute = args.minute; datetime->second = args.second; @@ -140,7 +139,7 @@ grub_set_datetime (struct grub_datetime *datetime) args.year = datetime->year; args.month = datetime->month; - args.day = datetime->day - 1; + args.day = datetime->day; args.hour = datetime->hour; args.minute = datetime->minute; args.second = datetime->second; @@ -149,7 +148,7 @@ grub_set_datetime (struct grub_datetime *datetime) grub_ieee1275_close (ihandle); - if (status == -1 || args.catch_result) + if (status == -1) 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 8fc16d243..7ede29de9 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 ("power-off", 0); grub_ieee1275_interpret ("shut-down", 0); + grub_ieee1275_interpret ("power-off", 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 c6dd8facb..021f0ce71 100644 --- a/grub-core/lib/ieee1275/relocator.c +++ b/grub-core/lib/ieee1275/relocator.c @@ -21,81 +21,65 @@ #include #include -/* 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; - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) + 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; - grub_machine_mmap_iterate (count, &counter); + } + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) + return 0; + grub_machine_mmap_iterate (count); return 2 * counter; } -/* 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) { - struct grub_relocator_firmware_fill_events_ctx ctx = { - .events = events, - .counter = 0 - }; + 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; + + 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++; - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) return 0; - grub_machine_mmap_iterate (grub_relocator_firmware_fill_events_iter, &ctx); - return ctx.counter; + } + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) + return 0; + grub_machine_mmap_iterate (fill); + return counter; } int diff --git a/grub-core/lib/json/jsmn.h b/grub-core/lib/json/jsmn.h deleted file mode 100644 index 3178dcc97..000000000 --- a/grub-core/lib/json/jsmn.h +++ /dev/null @@ -1,471 +0,0 @@ -/* - * 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 deleted file mode 100644 index 1c20c75ea..000000000 --- a/grub-core/lib/json/json.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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; -} diff --git a/grub-core/lib/json/json.h b/grub-core/lib/json/json.h deleted file mode 100644 index 4ea2a22d8..000000000 --- a/grub-core/lib/json/json.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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); - -#endif diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 05719ab2c..775eaad1f 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,2012 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,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 @@ -24,8 +24,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wformat-nonliteral" - struct legacy_command { const char *name; @@ -67,27 +65,23 @@ 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; echo $\"" N_("Default server is ${net_default_server}") "\"; if [ x%s = x--with-configfile ]; then " + {"bootp", "net_bootp; net_ls_addr; 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" @@ -131,7 +125,6 @@ static struct legacy_command legacy_commands[] = {"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...", @@ -143,8 +136,6 @@ 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", @@ -252,10 +243,6 @@ 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" @@ -301,18 +288,14 @@ 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 unsupported. */ + /* FIXME: --no-echo, --no-edit, hercules 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] [graphics]", + "[--silent] [console] [serial] [hercules]", "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" @@ -324,7 +307,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", "testload '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + {"testload", "cat '%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" @@ -351,9 +334,6 @@ 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 * @@ -393,32 +373,9 @@ 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, &rest, 0); + part = grub_strtoull (comma + 1, (char **) &rest, 0); if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') { subpart = rest[1] - 'a'; @@ -429,7 +386,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 + 5); + ret = grub_malloc (ptr - in + overhead + 35); if (!ret) return NULL; @@ -550,11 +507,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; -#endif int hercules = 0; - int console = 0, serial = 0, graphics = 0; +#endif + int console = 0, serial = 0; /* Big enough for any possible resulting command. */ - char outbuf[512] = ""; + char outbuf[256] = ""; char *outptr; while (*ptr) { @@ -584,40 +541,45 @@ 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; - if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) - graphics = 1; +#endif while (*ptr && !grub_isspace (*ptr)) ptr++; while (*ptr && grub_isspace (*ptr)) ptr++; } - if (!console && !serial && !hercules && !graphics) + if (!console && !serial) return grub_strdup ("terminal_input; terminal_output; terminfo\n"); - outptr = outbuf; - - if (graphics) - outptr = grub_stpcpy (outptr, "insmod all_video; "); - - outptr = grub_stpcpy (outptr, "terminal_input "); + grub_strcpy (outbuf, "terminal_input "); + outptr = outbuf + grub_strlen (outbuf); if (serial) - outptr = grub_stpcpy (outptr, "serial "); - if (console || hercules || graphics) - outptr = grub_stpcpy (outptr, "console "); - outptr = grub_stpcpy (outptr, "; terminal_output "); - if (serial) - outptr = grub_stpcpy (outptr, "serial "); + { + grub_strcpy (outptr, "serial "); + outptr += grub_strlen (outptr); + } if (console) - 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'; + { + grub_strcpy (outptr, "console "); + outptr += grub_strlen (outptr); + } + grub_strcpy (outptr, "; terminal_output "); + outptr += grub_strlen (outptr); + if (serial) + { + grub_strcpy (outptr, "serial "); + outptr += grub_strlen (outptr); + } + if (console) + { + grub_strcpy (outptr, "console "); + outptr += grub_strlen (outptr); + } + grub_strcpy (outptr, "; "); + outptr += grub_strlen (outptr); if (serial) { grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, @@ -664,7 +626,6 @@ 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); diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog b/grub-core/lib/libgcrypt/cipher/ChangeLog index 1b3694f58..8924f17e1 100644 --- a/grub-core/lib/libgcrypt/cipher/ChangeLog +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog @@ -1,93 +1,3 @@ -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. @@ -3978,8 +3888,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, 2010 Free Software Foundation, Inc. + Copyright 1998,1999,2000,2001,2002,2003,2004,2005,2006 + 2007, 2008, 2009 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 deleted file mode 100644 index 05516c99e..000000000 --- a/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 +++ /dev/null @@ -1,4247 +0,0 @@ -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 deleted file mode 100644 index 76cdc96ad..000000000 --- a/grub-core/lib/libgcrypt/cipher/Makefile.am +++ /dev/null @@ -1,83 +0,0 @@ -# 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 deleted file mode 100644 index 0cd64f71f..000000000 --- a/grub-core/lib/libgcrypt/cipher/Manifest +++ /dev/null @@ -1,73 +0,0 @@ -# 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 63f6fcd11..ee9498b23 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_calloc (data_mpis_n, sizeof (*data_mpis_new)); + data_mpis_new = gcry_malloc (sizeof (*data_mpis_new) * data_mpis_n); 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_calloc (data_n + 1, sizeof (*arg_list)); + arg_list = gcry_malloc (sizeof (*arg_list) * (data_n + 1)); 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_calloc (data_length, sizeof (*arg_list) * 2); + arg_list = gcry_malloc (sizeof (*arg_list) * (data_length * 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_calloc (arg_list_n, sizeof (*arg_list)); + arg_list = gcry_malloc (sizeof (*arg_list) * arg_list_n); 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 whether the message that is contained in + METHOD; ACTION specifies wether 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 6ef07fb20..6bb0555c6 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,3 +153,4 @@ 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 b4d2b9c9a..6ef68e371 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 deleted file mode 100644 index df3559472..000000000 --- a/grub-core/lib/libgcrypt/cipher/bufhelp.h +++ /dev/null @@ -1,432 +0,0 @@ -/* 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 a26362177..067af85bc 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 2e28bce2a..79cd49b7c 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 cccf786ca..4425a3a2b 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 9905f5cb9..333d55e91 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 9852d6a5a..2c33ee94f 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, 2009, 2011 Free Software Foundation, Inc. + * 2005, 2007, 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -33,12 +33,9 @@ #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 (__GNUC__) -# define NEED_16BYTE_ALIGNED_CONTEXT 1 +#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) +#define NEED_16BYTE_ALIGNED_CONTEXT 1 #endif /* A dummy extraspec so that we do not need to tests the extraspec @@ -61,39 +58,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 @@ -101,20 +98,16 @@ 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 } }; @@ -125,7 +118,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 whether the default ciphers have already been +/* Flag to check wether the default ciphers have already been registered. */ static int default_ciphers_registered; @@ -144,20 +137,19 @@ static int default_ciphers_registered; while (0) -/* 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 +/* 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 { PROPERLY_ALIGNED_TYPE foo; #ifdef NEED_16BYTE_ALIGNED_CONTEXT char bar[16] __attribute__ ((aligned (16))); -#endif +#endif char c[1]; } cipher_context_alignment_t; @@ -174,7 +166,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 @@ -182,19 +174,16 @@ 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 *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); - void (*ctr_enc)(void *context, unsigned char *iv, + void (*cbc_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); } bulk; @@ -203,29 +192,19 @@ struct gcry_cipher_handle int mode; unsigned int flags; - 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. */ + /* The initialization vector. To help code optimization we make + sure that it is aligned on an unsigned long and u32 boundary. */ union { - cipher_context_alignment_t iv_align; - unsigned char iv[MAX_BLOCKSIZE]; + unsigned long dummy_iv; + u32 dummy_u32_iv; + 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 LASTIV. */ + int unused; /* Number of unused bytes in the IV. */ + + unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */ + /* What follows are two contexts of the cipher in use. The first one needs to be aligned well enough for the cipher operation @@ -243,7 +222,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; @@ -302,7 +281,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) @@ -405,8 +384,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); @@ -436,7 +415,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; @@ -500,7 +479,7 @@ gcry_cipher_map_name (const char *string) } ath_mutex_unlock (&ciphers_registered_lock); - + return algorithm; } @@ -609,13 +588,15 @@ check_cipher_algo (int algorithm) else err = GPG_ERR_CIPHER_ALGO; ath_mutex_unlock (&ciphers_registered_lock); - + return err; } -/* Return the standard length in bits of the key for the cipher - algorithm with the identifier ALGORITHM. */ +/* 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. */ static unsigned int cipher_get_keylen (int algorithm) { @@ -633,13 +614,17 @@ 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 return 0 for an invalid algorithm. */ + 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. */ static unsigned int cipher_get_blocksize (int algorithm) { @@ -657,6 +642,8 @@ 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; @@ -691,10 +678,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 whether the cipher is marked + /* Fetch the according module and check wether the cipher is marked available for use. */ ath_mutex_lock (&ciphers_registered_lock); module = _gcry_module_lookup_id (ciphers_registered, algo); @@ -706,6 +693,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, { /* Not available for use. */ err = GPG_ERR_CIPHER_ALGO; + _gcry_module_release (module); } else { @@ -719,7 +707,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 @@ -736,7 +724,6 @@ 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; @@ -782,7 +769,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, h = gcry_calloc (1, size); if (! h) - err = gpg_err_code_from_syserror (); + err = gpg_err_code_from_errno (errno); else { size_t off = 0; @@ -818,10 +805,9 @@ 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; } @@ -896,10 +882,7 @@ 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); } @@ -911,7 +894,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) { @@ -922,10 +905,7 @@ 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; } @@ -938,92 +918,61 @@ 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->u_ctr.ctr, 0, c->cipher->blocksize); + memset (c->ctr, 0, c->cipher->blocksize); } - -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) +static void +do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, + unsigned int nblocks ) { - 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; - + unsigned int n; + for (n=0; n < nblocks; n++ ) { - c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); - inbuf += blocksize; - outbuf += blocksize; + c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); + inbuf += c->cipher->blocksize; + outbuf += c->cipher->blocksize; } - return 0; } -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) +static void +do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, + unsigned int nblocks ) { - unsigned int blocksize = c->cipher->blocksize; - unsigned int n, nblocks; + unsigned int 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++ ) + for (n=0; n < nblocks; n++ ) { - c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf ); - inbuf += blocksize; - outbuf += blocksize; + c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); + inbuf += c->cipher->blocksize; + outbuf += c->cipher->blocksize; } - - return 0; } -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) +static void +do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, + const unsigned char *inbuf, unsigned int nbytes ) { unsigned int n; unsigned char *ivp; int i; size_t blocksize = c->cipher->blocksize; - unsigned nblocks = inbuflen / blocksize; + unsigned nblocks = 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 ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { - if ((inbuflen % blocksize) == 0) + if ((nbytes % 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; @@ -1042,17 +991,17 @@ do_cbc_encrypt (gcry_cipher_hd_t c, } } - if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { /* We have to be careful here, since outbuf might be equal to inbuf. */ int restbytes; unsigned char b; - if ((inbuflen % blocksize) == 0) + if ((nbytes % blocksize) == 0) restbytes = blocksize; else - restbytes = inbuflen % blocksize; + restbytes = nbytes % blocksize; outbuf -= blocksize; for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++) @@ -1063,51 +1012,40 @@ do_cbc_encrypt (gcry_cipher_hd_t c, } 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 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) +static void +do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, + const unsigned char *inbuf, unsigned int nbytes) { unsigned int n; unsigned char *ivp; int i; size_t blocksize = c->cipher->blocksize; - unsigned int nblocks = inbuflen / blocksize; + unsigned int nblocks = 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) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { nblocks--; - if ((inbuflen % blocksize) == 0) + if ((nbytes % 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 @@ -1122,22 +1060,22 @@ do_cbc_decrypt (gcry_cipher_hd_t c, } } - if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) { int restbytes; - - if ((inbuflen % blocksize) == 0) + + if ((nbytes % blocksize) == 0) restbytes = blocksize; else - restbytes = inbuflen % blocksize; - + restbytes = nbytes % 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]; @@ -1146,38 +1084,32 @@ do_cbc_decrypt (gcry_cipher_hd_t c, outbuf[i] ^= *ivp++; /* c->lastiv is now really lastlastiv, does this matter? */ } - - return 0; } -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) +static void +do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, + const unsigned char *inbuf, unsigned int nbytes ) { unsigned char *ivp; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; - - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - - if ( inbuflen <= c->unused ) + + if ( nbytes <= 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; - inbuflen; - inbuflen--, c->unused-- ) + nbytes; + nbytes--, c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); - return 0; + return; } if ( c->unused ) { /* XOR the input with the IV and store input into IV */ - inbuflen -= c->unused; + nbytes -= c->unused; for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } @@ -1185,17 +1117,17 @@ do_cfb_encrypt (gcry_cipher_hd_t c, /* 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 (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc) + if (nbytes >= blocksize_x_2 && c->bulk.cfb_enc) { - unsigned int nblocks = inbuflen / blocksize; - c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + unsigned int nblocks = nbytes / blocksize; + c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; - inbuflen -= nblocks * blocksize; + nbytes -= nblocks * blocksize; } else { - while ( inbuflen >= blocksize_x_2 ) + while ( nbytes >= blocksize_x_2 ) { int i; /* Encrypt the IV. */ @@ -1203,11 +1135,11 @@ do_cfb_encrypt (gcry_cipher_hd_t c, /* 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++); - inbuflen -= blocksize; + nbytes -= blocksize; } } - if ( inbuflen >= blocksize ) + if ( nbytes >= blocksize ) { int i; /* Save the current IV and then encrypt the IV. */ @@ -1216,56 +1148,51 @@ do_cfb_encrypt (gcry_cipher_hd_t c, /* 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++); - inbuflen -= blocksize; + nbytes -= blocksize; } - if ( inbuflen ) + if ( nbytes ) { /* 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 -= inbuflen; - for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + c->unused -= nbytes; + for(ivp=c->u_iv.iv; nbytes; nbytes-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } - return 0; } -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) +static void +do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, + const unsigned char *inbuf, unsigned int nbytes ) { unsigned char *ivp; unsigned long temp; int i; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; - - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - - if (inbuflen <= c->unused) + + if (nbytes <= 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; - inbuflen; - inbuflen--, c->unused--) + nbytes; + nbytes--, c->unused--) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - return 0; + return; } - + if (c->unused) { /* XOR the input with the IV and store input into IV. */ - inbuflen -= c->unused; + nbytes -= c->unused; for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) { temp = *inbuf++; @@ -1273,21 +1200,21 @@ do_cfb_decrypt (gcry_cipher_hd_t c, *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 (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec) + if (nbytes >= blocksize_x_2 && c->bulk.cfb_dec) { - unsigned int nblocks = inbuflen / blocksize; - c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + unsigned int nblocks = nbytes / blocksize; + c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; - inbuflen -= nblocks * blocksize; + nbytes -= nblocks * blocksize; } else { - while (inbuflen >= blocksize_x_2 ) + while (nbytes >= blocksize_x_2 ) { /* Encrypt the IV. */ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); @@ -1298,11 +1225,11 @@ do_cfb_decrypt (gcry_cipher_hd_t c, *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - inbuflen -= blocksize; + nbytes -= blocksize; } } - if (inbuflen >= blocksize ) + if (nbytes >= blocksize ) { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize); @@ -1314,109 +1241,99 @@ do_cfb_decrypt (gcry_cipher_hd_t c, *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - inbuflen -= blocksize; + nbytes -= blocksize; } - if (inbuflen) - { + if (nbytes) + { /* 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 -= inbuflen; - for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + c->unused -= nbytes; + for (ivp=c->u_iv.iv; nbytes; nbytes-- ) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } } - return 0; } -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) +static void +do_ofb_encrypt( gcry_cipher_hd_t c, + byte *outbuf, const byte *inbuf, unsigned nbytes ) { - unsigned char *ivp; + byte *ivp; size_t blocksize = c->cipher->blocksize; - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - - if ( inbuflen <= c->unused ) + if ( nbytes <= 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; - inbuflen; - inbuflen--, c->unused-- ) + nbytes; + nbytes--, c->unused-- ) *outbuf++ = (*ivp++ ^ *inbuf++); - return 0; + return; } if( c->unused ) { - inbuflen -= c->unused; + nbytes -= 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 ( inbuflen >= blocksize ) + while ( nbytes >= 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++); - inbuflen -= blocksize; + nbytes -= blocksize; } - if ( inbuflen ) + if ( nbytes ) { /* 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 -= inbuflen; - for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + c->unused -= nbytes; + for(ivp=c->u_iv.iv; nbytes; nbytes-- ) *outbuf++ = (*ivp++ ^ *inbuf++); } - return 0; } -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) +static void +do_ofb_decrypt( gcry_cipher_hd_t c, + byte *outbuf, const byte *inbuf, unsigned int nbytes ) { - unsigned char *ivp; + byte *ivp; size_t blocksize = c->cipher->blocksize; - - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - - if( inbuflen <= c->unused ) + + if( nbytes <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ - for (ivp=c->u_iv.iv+blocksize - c->unused; inbuflen; inbuflen--,c->unused--) + for (ivp=c->u_iv.iv+blocksize - c->unused; nbytes; nbytes--,c->unused--) *outbuf++ = *ivp++ ^ *inbuf++; - return 0; + return; } if ( c->unused ) { - inbuflen -= c->unused; + nbytes -= 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 ( inbuflen >= blocksize ) + while ( nbytes >= blocksize ) { int i; /* Encrypt the IV (and save the current one). */ @@ -1424,335 +1341,113 @@ 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++; - inbuflen -= blocksize; + nbytes -= blocksize; } - if ( inbuflen ) + if ( nbytes ) { /* 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 -= inbuflen; - for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + c->unused -= nbytes; + for (ivp=c->u_iv.iv; nbytes; nbytes-- ) *outbuf++ = *ivp++ ^ *inbuf++; } - return 0; } -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) +static void +do_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, + unsigned int nbytes ) { unsigned int n; + byte tmp[MAX_BLOCKSIZE]; int i; - unsigned int blocksize = c->cipher->blocksize; - unsigned int nblocks; - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - - /* First process a left over encrypted counter. */ - if (c->unused) + for(n=0; n < nbytes; n++) { - 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; - } + if ((n % c->cipher->blocksize) == 0) + { + c->cipher->encrypt (&c->context.c, tmp, c->ctr); - - /* 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 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) -{ - 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--) + for (i = c->cipher->blocksize; i > 0; i--) { - t[x]++; - if (t[x]) + c->ctr[i-1]++; + if (c->ctr[i-1] != 0) 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; + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ tmp[n % c->cipher->blocksize]; + } } -/* 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) +static void +do_ctr_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, + unsigned int nbytes ) { - 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; + do_ctr_encrypt (c, outbuf, inbuf, nbytes); } /**************** * Encrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. - * Depending on the mode some constraints apply to INBUFLEN. + * Depending on the mode some contraints apply to NBYTES. */ static gcry_err_code_t -cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) +cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, + const byte *inbuf, unsigned int nbytes) { - gcry_err_code_t rc; + gcry_err_code_t rc = GPG_ERR_NO_ERROR; - 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; + 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; } - - return rc; + return rc; } @@ -1766,15 +1461,29 @@ 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. */ - err = cipher_encrypt (h, out, outsize, out, outsize); + 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; else - err = cipher_encrypt (h, out, outsize, in, inlen); + err = cipher_encrypt (h, out, 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); + memset (out, 0x42, outsize); /* Failsafe: Make sure that the + plaintext will never make it into + OUT. */ return gcry_error (err); } @@ -1784,67 +1493,60 @@ 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 INBUFLEN. + * Depending on the mode some some contraints apply to NBYTES. */ static gcry_err_code_t -cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) +cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, + unsigned int nbytes) { - gcry_err_code_t rc; + gcry_err_code_t rc = GPG_ERR_NO_ERROR; - 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; + 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; } - - return rc; + return rc; } @@ -1852,12 +1554,25 @@ 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; + gcry_err_code_t err = 0; - if (!in) /* Caller requested in-place encryption. */ - err = cipher_decrypt (h, out, outsize, out, outsize); + 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; else - err = cipher_decrypt (h, out, outsize, in, inlen); + err = cipher_decrypt (h, out, in, inlen); return gcry_error (err); } @@ -1903,15 +1618,9 @@ 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->u_ctr.ctr, ctr, hd->cipher->blocksize); - hd->unused = 0; - } + memcpy (hd->ctr, ctr, hd->cipher->blocksize); else if (!ctr || !ctrlen) - { - memset (hd->u_ctr.ctr, 0, hd->cipher->blocksize); - hd->unused = 0; - } + memset (hd->ctr, 0, hd->cipher->blocksize); else return gpg_error (GPG_ERR_INV_ARG); return 0; @@ -1970,12 +1679,17 @@ 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. */ - rc = gpg_err_code (_gcry_cipher_setctr (h, buffer, buflen)); + 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; 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; @@ -1983,7 +1697,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. */ @@ -1994,7 +1708,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); @@ -2016,10 +1730,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. - - The function always returns GPG_ERR_INV_OP. + There are no values for CMD yet defined. + 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) @@ -2056,11 +1770,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 occurred or not (i.e. while + and thereby detecting whether a error occured or not (i.e. while checking the block size) */ gcry_error_t @@ -2080,7 +1794,8 @@ 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 for an error is an invalid algo. */ + /* The only reason is an invalid algo or a strange + blocksize. */ err = GPG_ERR_CIPHER_ALGO; } break; @@ -2124,7 +1839,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; @@ -2140,7 +1855,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; @@ -2201,7 +1916,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 28454f8ab..d04fff894 100644 --- a/grub-core/lib/libgcrypt/cipher/crc.c +++ b/grub-core/lib/libgcrypt/cipher/crc.c @@ -25,11 +25,120 @@ #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 { @@ -38,302 +147,8 @@ 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) { @@ -342,40 +157,12 @@ crc32_init (void *context) } static void -crc32_write (void *context, const void *inbuf_arg, size_t inlen) +crc32_write (void *context, const void *inbuf, size_t inlen) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; - const byte *inbuf = inbuf_arg; - u32 crc; - - if (!inbuf || !inlen) + if (!inbuf) return; - - 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; + ctx->CRC = update_crc32 (ctx->CRC, inbuf, inlen); } static byte * @@ -390,12 +177,13 @@ crc32_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; ctx->CRC ^= 0xffffffffL; - buf_put_be32 (ctx->buf, ctx->CRC); + 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; } /* CRC32 a'la RFC 1510 */ -/* CRC of the string "123456789" is 0x2dfd2d88 */ - static void crc32rfc1510_init (void *context) { @@ -407,366 +195,82 @@ static void crc32rfc1510_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; - buf_put_be32(ctx->buf, ctx->CRC); + 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; } /* CRC24 a'la RFC 2440 */ /* - * Code generated by universal_crc by Danjel McGougan + * The following CRC 24 routines are adapted from RFC 2440, which has + * the following copyright notice: * - * CRC parameters used: - * bits: 24 - * poly: 0x864cfb - * init: 0xb704ce - * xor: 0x000000 - * reverse: false - * non-direct: false + * Copyright (C) The Internet Society (1998). All Rights Reserved. * - * CRC of the string "123456789" is 0x21cf02 + * 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 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; -} +#define CRC24_INIT 0xb704ceL +#define CRC24_POLY 0x1864cfbL 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 || !inlen) + if (!inbuf) return; - 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--) { + ctx->CRC ^= (*inbuf++) << 16; + for (i = 0; i < 8; i++) { + ctx->CRC <<= 1; + if (ctx->CRC & 0x1000000) + ctx->CRC ^= CRC24_POLY; } - - 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->CRC = crc24_final(ctx->CRC); - buf_put_le32 (ctx->buf, ctx->CRC); + ctx->buf[0] = (ctx->CRC >> 16) & 0xFF; + ctx->buf[1] = (ctx->CRC >> 8) & 0xFF; + ctx->buf[2] = (ctx->CRC ) & 0xFF; } 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 96b06ae36..f91df7771 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/Triple-DES implementation occurred: %s\n", error_msg); + * fprintf(stderr, "An error in the DES/Tripple-DES implementation occured: %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 883a815f2..100710f97 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,19 +141,14 @@ 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 ); @@ -161,20 +156,13 @@ 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 these extra bytes here. - However the required management code is more complex and - thus we better use this simple method. */ + to get_random_bytes() and use this the here maybe it is + easier to do this directly in random.c. */ 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 @@ -184,7 +172,7 @@ gen_k( gcry_mpi_t q ) } if( !(mpi_cmp( k, q ) < 0) ) /* check: k < q */ - { + { if( DBG_CIPHER ) progress('+'); continue; /* no */ @@ -200,7 +188,7 @@ gen_k( gcry_mpi_t q ) gcry_free(rndbuf); if( DBG_CIPHER ) progress('\n'); - + return k; } @@ -327,7 +315,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. */ } @@ -342,13 +330,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 ); @@ -357,7 +345,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 ); @@ -367,7 +355,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 ); @@ -418,8 +406,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. */ @@ -479,15 +467,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 */ @@ -505,33 +493,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 ); @@ -703,7 +691,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. */ @@ -712,7 +700,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) @@ -720,7 +708,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 ) { @@ -772,7 +760,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); @@ -816,7 +804,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)); @@ -891,7 +879,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. */ @@ -906,8 +894,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)); } } @@ -919,7 +907,6 @@ 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) { @@ -1035,19 +1022,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 raw)" - " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; - static const char sample_data_bad[] = - "(data (flags raw)" - " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; + static const char sample_data[] = + "(data (flags pkcs1)" + " (hash sha1 #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; + static const char sample_data_bad[] = + "(data (flags pkcs1)" + " (hash sha1 #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; const char *errtxt = NULL; gcry_error_t err; @@ -1058,7 +1045,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) { @@ -1105,10 +1092,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) { @@ -1158,7 +1145,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1175,7 +1162,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, @@ -1186,8 +1173,9 @@ 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 b8487dc13..fcbd8e3a9 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, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, @@ -33,21 +33,20 @@ 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. - - ECDH encrypt and decrypt code written by Andrey Jivsov, -*/ + been rewritten and moved to mpi/ec.c. */ /* TODO: - - If we support point compression we need to uncompress before - computing the keygrip + - If we support point compression we need to decide how to compute + the keygrip - it should not change due to compression. - 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. */ @@ -60,6 +59,7 @@ #include "mpi.h" #include "cipher.h" + /* Definition of a curve. */ typedef struct { @@ -68,8 +68,7 @@ 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. */ - const char *name; /* Name of curve or NULL. */ -} elliptic_curve_t; +} elliptic_curve_t; typedef struct @@ -91,7 +90,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. */ @@ -101,11 +100,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" }, @@ -121,7 +120,11 @@ static const struct { NULL, NULL} }; -typedef struct { + + +/* This static table defines all available curves. */ +static const 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. */ @@ -129,10 +132,7 @@ typedef struct { const char *a, *b; /* The coefficients. */ const char *n; /* The order of the base point. */ const char *g_x, *g_y; /* Base point. */ -} ecc_domain_parms_t; - -/* This static table defines all available curves. */ -static const ecc_domain_parms_t domain_parms[] = +} domain_parms[] = { { "NIST P-192", 192, 1, @@ -197,7 +197,7 @@ static const ecc_domain_parms_t domain_parms[] = "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" }, - { "brainpoolP160r1", 160, 0, + { "brainpoolP160r1", 160, 0, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -206,7 +206,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x1667cb477a1a8ec338f94741669c976316da6321" }, - { "brainpoolP192r1", 192, 0, + { "brainpoolP192r1", 192, 0, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -369,6 +369,7 @@ curve_copy (elliptic_curve_t E) } + /* Helper to scan a hex string. */ static gcry_mpi_t scanval (const char *string) @@ -399,10 +400,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); @@ -411,6 +412,9 @@ 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. @@ -424,8 +428,7 @@ 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 at seclevel %d\n", - nbits, security_level); + log_debug ("choosing a random k of %u bits\n", nbits); gcry_mpi_randomize (k, nbits, security_level); @@ -434,27 +437,23 @@ gen_k (gcry_mpi_t p, int security_level) return k; } - -/* 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. */ +/**************** + * 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. + */ static gpg_err_code_t -fill_in_curve (unsigned int nbits, const char *name, - elliptic_curve_t *curve, unsigned int *r_nbits) +generate_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 our native curves. */ + /* First check nor native curves. */ for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (name, domain_parms[idx].desc)) - { - resname = domain_parms[idx].desc; - break; - } + break; /* If not found consult the alias table. */ if (!domain_parms[idx].desc) { @@ -466,10 +465,7 @@ fill_in_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)) - { - resname = domain_parms[idx].desc; - break; - } + break; } } } @@ -486,7 +482,8 @@ fill_in_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); @@ -496,7 +493,6 @@ fill_in_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; } @@ -508,39 +504,33 @@ fill_in_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, - const char **r_usedcurve) + gcry_mpi_t q_x, gcry_mpi_t q_y) { 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; - *r_usedcurve = NULL; - - err = fill_in_curve (nbits, name, &E, &nbits); + err = generate_curve (nbits, name, &E, &nbits); if (err) return err; if (DBG_CIPHER) { - 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); + 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); } - random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; - d = gen_k (E.n, random_level); + if (DBG_CIPHER) + log_debug ("choosing a random x of size %u\n", nbits); + d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM); /* Compute Q. */ point_init (&Q); @@ -562,29 +552,27 @@ 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 ("ecgen: Failed to get affine coordinates\n"); + log_fatal ("ecc generate: 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 ("ecgen: Failed to get affine coordinates\n"); + log_fatal ("ecc generate: 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. @@ -634,56 +622,54 @@ 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_ec_t ctx = NULL; - - point_init (&Q); + gcry_mpi_t y_2, y2 = mpi_alloc (0); + mpi_ec_t ctx; /* ?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"); - goto leave; + return (1); } /* 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"); - goto leave; + return (1); } + 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"); - goto leave; + point_free (&Q); + _gcry_mpi_ec_free (ctx); + return 1; } /* 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"); - goto leave; + _gcry_mpi_ec_free (ctx); + return (1); } /* pubkey = [d]G over E */ _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx); @@ -692,16 +678,12 @@ check_secret_key (ECC_secret_key * sk) if (DBG_CIPHER) log_debug ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); - goto leave; + _gcry_mpi_ec_free (ctx); + return (1); } - rc = 0; /* Okay. */ - - leave: _gcry_mpi_ec_free (ctx); - mpi_free (y2); - mpi_free (y_2); point_free (&Q); - return rc; + return 0; } @@ -717,9 +699,6 @@ 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); @@ -742,7 +721,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) @@ -758,12 +737,6 @@ 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); @@ -776,7 +749,6 @@ 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. */ @@ -848,10 +820,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; @@ -874,7 +846,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) } - + /********************************************* ************** interface ****************** *********************************************/ @@ -907,16 +879,18 @@ 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 @@ -935,7 +909,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; @@ -945,7 +919,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; @@ -971,7 +945,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) mpi_free (x); mpi_free (y); - + return 0; } @@ -988,11 +962,10 @@ 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) { @@ -1005,14 +978,6 @@ 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. */ @@ -1023,45 +988,28 @@ 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, transient_key, g_x, g_y, q_x, q_y, - &usedcurve); + ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y); 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 (); /* 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 gpg_err_code_from_syserror (); return 0; } @@ -1076,7 +1024,7 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, } -/* Return the parameters of the curve NAME in an MPI array. */ +/* Return the parameters of the curve NAME. */ static gcry_err_code_t ecc_get_param (const char *name, gcry_mpi_t *pkey) { @@ -1085,8 +1033,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 = fill_in_curve (0, name, &E, &nbits); + + err = generate_curve (0, name, &E, &nbits); if (err) return err; @@ -1105,120 +1053,10 @@ 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) { @@ -1227,9 +1065,8 @@ 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[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10]) return GPG_ERR_BAD_MPI; sk.E.p = skey[0]; @@ -1313,7 +1150,6 @@ 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) @@ -1357,221 +1193,6 @@ 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) @@ -1582,23 +1203,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) { -#define N_COMPONENTS 6 - static const char names[N_COMPONENTS+1] = "pabgnq"; + static const char names[] = "pabgnq"; gpg_err_code_t ec = 0; gcry_sexp_t l1; - gcry_mpi_t values[N_COMPONENTS]; + gcry_mpi_t values[6]; int idx; /* Clear the values for easier error cleanup. */ - for (idx=0; idx < N_COMPONENTS; idx++) + for (idx=0; idx < 6; idx++) values[idx] = NULL; - - /* Fill values with all provided parameters. */ - for (idx=0; idx < N_COMPONENTS; idx++) + + /* Fill values with all available parameters. */ + for (idx=0; idx < 6; idx++) { l1 = gcry_sexp_find_token (keyparam, names+idx, 1); if (l1) @@ -1612,20 +1233,19 @@ 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[N_COMPONENTS]; - - for (idx = 0; idx < N_COMPONENTS; idx++) + gcry_mpi_t tmpvalues[6]; + + for (idx = 0; idx < 6; 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. */ @@ -1636,7 +1256,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) if (ec) goto leave; - for (idx = 0; idx < N_COMPONENTS; idx++) + for (idx = 0; idx < 6; idx++) { if (!values[idx]) values[idx] = tmpvalues[idx]; @@ -1646,9 +1266,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 function later and + should not be required but we use an internal fucntion later and thus we better make 100% sure that they are normalized). */ - for (idx = 0; idx < N_COMPONENTS; idx++) + for (idx = 0; idx < 6; idx++) if (!values[idx]) { ec = GPG_ERR_NO_OBJ; @@ -1656,14 +1276,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 < N_COMPONENTS; idx++) + for (idx = 0; idx < 6; idx++) { char buf[30]; unsigned char *rawmpi; unsigned int rawmpilen; - + rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL); if (!rawmpi) { @@ -1678,18 +1298,17 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } leave: - for (idx = 0; idx < N_COMPONENTS; idx++) + for (idx = 0; idx < 6; idx++) _gcry_mpi_release (values[idx]); - + return ec; -#undef N_COMPONENTS } -/* +/* Self-test section. */ @@ -1699,7 +1318,7 @@ selftests_ecdsa (selftest_report_func_t report) { const char *what; const char *errtxt; - + what = "low-level"; errtxt = NULL; /*selftest ();*/ if (errtxt) @@ -1732,7 +1351,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1746,12 +1365,6 @@ static const char *ecdsa_names[] = "ecc", NULL, }; -static const char *ecdh_names[] = - { - "ecdh", - "ecc", - NULL, - }; gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = { @@ -1767,27 +1380,11 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = ecc_get_nbits }; -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 = +pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = { run_selftests, ecc_generate_ext, compute_keygrip, - ecc_get_param, - ecc_get_curve, - ecc_get_param_sexp + ecc_get_param }; + diff --git a/grub-core/lib/libgcrypt/cipher/elgamal.c b/grub-core/lib/libgcrypt/cipher/elgamal.c index ce4be8524..0b0c07cb4 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,9 +837,10 @@ 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 8c413bcba..656e180e2 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,3 +91,4 @@ _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 fdebef42a..9c4e33359 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 a32ece75d..56c9b203c 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 deleted file mode 100644 index 3c5578f95..000000000 --- a/grub-core/lib/libgcrypt/cipher/idea.c +++ /dev/null @@ -1,378 +0,0 @@ -/* 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 deleted file mode 100644 index 46e8550df..000000000 --- a/grub-core/lib/libgcrypt/cipher/kdf.c +++ /dev/null @@ -1,278 +0,0 @@ -/* 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 c3b3a4f3a..5dfbbd95a 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,10 +87,6 @@ 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, @@ -105,7 +101,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 whether the default ciphers have already been +/* Flag to check wether the default ciphers have already been registered. */ static int default_digests_registered; @@ -177,7 +173,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 ()) @@ -230,7 +226,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; @@ -271,11 +267,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; @@ -296,7 +292,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; @@ -567,7 +563,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"); @@ -578,7 +574,7 @@ md_enable (gcry_md_hd_t hd, int algorithm) err = GPG_ERR_DIGEST_ALGO; } } - + if (!err) { size_t size = (sizeof (*entry) @@ -635,7 +631,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); @@ -697,7 +693,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); @@ -787,7 +783,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) @@ -838,8 +834,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); @@ -860,7 +856,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) @@ -876,7 +872,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; @@ -890,7 +886,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: @@ -952,13 +948,10 @@ md_read( gcry_md_hd_t a, int algo ) if (! algo) { - /* 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); - } + /* 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 ); } else { @@ -1142,7 +1135,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 occurred or not (i.e. while checking + * and thereby detecting whether a error occured or not (i.e. while checking * the block size) */ gcry_error_t @@ -1167,7 +1160,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)) { @@ -1202,7 +1195,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"); @@ -1232,7 +1225,6 @@ md_stop_debug( gcry_md_hd_t md ) volatile u64 b = 42; volatile u64 c; c = a * b; - (void)c; } #endif } @@ -1269,7 +1261,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) @@ -1303,7 +1295,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; @@ -1315,7 +1307,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; @@ -1367,7 +1359,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 22fbf8d90..aa180f0d4 100644 --- a/grub-core/lib/libgcrypt/cipher/md4.c +++ b/grub-core/lib/libgcrypt/cipher/md4.c @@ -53,6 +53,7 @@ #include #include "g10lib.h" +#include "memory.h" #include "cipher.h" #include "bithelp.h" @@ -198,7 +199,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; @@ -259,15 +260,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; @@ -325,3 +326,4 @@ 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 a98678a9b..3d3046df2 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,6 +37,7 @@ #include #include "g10lib.h" +#include "memory.h" #include "cipher.h" #include "bithelp.h" @@ -87,9 +88,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; @@ -221,7 +222,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 ); @@ -242,7 +243,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; @@ -269,7 +270,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 b12e79b19..b869bee83 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_calloc (n, sizeof *pool_in_use); + pool_in_use = gcry_malloc (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; - - 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.) */ + + err = prime_generate_internal ((mode == 1), &prime, pbits, qbits, g, + ret_factors, GCRY_WEAK_RANDOM, 0, 0, + NULL, NULL); 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_xcalloc( no_of_small_prime_numbers, sizeof *mods); + mods = gcry_xmalloc( 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 initialize the array with the first M + permutation it is useful to intialize 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 whether the number X is prime. */ +/* Check wether 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; + gcry_mpi_release (b); + gcry_mpi_release (pmin1); + *r_g = g; - return 0; + 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,3 +1859,4 @@ _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 ca087ad75..08abcbfde 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, 2011 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, + * 2007, 2008 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,8 +75,6 @@ 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 }, }; @@ -87,7 +85,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 whether the default pubkeys have already been +/* Flag to check wether the default pubkeys have already been registered. */ static int default_pubkeys_registered; @@ -199,7 +197,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) \ @@ -217,8 +215,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); } @@ -242,7 +240,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; @@ -271,8 +269,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); @@ -561,13 +559,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); @@ -617,7 +615,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); @@ -686,7 +684,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); @@ -760,10 +758,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); @@ -784,1018 +782,6 @@ 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, @@ -1869,11 +855,7 @@ 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 >= 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. */ - + gcry_assert (idx >= 6); /* We know that ECC has at least 6 elements. */ /* Init the array with the available curve parameters. */ for (name = element_names, idx = 0; *name && !err; name++, idx++) @@ -1902,23 +884,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]) @@ -1942,7 +924,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, err = GPG_ERR_NO_OBJ; goto leave; } - + leave: if (err) { @@ -1966,7 +948,6 @@ 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 @@ -1974,10 +955,6 @@ 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. * @@ -1993,8 +970,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, const char *override_elems, - gcry_mpi_t **retarray, gcry_module_t *retalgo) +sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, + gcry_module_t *retalgo) { gcry_err_code_t err = 0; gcry_sexp_t list, l2; @@ -2007,7 +984,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, 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. */ @@ -2025,18 +1002,16 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, 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, "ecdh") - || !strcmp (name, "ecc") ); + algorithm which has many flavours. */ + is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); gcry_free (name); - + if (!module) { gcry_sexp_release (list); @@ -2048,15 +1023,10 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, extraspec = module->extraspec; } - if (override_elems) - elems = override_elems; - else if (want_private) - elems = pubkey->elements_skey; - else - elems = pubkey->elements_pkey; + elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey; array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); if (!array) - err = gpg_err_code_from_syserror (); + err = gpg_err_code_from_errno (errno); if (!err) { if (is_ecc) @@ -2064,9 +1034,9 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, else err = sexp_elements_extract (list, elems, array, pubkey->name); } - + gcry_sexp_release (list); - + if (err) { gcry_free (array); @@ -2080,7 +1050,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, *retarray = array; *retalgo = module; } - + return err; } @@ -2096,7 +1066,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) @@ -2115,7 +1085,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. */ @@ -2129,7 +1099,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); @@ -2148,7 +1118,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_syserror (); + err = gpg_err_code_from_errno (errno); if (!err) err = sexp_elements_extract (list, elems, array, NULL); @@ -2161,7 +1131,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 @@ -2169,82 +1139,26 @@ 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 [raw, pkcs1, oaep, no-blinding])] - * [(hash-algo )] - * [(label