diff --git a/.bzrignore b/.bzrignore index b532d587f..43eec745d 100644 --- a/.bzrignore +++ b/.bzrignore @@ -5,6 +5,8 @@ 30_os-prober 40_custom 41_custom +*.1 +*.8 aclocal.m4 ascii.bitmaps ascii.h @@ -14,14 +16,12 @@ build_env.mk config.cache config.guess config.h -config.h.in +config-util.h +config-util.h.in config.log config.status config.sub configure -conf/*.mk -conf/gcry.rmk -*.d DISTLIST debian/grub-extras/*/conf/*.mk docs/*.info @@ -42,6 +42,9 @@ grub-fstest grub_fstest_init.c grub_fstest_init.h grub-install +grub-kbdcomp +grub-macho2img +grub-menulst2cfg grub-mk* grub-mkpasswd-pbkdf2 grub-pe2elf @@ -60,23 +63,75 @@ 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 *.pf2 +*.pp po/*.mo po/grub.pot 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/genmod.sh +grub-core/gensyminfo.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 +widthspec.bin +widthspec.h 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 b/ChangeLog index 958c55c79..8f78477e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,3978 @@ +2010-11-15 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c (grub_keyboard_controller_read) + [GRUB_MACHINE_MIPS_YEELOONG || GRUB_MACHINE_QEMU]: ifdef-ed out + (now unused). + (grub_keyboard_controller_init) + [GRUB_MACHINE_MIPS_YEELOONG || GRUB_MACHINE_QEMU]: Don't attempt to + read the initial state since controller isn't inited yet. + +2010-11-15 Vladimir Serbinenko + + * grub-core/lib/relocator.c (malloc_in_range): Take into account that + allocate_regbeg may need to create new chunk header. + +2010-11-14 Vladimir Serbinenko + + Fix quoting in legacy parser. + + * grub-core/lib/legacy_parse.c (grub_legacy_escape): Correctly handle + single quotes. + (grub_legacy_parse): Likewise. + Reported by: Jordan Uggla. + Tested by: Jordan Uggla. + +2010-11-14 Vladimir Serbinenko + + Don't add -lgcc on i386 and x86_64. + + * configure.ac (LIBS): Don't add -lgcc on i386 and x86_64. + * conf/Makefile.common (LDADD_KERNEL): Likewise. + * grub-core/Makefile.core.def (kernel): Use LDADD_KERNEL. + +2010-11-14 Vladimir Serbinenko + + * configure.ac: Add -Wno-trampolines when supported. + +2010-11-14 Modestas Vainius + + * grub-core/kern/emu/getroot.c (grub_util_is_dmraid): Recognise ddf1_ + fakeraid. + +2010-11-14 Giuseppe Caizzone + + Add generic logical block size support for UDF. + + * grub-core/fs/udf.c (GRUB_UDF_LOG2_BLKSIZE): Removed. + (GRUB_UDF_BLKSZ): Removed. + (struct grub_udf_data): New field "lbshift" to hold the logical block + size of the file system in log2 format. All users updated. + (sblocklist): Change type to unsigned. + (grub_udf_mount): Change type of "sblklist" to unsigned. + Move AVDP search before VRS recognition, because the latter requires + knowledge of the logical block size, which is detected during the + former. + Detect and validate logical block size during AVDP search, adding + support for block sizes 512, 1024 and 4096. + Make VRS recognition independent of block size. + +2010-11-14 Giuseppe Caizzone + + Properly handle deleted files on UDF. + + * grub-core/fs/udf.c (grub_udf_iterate_dir): Skip directory entries + whose "characteristics" field has the bit GRUB_UDF_FID_CHAR_DELETED + set. + +2010-11-14 Giuseppe Caizzone + + Support reading files larger than 2 GiB. + + * grub-core/fs/udf.c (grub_udf_iterate_dir): Change type of variable + "offset" to grub_off_t. + (grub_udf_read_file): Likewise for parameter "pos". + +2010-11-14 Vladimir Serbinenko + + * docs/grub.texi (Changes from GRUB Legacy): Note when save_env is + unavailable. + (Simple configuration): Refer to Changes from GRUB Legacy about + save_env availability. + +2010-11-14 Vladimir Serbinenko + + * util/grub-install.in: Ignore empty partition table detection + instead of trying to include part_ module. + +2010-11-14 Vladimir Serbinenko + + * grub-core/disk/lvm.c (GRUB_MOD_FINI): Reset the vg_list. Fixes + LVM on RAID support. + +2010-11-14 Vladimir Serbinenko + + Properly define WORDS_BIGENDIAN in wrapped environments. + + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (WORDS_BIGENDIAN): New + definition. + * grub-core/lib/posix_wrap/sys/types.h (WORDS_BIGENDIAN): Likewise. + + Reported by: Manoel Rebelo Abranches. + Tested by: Manoel Rebelo Abranches. + +2010-11-13 Vladimir Serbinenko + + * util/grub-mkconfig.in: Fix quoting. + +2010-11-13 Vladimir Serbinenko + + Support big ext2 files. + + * grub-core/fs/ext2.c (grub_ext2_inode): Rename dir_acl to size_high. + (grub_ext2_read_block): Support triple indirect blocks. + (grub_ext2_read_file): Use 64-bit types and read size_high. + (grub_ext2_open): Read size_high. + Reported by: Ximin Luo. + Tested by: Manoel Rebelo Abranches. + +2010-11-13 Vladimir Serbinenko + + * util/grub-install.in: Handle filenames containing spaces. + Reported by: Jordan Uggla. + Tested by: Jordan Uggla. + +2010-11-13 Vladimir Serbinenko + + * util/grub-mkconfig.in (grub_script_check): New variable. + Use grub_script_check instead of grub-script-check. + Reported by: Barry Jackson. + +2010-11-13 Vladimir Serbinenko + + * docs/grub.texi (menu): Correct the order. + Reported by: D. Hugh Redelmeier. + +2010-11-12 Vladimir Serbinenko + + * grub-core/kern/i386/pc/startup.S (multiboot_trampoline): Add missing + jump. + +2010-11-08 Manoel Rebelo Abranches + + * include/grub/elfload.h (grub_elf32_size): New parameter. + All users updated. + Return maximum segments alignment. + (grub_elf64_size): Likewise. + * kern/elf.c (grub_elf32_size): New parameter. All users updated. + Return maximum segments alignment. + (grub_elf64_size): Likewise. + * grub-core/loader/powerpc/ieee1275/linux.c: + (grub_linux_claimmap_iterate): New function. Uses the + "available" property in the "memory" node for memory allocation + for kernel in the PowerPC loader. + (grub_linux_load32): Correctly find linux entry point offset. + (grub_linux_load64): Likewise. + +2010-11-07 Robert Millan + + On mips-yeeloong, build with -march=loongson2f when this flag is + available (GCC >= 4.4). + * conf/Makefile.common [COND_mips_yeeloong] (CFLAGS_PLATFORM): Remove + `-march=mips3'. + * configure.ac: For mips-yeeloong, add -march=loongson2f if available, + or otherwise add -march=mips3. + +2010-11-07 BVK Chaitanya + + Suppress shell expansion on echo '*' and echo "*" like cases. + Reported by: Jordan Uggla. + + * grub-core/script/execute.c (grub_script_arglist_to_argv): Escape + string arguments before shell expansion. + * tests/grub_cmd_echo.in: New testcases. + +2010-11-07 Robert Millan + + * conf/mips-qemu-mips.rmk: Remove stale file from previous + transition. + +2010-11-07 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Handle devices like "sdaa1". + +2010-11-06 Vladimir Serbinenko + + * include/grub/emu/misc.h: Don't include grub/util/libzfs.h. + * include/grub/emu/misc.h (grub_get_libzfs_handle): Move from here ... + * include/grub/util/libzfs.h (grub_get_libzfs_handle): ... here. + +2010-11-06 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (grub_ntfs_uuid): Make uppercase. + +2010-11-06 Vladimir Serbinenko + + * util/grub-install.in: Replace useless recomendation to pass + --modules with a recomendation to report a bug. + +2010-11-06 Vladimir Serbinenko + + Properly register serial terminfo. + Reported by: Jordan Uggla + + * grub-core/term/serial.c (grub_serial_terminfo_input_template): New + const. + (grub_serial_terminfo_output_template): Likewise. + (grub_cmd_serial): Register "serial" with terminfo. + (GRUB_MOD_INIT(serial)): Fill grub_serial_terminfo_input and + grub_serial_terminfo_output. + +2010-11-05 Robert Millan + + * util/grub-mkconfig.in: Remove gfxterm.mod probe (no longer + needed). + +2010-11-05 Robert Millan + + On Yeeloong, pass machine type information to Linux. + + * grub-core/loader/mips/linux.c [GRUB_MACHINE_MIPS_YEELOONG] + (LOONGSON_MACHTYPE): New macro, set to + "machtype=lemote-yeeloong-2f-8.9inches". + [LOONGSON_MACHTYPE] (grub_cmd_linux): Pass LOONGSON_MACHTYPE as + additional argument to Linux. + +2010-11-04 Robert Millan + + * util/deviceiter.c (grub_util_iterate_devices): Increase SCSI + limit to 48 (to cope with Sun Fire X4500), and IDE limit to 96 + (its SATA disks are detected as slaveless IDE master drives on + kFreeBSD). + Reported by Carsten Aulbert. + +2010-11-02 Colin Watson + + * util/bin2h.c (main): Fix spelling error in generated output. + +2010-11-01 Grégoire Sutre + + * grub-core/partmap/bsdlabel.c (iterate_real): Fix an integer overflow. + +2010-11-01 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (grub_cmd_linux): Autoload vbe.mod if + vga= option is supplied. + +2010-11-01 Vladimir Serbinenko + + * util/grub.d/10_hurd.in: Don't call savedefault on recovery entries. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + +2010-11-01 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_parse): Avoid interpreting direct + argument as an argument to no-argument option. + +2010-11-01 Vladimir Serbinenko + + * util/grub.d/10_linux.in: Add missing load_video with explicit + GRUB_GFXPAYLOAD_LINUX. + +2010-11-01 Vladimir Serbinenko + + * Makefile.am (libgrub.pp): Propagate the libgrub.a split. + +2010-11-01 Vladimir Serbinenko + + * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Do not put + elements with invlid index. + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. + * grub-core/disk/raid.c (insert_array): Automatically reallocate + members. + * include/grub/raid.h (grub_raid_member): New struct. + (grub_raid_array): Transform devices and start_sector into usage of + grub_raid_member. All users updated + (allocated_devs): New member. + +2010-11-01 Vladimir Serbinenko + + * docs/man/grub-set-default.h2m: Clarify that only saved default entry + is modified + +2010-10-29 BVK Chaitanya + + NetBSD build fix for getline function conflict from gnulib. + + * Makefile.util.def (libgrubkern.a): New library for grub kernel + components that depend on gnulib headers. + (libgrubmods.a): Renamed from earlier libgrub.a. + * conf/Makefile.common: Remove gnulib from *_LIBRARY flags. + +2010-10-26 Vladimir Serbinenko + + * util/grub-setup.c (setup): Refuse to do a cross-disk embeddingless + install rather than creating a broken install. + +2010-10-26 Vladimir Serbinenko + + * util/grub-setup.c (argp): Remove misleading example of installing to + a partition. + +2010-10-26 Vladimir Serbinenko + + * util/grub-setup.c (setup): Clarify the error message. + +2010-10-26 Vladimir Serbinenko + + * include/grub/types.h (grub_target_off_t): Removed no longer used type. + +2010-10-23 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c + (grub_make_system_path_relative_to_its_root) + [HAVE_LIBZFS && HAVE_LIBNVPAIR]: Fix mountpoint return on ZFS. + +2010-10-23 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c + (grub_make_system_path_relative_to_its_root): Revert r2882. + +2010-10-22 Vladimir Serbinenko + + * grub-core/lib/relocator.c (grub_relocator_subchunk): Remove now + useless field head. All users updated. + (free_subchunk): Correct handling of IN_REGION subchunk. + +2010-10-22 Colin Watson + + * docs/grub.texi (Installing GRUB using grub-install): Proofread. + (Supported kernels): Likewise. + +2010-10-18 Grégoire Sutre + + Make mktemp invocations portable. + + * grub-core/genmod.sh.in: Use mktemp with an explicit template, and + exit if mktemp fails. + * tests/grub_script_blockarg.in: Likewise. + * tests/partmap_test.in: Likewise. + * tests/util/grub-shell-tester.in: Likewise. + * tests/util/grub-shell.in: Likewise. + * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. + * Makefile.am: Likewise, and chain shell commands with `&&' + instead of ';'. + * util/grub-mkrescue.in: Use the same explicit template as above, and + exit if mktemp fails. + +2010-10-18 BVK Chaitanya + + * util/grub.d/10_linux.in: Fix built-in initramfs image mode for + Linux kernel, reported by Dennis Schridde. + +2010-10-17 Szymon Janc + + * grub-core/normal/auth.c (grub_auth_check_authentication): + Set-but-not-used variable removed. + +2010-10-17 Vladimir Serbinenko + + * docs/grub.texi (GNU/Linux): Document APM unavailability with + 32-bit linux protocol. + +2010-10-17 Vladimir Serbinenko + + * grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Check + cursor shape for sanity. + +2010-10-17 Vladimir Serbinenko + + * docs/grub.texi (Installation): Document buggy BIOS install. + +2010-10-17 Vladimir Serbinenko + + * docs/grub.texi (Installation): Indent. + +2010-10-17 Vladimir Serbinenko + + * util/grub-setup.c (setup): New parameter allow_floppy. + (arguments): New member allow_floppy. + (argp_parser): Handle --allow-floppy. + (main): Pass allow_floppy. + * util/grub-install.in: New option --allow-floppy passed though to + grub-setup. + +2010-10-17 Vladimir Serbinenko + + * util/grub-install.in: Handle partitionless disks. + +2010-10-17 Vladimir Serbinenko + + * util/grub-setup.c (setup): Don't clean blocklists before readability + verfification. + +2010-10-16 Vladimir Serbinenko + + * docs/grub.texi (Installation): Document embedding zone. Remove + obsolete grub-install example. + +2010-10-16 Szymon Janc + + * grub-core/commands/legacycfg.c (grub_cmd_legacy_kernel): + Set-but-not-used variable ifdef'ed. + * grub-core/lib/legacy_parse.c (grub_legacy_parse): Likewise. + * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Set-but-not-used + variable removed. + * grub-core/disk/lvm.c (grub_lvm_scan_device): Likewise. + * grub-core/fs/jfs.c (grub_jfs_find_file): Likewise. + * grub-core/fs/minix.c (grub_minix_dir): Likewise. + * grub-core/fs/sfs.c (grub_sfs_read_extent): Likewise. + * grub-core/fs/ufs.c (grub_ufs_dir): Likewise. + * grub-core/gfxmenu/gui_list.c (grub_gui_list_new): Likewise. + * grub-core/gfxmenu/view.c (redraw_menu_visit): Likewise. + * grub-core/gfxmenu/widget-box.c (draw): Likewise. + * grub-core/lib/relocator.c (malloc_in_range): Likewise. + * grub-core/loader/i386/bsdXX.c (grub_netbsd_load_elf_meta): Likewise. + * grub-core/loader/i386/bsd_pagetable.c (fill_bsd64_pagetable): + Likewise. + +2010-10-16 Vladimir Serbinenko + + * grub-core/commands/acpihalt.c (skip_ext_op): Skip index field op. + * include/grub/acpi.h (GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP): New + enum value. + +2010-10-16 Vladimir Serbinenko + + * grub-core/commands/acpihalt.c (get_sleep_type): Accept \_S5_ as + synonym to _S5_. Needed for some DSDTs. + +2010-10-16 Vladimir Serbinenko + + Userspace ACPI parser debugging. + + * grub-core/commands/acpihalt.c [GRUB_DSDT_TEST]: Include userspace + headers and add relevant defines. Don't include standard headers. + (main) [GRUB_DSDT_TEST]: New function. + * include/grub/acpi.h [GRUB_DSDT_TEST]: Don't include standard headers. + Don't declare functions. + +2010-10-16 Vladimir Serbinenko + + Remove dead grub_efi_mm_fini. + + * grub-core/kern/efi/mm.c (allocated_page): Removed. + (ALLOCATED_PAGES_SIZE): Likewise. + (MAX_ALLOCATED_PAGES): Likewise. + (allocated_pages): Likewise. + (grub_efi_allocate_pages): Don't record allocated pages. + (grub_efi_free_pages): Likewise. + (grub_efi_mm_init): Likewise. + (grub_efi_mm_fini): Removed. + +2010-10-16 Vladimir Serbinenko + + * grub-core/kern/efi/mm.c (BYTES_TO_PAGES): Round up instead of down. + (grub_efi_mm_init): Take into account the memory map size increase. + +2010-10-16 Vladimir Serbinenko + + * grub-core/term/ns8250.c (do_real_config): Set port->broken to 0. + (serial_hw_put): Wait based on real time rather than port reads. Don't + roken ports. + * include/grub/serial.h (grub_serial_port): New field broken. + +2010-10-16 Robert Millan + + * grub-core/kern/emu/misc.c + (grub_make_system_path_relative_to_its_root): Fix premature return + when processing non-root ZFS filesystems. + Reported by Sergio Talens-Oliag. + +2010-10-15 Robert Millan + + * util/grub.d/10_linux.in (list): Expand "vmlinu[zx]" instances to + guarantee compressed ones are processed first. + +2010-10-14 Vladimir Serbinenko + + * grub-core/efiemu/main.c (grub_efiemu_prepare): Handle errors from + grub_efiemu_autocore. + +2010-10-14 Vladimir Serbinenko + + * grub-core/kern/i386/pc/startup.S (bypass_table): Use 0x1b explicitly + rather than 0x1b. + (grub_console_getkey): Use correct jae opcode rather than ja. + +2010-10-12 Robert Millan + + * util/grub-mkconfig.in: Merge `GRUB_DISABLE_LINUX_RECOVERY' and + `GRUB_DISABLE_NETBSD_RECOVERY' into a single `GRUB_DISABLE_RECOVERY' + variable. All references updated. + + * util/grub.d/10_kfreebsd.in: Support recovery boot entries. + +2010-10-08 Vladimir Serbinenko + + Correctly distinguish mdraid flavours. + + * grub-core/disk/raid.c (grub_raid_getname) [GRUB_UTIL]: New function. + (insert_array): New argument raid. + * include/grub/disk.h (grub_disk_dev) [GRUB_UTIL]: New member raidname. + * include/grub/raid.h (grub_raid_array) [GRUB_UTIL]: New member driver. + * util/grub-probe.c (probe): PRint raidname instead of plainly "mdraid". + +2010-10-09 Vladimir Serbinenko + + * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Fix incorrect + handling of special keys. + +2010-10-02 Aleš Nesrsta + + * include/grub/scsi.h (grub_make_scsi_id): Fix incorrect usgae of + GRUB_SCSI_ID_BUS_SHIFT instead of GRUB_SCSI_ID_LUN_SHIFT. + +2010-10-02 Aleš Nesrsta + + * grub-core/bus/usb/ohci.c (GRUB_OHCI_TDS): Increase. + * grub-core/bus/usb/uhci.c (N_TD): New definition. All previous implicit + users updated. + * grub-core/bus/usb/usbtrans.c (grub_usb_bulk_setup_readwrite): + Use right endpoint when querying descriptor. + +2010-10-01 Vladimir Serbinenko + + Clear out 0x80 color bit on EFI. + Tested by: decoder + Reported by: decoder and meta tech. + + * grub-core/term/efi/console.c (grub_console_standard_color): Removed. + (grub_console_setcolorstate): Clear out 0x80 bit. + Use GRUB_TERM_DEFAULT_STANDARD_COLOR. + (grub_console_output): Use GRUB_TERM_DEFAULT_NORMAL_COLOR. + Use GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR. + +2010-10-01 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (DEFAULT_VIDEO_MODE) [GRUB_MACHINE_EFI]: + Set to "auto". + +2010-09-30 Vladimir Serbinenko + + * grub-core/gettext/gettext.c (grub_gettext_init_ext): Avoid using + mo_file after freeing. + +2010-09-30 Vladimir Serbinenko + + * grub-core/normal/term.c (read_terminal_list): Free in a right order. + +2010-09-30 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_execute_sourcecode): Set + flags. + +2010-09-30 Vladimir Serbinenko + + * util/grub-setup.c (main) [GRUB_MACHINE_IEEE1275]: Propagate argp + usage. + +2010-09-30 Vladimir Serbinenko + + Put terminfo into core on ieee1275 and yeeloong (needed for console). + + * gentpl.py: New groups terminfoinkernel and terminfomodule. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Include extcmd.h, arg.h + and terminfo.h when needed. + * grub-core/Makefile.core.def (kernel): Include term/terminfo.c, + term/tparm.c, commands/extcmd.c, lib/arg.c on terminfokernel. + (terminfo): Enable only on terminfokernel. + (extcmd): Likewise. + * include/grub/extcmd.h: Add missing EXPORT_FUNC. + * include/grub/lib/arg.h: Likewise. + * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_dimensions): Fix + incorrect usage of ->. + +2010-09-29 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_make_mbi] + [GRUB_MACHINE_EFI && __i386__]: Fix typo. + +2010-09-29 Vladimir Serbinenko + + Fix coreboot compilation. + + * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): + Take VBE info into account even if only text is supported. + (fill_vbe_info): Take into account the case when only VGA text + is supported. + * include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): Set to zero + on coreboot, multiboot and qemu. + +2010-09-29 Vladimir Serbinenko + + * grub-core/lib/relocator.c (malloc_in_range): Trim too verbose + debug messages. + (grub_relocator_prepare_relocs): Set movers_chunk.srcv. + +2010-09-29 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_cmd_netbsd): Provide default serial + parameters. + +2010-09-29 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_parse): Fix treating of all commands as + if they were BSD-style. + +2010-09-29 Vladimir Serbinenko + + * grub-core/boot/i386/pc/lnxboot.S: Replace + GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE with + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART. + +2010-09-29 Vladimir Serbinenko + + Write embedding zone using Reed-Solomon. + + * Makefile.util.def (grub-setup): Add grub-core/lib/reed_solomon.c. + * grub-core/Makefile.am (rs_decoder.S): New target. + (kern/i386/pc/startup.S): Depend on rs_decoder.S. + * grub-core/kern/i386/pc/startup.S (reed_solomon_redundancy): New field. + (multiboot): Move to RS part. + (post_reed_solomon): New label. + (grub_boot_drive): Move to non-RS part since it's modified in memory + on boot. + Include rs_decoder.S. + * grub-core/lib/reed_solomon.c: New file. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): + New definition. + (GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE): Removed. + (GRUB_KERNEL_I386_PC_RAW_SIZE): Updated. + (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): New definition. + * include/grub/partition.h (grub_partition_map): Change prototype of + embed to allow returning additional sectors. + * include/grub/reed_solomon.h: New file. + * util/grub-setup.c (setup): Handle Reed-Solomon. + +2010-09-28 Colin Watson + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_make_mbi): Fix + i386 and x86-64 definedness tests. + +2010-09-27 Yves Blusseau + + Fix generation of kernel_syms.lst + + * grub-core/Makefile.am (kernel_syms.lst): Fix value and position of + ASM_PREFIX + +2010-09-26 Robert Millan + + Support degraded ZFS arrays in "grub-probe -t device" resolution. + + * grub-core/kern/emu/getroot.c (find_root_device_from_libzfs): When + the pool is an array of devices, iterate through it and return the + first device that passes a stat() test (instead of blindly returning + the first one). + +2010-09-26 Robert Millan + + Build fixes for GNU/kFreeBSD. + + * Makefile.util.def: Add `$(LIBZFS) $(LIBNVPAIR)' library dependencies + to programs that require ZFS conversion. + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Support + kernels that don't have FLOPPY_MAJOR. + +2010-09-25 BVK Chaitanya + + * grub-core/kern/emu/full.c (grub_emu_post_init): Fix typo. + +2010-09-25 BVK Chaitanya + + Fix grub-emu build. + + * grub-core/kern/emu/main.c: Remove #include . + * grub-core/kern/emu/full.c: Split grub_mdraid_{init,fini} into + mdraid09 and mdraid1x. + +2010-09-24 Colin Watson + + Re-enable grub-extras. + + * autogen.sh: Create symlinks to ${GRUB_CONTRIB} if necessary to + avoid confusing Automake. Run autogen only twice, once for the top + level and once for grub-core. Add Makefile.util.def and + Makefile.core.def from extra modules to the appropriate autogen + invocations. If Makefile.common exists in an extra module, include + it in both Makefile.util.am and grub-core/Makefile.core.am; + similarly, include any Makefile.util.common file in Makefile.util.am + and any Makefile.core.common file in grub-core/Makefile.core.am. + * conf/Makefile.common ($(top_srcdir)/grub-core/Makefile.core.am): + Depend on $(top_srcdir)/grub-core/Makefile.gcry.def. + ($(top_srcdir)/grub-core/Makefile.gcry.def): Remove. + * grub-core/Makefile.am: Remove inclusion of Makefile.gcry.am. + + * gentpl.py (gvar_add): Turn GVARS into a set. + (global_variable_initializers): Sort global variables on output. + (vars_init): New function. + (first_time): Likewise. + (library): Ensure that non-global variable initialisations are + emitted before the first time we emit code for a library block. + Append to variables rather than setting them. Only emit + noinst_LIBRARIES, BUILT_SOURCES, and CLEANFILES the first time for + each conditional path. + (program): installdir() emits an Autogen macro, so must be passed to + var_add rather than gvar_add. + (data): Likewise. + (script): Likewise. + (rules): New function, centralising handling for different target + types. Set up Guile association lists for first_time and vars_init, + and send most output to a diversion so that variable initialisations + can be emitted first. + (module_rules): Use new rules function. + (kernel_rules): Likewise. + (image_rules): Likewise. + (library_rules): Likewise. + (program_rules): Likewise. + (script_rules): Likewise. + (data_rules): Likewise. + + * configure.ac: Add AC_PROG_LN_S, for the benefit of ntldr-img. + + * .bzrignore: Add contrib and grub-core/contrib. Remove + grub-core/Makefile.gcry.am. + +2010-09-24 Yves Blusseau + + * grub-core/lib/LzFind.c: Add missing include. + * grub-core/lib/LzmaEnc.c: Likewise. + * grub-core/script/lexer.c: Likewise. + * grub-core/script/yylex.l: Likewise. + * util/grub-macho2img.c: Likewise. + * util/grub-menulst2cfg.c: Likewise. + * util/grub-mklayout.c: Likewise. + * util/grub-mkpasswd-pbkdf2.c + * util/grub-mkrelpath.c: Likewise. + * util/resolve.c: Likewise. + +2010-09-24 BVK Chaitanya + + * Makefile.util.def (example_unit_test): Add + grub-core/gnulib/libgnu.a. + +2010-09-23 Grégoire Sutre + + * grub-core/commands/acpihalt.c (get_sleep_type): Initialize prev. + +2010-09-23 Vladimir Serbinenko + + Support xz compression on yeeloong. + + * Makefile.util.def (grub-mkimage): Add $(LIBLZMA). + * configure.ac: Check for LZMA. + * grub-core/Makefile.core.def (xz_decompress): New target. + (none_decompress): Likewise. + * grub-core/boot/decompressor/minilib.c: New file. + * grub-core/boot/decompressor/none.c: Likewise. + * grub-core/boot/decompressor/xz.c: Likewise. + * grub-core/kern/mips/cache.S: Change to noreorder nomacro. + * grub-core/kern/mips/cache_flush.S: Likewise. + * grub-core/kern/i386/pc/lzma_decode.S: Remove dead code. + * grub-core/kern/mips/startup.S: Move first stage to ... + * grub-core/boot/mips/startup_raw.S: ...here. Change to noreorder + nomacro. + * grub-core/kern/mips/startup.S: Change to noreorder nomacro. + * grub-core/lib/mips/relocator_asm.S: Change to noreorder nomacro. + * grub-core/lib/xzembed/xz_dec_bcj.c [GRUB_EMBED_DECOMPRESSOR]: + Allocate statically. + * grub-core/lib/xzembed/xz_dec_lzma2.c [GRUB_EMBED_DECOMPRESSOR]: + Allocate statically or use scratch. Don't check CRC32. + * grub-core/lib/xzembed/xz_dec_stream.c [GRUB_EMBED_DECOMPRESSOR]: + Allocate statically. Don't check CRC32. + * include/grub/decompressor.h: New file. + * include/grub/offsets.h (GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE): + Removed. + (GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE): New field. + (GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE): Adjusted. + (GRUB_KERNEL_MIPS_YEELOONG_PREFIX): Likewise. + (GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END): Likewise. + (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE): New define. + * util/grub-mkimage.c (grub_compression_t): New type. + (PLATFORM_FLAGS_DECOMPRESSORS): New flag. + (image_target_desc): New field default_compression. + (image_targets): Adjust yeeloong targets. + (compress_kernel_xz) [HAVE_LIBLZMA]: New function. + (compress_kernel): New parameter comp. + (generate_image): Likewise. Handle new compression case. + (options): New option --compression + (help): Likewise. + (main): Handle new option. + +2010-09-22 Grégoire Sutre + + * grub-core/kern/emu/hostdisk.c [__NetBSD__]: Define FLOPPY_MAJOR. + +2010-09-22 Colin Watson + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_make_mbi): Fix + typo in __i386__ conditional. + +2010-09-22 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c (GRUB_MACHINE_EFI): Add missing + include. + +2010-09-22 Vladimir Serbinenko + + Implement EFI and ACPI multiboot2 extensions. + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare + new tags as supported. + (acpiv2_size): New function. + (grub_multiboot_get_mbi_size): Take new tags into account. + (grub_multiboot_make_mbi): Add new tags. + * include/grub/multiboot.h (GRUB_MACHINE_HAS_ACPI): New definition. + +2010-09-21 Aleš Nesrsta + + * grub-core/bus/usb/serial/common.c (grub_usbserial_attach): + Added missing configuration of USB device. + +2010-09-21 Colin Watson + + * grub-core/normal/menu_entry.c (run): Make sure we always return + a value. + +2010-09-21 Colin Watson + + * grub-core/commands/efi/lsefimmap.c (grub_cmd_lsefimmap): + NumberOfPages is UINT64 according to the UEFI specification, not + UINTN. Fix printf format. + +2010-09-21 Colin Watson + + * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Change type of + `err' to grub_usb_err_t. + Reported and tested by: KESHAV P.R. + +2010-09-21 Colin Watson + + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Make + tpart non-const, so that we can assign to it. (Since this is a + typedef, the constness refers to the pointer rather than what it + points to.) + +2010-09-21 Colin Watson + + * conf/Makefile.common (CPPFLAGS_GNULIB): Add + $(top_srcdir)/grub-core/gnulib as well as + $(top_builddir)/grub-core/gnulib. + Reported by: KESHAV P.R. + +2010-09-21 Colin Watson + + * util/grub-install.in: Fix the bootloader ID option to be + consistently --bootloader-id, not --bootloader_id. + Reported by: KESHAV P.R. + +2010-09-21 Colin Watson + + * grub-core/commands/hashsum.c (GRUB_MOD_INIT): Make "Compute or + check hash checksum." consistently translatable. + +2010-09-21 Yves Blusseau + + * conf/Makefile.common (CPPFLAGS_GNULIB): Replace $(top_srcdir) with + $(top_builddir). + +2010-09-21 Colin Watson + + * grub-core/commands/hashsum.c (aliases): Add sha1sum alias. + (GRUB_MOD_INIT): Register sha1sum command. + (GRUB_MOD_FINI): Unregister sha1sum command. + +2010-09-21 Yves Blusseau + + Keep boot and grub directory names in sync with utils scripts + + * configure.ac: Define GRUB_BOOT_DIR_NAME and GRUB_DIR_NAME macros. + * config.h.in: Add previous macros. + * include/grub/emu/misc.h (DEFAULT_DIRECTORY): Use previous macros. + * util/grub-install.in: Use $bootdir and $grubdir variables. + +2010-09-21 Colin Watson + + * grub-core/kern/emu/hostdisk.c (find_system_device): Only try to + convert partition names to disk names if the new `convert' parameter + is set. + (grub_util_biosdisk_get_grub_dev): If opening the disk device + returns GRUB_ERR_UNKNOWN_DEVICE, treat the partition device as a + disk in its own right. This can happen with Xen disk images. + +2010-09-21 Yves Blusseau + + * util/grub-editenv.c: Update strings to avoid warnings when generating + grub.pot file. + * util/grub-setup.c: Likewise. + +2010-09-21 Vladimir Serbinenko + + * configure.ac: Change version to 1.99~beta0. + +2010-09-21 Vladimir Serbinenko + + * grub-core/loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap): + Add BADRAM. + * grub-core/loader/multiboot_mbi2.c (grub_fill_multiboot_mmap): + Likewise. + * include/multiboot.h: Resynced with specification. + * include/multiboot2.h: Likewise. + +2010-09-21 Colin Watson + + Fix po directory handling. + + * configure.ac: Create po/Makefile.in rather than po/Makefile. + * grub-core/gnulib/Makefile.am: Import gettext module. + * m4/gnulib-cache.m4: Likewise. + * m4/gnulib-comp.m4: Likewise. + * m4/gettext.m4: New file, from gnulib. + * m4/glibc2.m4: Likewise. + * m4/iconv.m4: Likewise. + * m4/intdiv0.m4: Likewise. + * m4/intl.m4: Likewise. + * m4/intldir.m4: Likewise. + * m4/intlmacosx.m4: Likewise. + * m4/intmax.m4: Likewise. + * m4/inttypes-pri.m4: Likewise. + * m4/lcmessage.m4: Likewise. + * m4/lib-ld.m4: Likewise. + * m4/lib-link.m4: Likewise. + * m4/lib-prefix.m4: Likewise. + * m4/lock.m4: Likewise. + * m4/nls.m4: Likewise. + * m4/po.m4: Likewise. + * m4/printf-posix.m4: Likewise. + * m4/progtest.m4: Likewise. + * m4/threadlib.m4: Likewise. + * m4/uintmax_t.m4: Likewise. + * m4/visibility.m4: Likewise. + * po/Makefile.am: Remove. + * po/Makefile.in.in: New file, from gettext. + ($(DOMAIN).pot-update): Support POTFILES-shell. + * po/Makevars: New file. + * po/POTFILES-shell: Rename to ... + * po/POTFILES-shell.in: ... this. Update. + * po/POTFILES: Rename to ... + * po/POTFILES.in: ... this. Update. + * po/Rules-quot: New file, from gettext. + * po/boldquot.sed: Likewise. + * po/en@boldquot.header: Likewise. + * po/en@quot.header: Likewise. + * po/insert-header.sin: Likewise. + * po/quot.sed: Likewise. + * po/remove-potcdate.sin: Likewise. + +2010-09-20 Vladimir Serbinenko + + * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Use UUID when possible. + +2010-09-20 Vladimir Serbinenko + + * util/grub.d/20_linux_xen.in: Use submenus. + +2010-09-20 Vladimir Serbinenko + + Support submenus. + + * grub-core/commands/menuentry.c (grub_normal_add_menu_entry): New + parameter submenu. All users updated. + * grub-core/normal/main.c (free_menu): Rename to ... + (grub_normal_free_menu): ... this. Made global. + * grub-core/normal/menu.c (grub_menu_execute_entry): Open new context + if requested. + * grub-core/normal/menu_entry.c (screen): New field submenu. + (make_screen): Set submenu. + (run): Open new context if requested. + * include/grub/menu.h (grub_menu_entry): New field submenu. + * include/grub/normal.h (grub_normal_free_menu): New proto. + +2010-09-20 Vladimir Serbinenko + + Menu entries extractor. + + * grub-core/commands/configfile.c (grub_cmd_source): Implement extractor + variants. + (GRUB_MOD_INIT): Register new variants. + (GRUB_MOD_FINI): Unregister new variants. + * grub-core/commands/legacycfg.c (grub_cmd_legacy_configfile): Merge + into grub_cmd_legacy_source. + (grub_cmd_legacy_source): Implement extractor variants. + (GRUB_MOD_INIT): Register new variants. + (GRUB_MOD_FINI): Unregister new variants. + * grub-core/commands/menuentry.c (grub_menu_init): Declare menuentry + as an extractor. + * grub-core/commands/search_wrap.c (GRUB_MOD_INIT): Declare + search as an extractor. + * grub-core/commands/test.c (GRUB_MOD_INIT): Declare + test as an extractor. + * grub-core/kern/corecmd.c (grub_register_core_commands): Declare set + as an extractor. + * grub-core/normal/context.c (grub_env_context_open): Reorganised. + (grub_env_new_context): New function. + (grub_env_context_open): Likewise. + (grub_env_extractor_open): Likewise. + (grub_env_extractor_close): Likewise. + * grub-core/script/execute.c (grub_script_execute_cmdline): Handle + grub_extractor_level. + * include/grub/command.h (GRUB_COMMAND_FLAG_EXTRACTOR): New flag. + * include/grub/env.h (grub_env_extractor_open): New proto. + (grub_env_extractor_close): Likewise. + * include/grub/normal.h (grub_extractor_level): New external variable. + +2010-09-20 Vladimir Serbinenko + + Make cutmem accept a region specification. + Suggested by: Samuel Thibault + + * grub-core/mmap/mmap.c (parsemem): New function. + (grub_cmd_cutmem): Handle new arguments. + +2010-09-20 Vladimir Serbinenko + + New command cutmem. + + * grub-core/mmap/mmap.c (grub_cmd_cutmem): New function. + (GRUB_MOD_INIT): Register new command. + (GRUB_MOD_FINI): Unregister new command. + +2010-09-20 Vladimir Serbinenko + + Support some annoying BSD and Minix subpartitions. + + * Makefile.util.def (libgrub.a): Add grub-core/partmap/bsdlabel.c. + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): + Properly handle concatenation. + * grub-core/kern/device.c (grub_device_iterate): Likewise. + * grub-core/normal/completion.c (iterate_partition): Likewise. + * grub-core/kern/disk.c (grub_disk_open): Make disk->name not + contain partition. All users updated. + * grub-core/partmap/bsdlabel.c (grub_netbsdlabel_partition_map): New + struct. + (grub_openbsdlabel_partition_map): Likewise. + (bsdlabel_partition_map_iterate): Rename to .. + (iterate_real): ... this. New arguments sector, freebsd and pmap. + (bsdlabel_partition_map_iterate): New function. + (netopenbsdlabel_partition_map_iterate): Likewise. + (netbsdlabel_partition_map_iterate): Likewise. + (openbsdlabel_partition_map_iterate): Likewise. + (GRUB_MOD_INIT): Register new partmaps. + (GRUB_MOD_FINI): Unregister new partmaps. + * grub-core/partmap/msdos.c (pc_partition_map_iterate): Rename to ... + (grub_partition_msdos_iterate): ... this. All users updated. + Don't support embedding other than in a minix partition. + * include/grub/msdos_partition.h (grub_partition_msdos_iterate): New + proto. + * include/grub/partition.h (grub_partition): New field msdostype. + * util/grub-install.in: Handle openbsd and netbsd types being in + part_bsd module. + +2010-09-20 Vladimir Serbinenko + + Split mdraid.mod into mdraid09.mod and mdraid1x.mod. + + * Makefile.util.def (libgrub.a): Add grub-core/disk/mdraid1x_linux.c. + * grub-core/Makefile.core.def (mdraid): Renamed to ... + (mdraid09): ... this. + (mdraid1x): New module. + * grub-core/disk/mdraid_linux.c: Move 1.x parts ... + * grub-core/disk/mdraid1x_linux.c: ...here. All users updated. + +2010-09-20 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c (asprintf): Use vsnprintf instead of + vsprintf. + +2010-09-20 Colin Watson + + * grub-core/commands/efi/lsefimmap.c: Correct header. + * NEWS: Update. + +2010-09-20 Colin Watson + + * util/grub-editenv.c (argp_parser): Don't pass translated strings + as printf format strings; the translations might contain '%' which + could cause a crash. + (main): Likewise. + * util/grub-fstest.c (argp_parser): Likewise. + * util/grub-setup.c (argp_parser): Likewise. + (main): Likewise. + +2010-09-20 Vladimir Serbinenko + + Use argp in grub-fstest. + + * util/grub-fstest.c: Don't include getopt.h. + Include argp.h. + (root): New variable. + (args_count): Likewise. + (nparm): Likewise. + (num_disks): Likewise. + (images): Likewise. + (cmd): Likewise. + (debug_str): Likewise. + (args): Likewise. + (options): Transformed to argp. + (usage): Removed. + (main): Split argument parsing into ... + (argp_parser): ... this. Changed to argp format. + (argp): New variable. + (main): Use argp_parse. + +2010-09-20 Tristan Gingold +2010-09-20 Robert Millan +2010-09-20 Vladimir Serbinenko + + * grub-core/commands/efi/lsefimmap.c: New file. + * grub-core/Makefile.core.def (lsefimmap): New module. + * include/grub/efi/api.h (PRIxGRUB_EFI_UINTN_T): New definition. + +2010-09-20 Vladimir Serbinenko + + Pause the execution (10s max) if any errors are displayed so the user + has a chance to see them. + + * grub-core/kern/err.c (grub_err_printed_errors): New variable. + (grub_print_error): Increment grub_err_printed_errors. + * grub-core/normal/menu.c (grub_menu_execute_entry): Pause the + execution if any errors were displayed. + (show_menu): Remove old code for pause. + * grub-core/normal/menu_entry.c (run): Likewise. + * grub-core/normal/term.c (grub_normal_char_counter): Removed. All + users updated. + (grub_normal_get_char_counter): Likewise. + * include/grub/err.h (grub_err_printed_errors): New external variable. + * include/grub/normal.h (grub_normal_get_char_counter): Removed. + +2010-09-20 Vladimir Serbinenko + + Support multiboot VBE info. + + * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): + Take VBE info into account. + (fill_vbe_info) [GRUB_MACHINE_HAS_VBE]: New function. + (retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]: + Call fill_vbe_info when appropriate. + (grub_multiboot_make_mbi): Account for the size occupied by VBE info. + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare tags + as supported. + (grub_multiboot_get_mbi_size): Take new tags into account. + (fill_vbe_tag) [GRUB_MACHINE_HAS_VBE]: New function. + (retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]: + Call fill_vbe_tag when appropriate. + (grub_multiboot_make_mbi): Properly align tags. + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_pm_interface): New + function. + * include/grub/i386/pc/vbe.h (grub_vbe_bios_get_pm_interface): New + proto. + * include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): New definition. + +2010-09-20 Vladimir Serbinenko + + Suport manual terminal geometry specification. + + * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_dimensions): + Save state in grub_ofconsole_terminfo_output. + (grub_ofconsole_term): Use grub_terminfo_getwh. + (grub_ofconsole_getwh): Removed. + * grub-core/term/serial.c (grub_serial_getwh): Removed. + (grub_serial_term): Use grub_terminfo_getwh. + * grub-core/term/terminfo.c (grub_terminfo_getwh): New function. + (options): New struct. + (OPTION_*): New enum. + (grub_cmd_terminfo): Transform into extcmd and handle new parameters. + * include/grub/terminfo.h (grub_terminfo_output_state): New fields + width and height. + (grub_terminfo_getwh): New proto. + * grub-core/lib/legacy_parse.c (grub_legacy_parse): Handle --lines. + +2010-09-20 Vladimir Serbinenko + + Handle legacy "terminal" command. + + * grub-core/lib/legacy_parse.c (legacy_command): New flags FLAG_TITLE + and FLAG_TERMINAL. + (legacy_commands): Add terminal and title. + (grub_legacy_parse): Handle terminal. Simplify title handling. + +2010-09-20 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_show_help): Correctly handle + parameters overflow. + +2010-09-20 Colin Watson + + * .bzrignore: Add grub-core/gnulib/sys, widthspec.bin, and + widthspec.h. + + * docs/grub.texi (Shell-like scripting): Document `!'. + (Network): Simplify using new i386-pc-pxe format. Mention + grub-mknetdir. + + * NEWS: Update. + +2010-09-20 Colin Watson + + * Makefile.am (SUBDIRS): Restore "."; it's important to force + ordering, so that e.g. ascii.h is built before grub-core/font/font.c + when needed. + +2010-09-20 Colin Watson + + * grub-core/commands/efi/lsefisystab.c: Correct header. + * grub-core/commands/efi/lssal.c: Likewise. + * grub-core/commands/testload.c: Likewise. + +2010-09-20 Colin Watson + + * util/grub-mkrescue.in: Add explicit root argument to --set to + prevent the UUID being interpreted as an argument to --set (matches + previous change to prepare_grub_to_access_device). + +2010-09-20 Colin Watson + + * kern/emu/hostdisk.c: Include and + on FreeBSD. Define HAVE_DIOCGDINFO on NetBSD and FreeBSD to reduce + the verbosity of later #ifs. + (find_partition_start): Define this function on FreeBSD too. + (device_is_wholedisk) [__FreeBSD__ || __FreeBSD_kernel__]: New + function. + (grub_util_biosdisk_get_grub_dev): Use partition-start-sector logic + on FreeBSD. + +2010-09-20 Yves Blusseau + + * util/grub-editenv.c: Use argp instead of getopt. + +2010-09-20 Yves Blusseau + + * util/grub-setup.c: Use argp instead of getopt. + +2010-09-20 Yves Blusseau + + Use gnulib-tool to create gnulib source files. + + * Add gnulib files generated by gnulib-tool in build-aux, m4 and + grub-core/gnulib directories + * .bzignore: Add **/.deps and autogenerated gnulib files + * configure.ac: Assign auxiliary directory to build-aux, add invocation + of gnulib macros, add grub-core/gnulib/Makefile + * Makefile.am: Add gnulib directory in SUBDIRS (removing unnecessary .), + include m4 directory to aclocal. + * Makefile.util.def: Remove direct compilation of gnulib source files + and use the new grub-core/gnulib/libgnu.a. + * build-aux/config.rpath: move config.rpath from top directory to + build-aux + * conf/Makefile.common: Remove the macro _GL_UNUSED already defined + in gnulib headers + * conf/Makefile.extra-dist: Add m4/gnulib-cache.m4 + * grub-core/Makefile.core.def: Remove unnecessary extra_dist + * grub-core/lib/posix_wrap/localcharset.h (locale_charset): Update + header. + * grub-core/lib/posix_wrap/langinfo.h (nl_langinfo): Return static + string. + +2010-09-20 Yves Blusseau + + * .bzrignore: Add grub-kbdcomp, grub-menulst2cfg, *.marker, + grub-core/genmod.sh and grub-core/gensyminfo.sh + +2010-09-20 BVK Chaitanya + + Add a test for echo command options. + + * tests/grub_cmd_echo.in: New test. + * Makefile.util.def: Rules for new test. + +2010-09-20 Szymon Janc + + Remove crc.mod and move crc command to hashsum.mod. + Remove lib/crc.c - users updated to use gcrypt implementation. + + * grub-core/commands/crc.c: Removed. + * grub-core/Makefile.core.def (crc): Module removed. + * grub-core/commands/hashsum.c (aliases[]): Add crc alias. + * grub-core/commands/hashsum.c (GRUB_MOD_INIT): Register crc command. + * grub-core/commands/hashsum.c (GRUB_MOD_FINI): Unregister crc command. + * grub-core/lib/crc.c: Removed. + * include/grub/lib/crc.h: Removed. + * Makefile.util.def (crc): Remove lib/crc.c + * grub-core/Makefile.core.def (libgrub.a): Remove grub-core/lib/crc.c. + * util/grub-fstest.c (cmd_crd): Use libgcrypt crc implementation. + * Makefile.util.def (libgrub.a): Add grub-core/lib/libgcrypt-grub/cipher/crc.c. + * Makefile.util.def (grub-fstest): Add CFLAGS_GCRY to cflags. + * Makefile.util.def (grub-fstest): Add CPPFLAGS_GCRY to cppflags. + * grub-core/efiemu/prepare.c (grub_efiemu_crc): Use libgcrypt crc implementation. + +2010-09-20 Vladimir Serbinenko + + * grub-core/boot/i386/pc/boot.S: Ignore %dl if it's not in a sane range. + +2010-09-19 Vladimir Serbinenko + + Split config.h for util and core. + + * acinclude.m4 (HAVE_ASM_USCORE): Transformed into a variable. + (ADDR32): Likewise. + (DATA32): Likewise. + (BSS_START_SYMBOL): Likewise. + (END_SYMBOL): Likewise. + (NEED_ENABLE_EXECUTE_STACK): Likewise. All users updated. + (grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK): Removed. + * config.h.in: New file. + * configure.ac: Use config-util.h as config define file. + Rename MACHINE into GRUB_MACHINE. All users updated. + (NEED_REGISTER_FRAME_INFO): Transformed into a variable. All users + updated. + (NESTED_FUNC_ATTR): Likewise. + Substitue new variables. + (COND_HAVE_ASM_USCORE): New conditional. + * grub-core/Makefile.am (ASM_PREFIX): New variable. + (kernel_syms.lst): Use ASM_PREFIX. + * grub-core/kern/emu/console.c: Include config-util.h. + * grub-core/kern/emu/misc.c: Likewise. + * grub-core/kern/emu/mm.c: Likewise. + * include/grub/emu/misc.h: Likewise. + * include/grub/libgcc.h: Likewise. + +2010-09-19 Vladimir Serbinenko + + * grub-core/term/efi/console.c (efi_codes): Fix GRUB_TERM_KEY_* + constants usage. + * grub-core/kern/emu/console.c (grub_ncurses_getkey): + Fix GRUB_TERM_KEY_* constants usage. + * grub-core/kern/emu/misc.c (asprintf): Fix vasprintf usage. + +2010-09-19 Vladimir Serbinenko + + * grub-core/bus/usb/ohci.c (grub_ohci_cancel_transfer): Use %p to + print pointer. + * grub-core/bus/usb/uhci.c: Remove empty define. + (grub_uhci_check_transfer): Add missing cast. + * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Use %p to + print pointer. + * grub-core/term/usb_keyboard.c (grub_usb_keyboard_getkey): Use + PRIuGRUB_SIZE. + * include/grub/types.h (PRIuGRUB_SIZE): New definition. + +2010-09-19 Vladimir Serbinenko + + * grub-core/Makefile.core.def (legacycfg): Add + lib/i386/pc/vesa_modes_table.c on emu. + +2010-09-19 BVK Chaitanya + + Reduce number of temporary files generated by build system. + + * grub-core/gencmdlist.sh: Removed. + * grub-core/genfslist.sh: Removed. + * grub-core/genhandlerlist.sh: Removed. + * grub-core/genmodsrc.sh: Removed. + * grub-core/genpartmaplist.sh: Removed. + * grub-core/genparttoollist.sh: Removed. + * grub-core/gentermiinallist.sh: Removed. + * grub-core/genvideolist.sh: Removed. + + * grub-core/genmod.sh.in: New file. + * grub-core/gensyminfo.sh.in: New file. + + * conf/Makefile.common (CPPFLAGS_*_LIST): New marker flags. + * conf/Makefile.extra-dist: Update with new files. + * gentpl.py: Remove rules related to unnecessary temporary files. + * grub-core/Makefile.am (syminfo.lst): New replacement for def-* + and und-* files. + * grub-core/Makefile.core.def: New rules for gensyminfo.sh and + genmod.sh scripts. + * grub-core/bus/usb/uhci.c: Remove empty #define. + * grub-core/genmoddep.awk: Updated with new syminfo format. + * util/bash-completion.d/Makefile.am: Add config.log to + CLEANFILES. + +2010-09-19 Yves Blusseau + + * Makefile.util.def: Add forgotten $(LIBINTL) library. + +2010-09-19 BVK Chaitanya + + * util/grub-mkconfig.in: Check the config script for syntax errors + before saving. + +2010-09-19 Colin Watson +2010-09-19 Vladimir Serbinenko + + * Makefile.util.def (grub-install): Use util/grub-install.in on all + platforms. + * util/grub-install.in: Add EFI and IEEE1275 support. + * util/i386/efi/grub-install.in: Removed. + * util/ieee1275/grub-install.in: Likewise. + +2010-09-19 Vladimir Serbinenko + + * grub-core/commands/i386/cmostest.c (+parse_args): New function. + (grub_cmd_cmosclean): Likewise. + (GRUB_MOD_INIT): Register command cmosclean. + * util/grub-mkconfig.in: Export GRUB_BUTTON_CMOS_CLEAN. + * util/grub.d/00_header.in: Handle GRUB_BUTTON_CMOS_CLEAN. + +2010-09-18 Carles Pina i Estany +2010-09-18 Aleš Nesrsta +2010-09-18 Vladimir Serbinenko + + Add keyboard layouts support. + + * Makefile.util.def (grub-mklayout): New file. + (grub-kbdcomp): New script. + * grub-core/Makefile.am (KERNEL_HEADER_FILES) [COND_mips_yeeloong]: + Add keyboard_layouts.h. + * grub-core/Makefile.core.def (kernel): Add commands/keylayouts.c and + commands/boot.c on yeeloong. + (keylayouts): New module. + * grub-core/bus/usb/ohci.c + * grub-core/bus/usb/uhci.c + * grub-core/bus/usb/usbhub.c (rescan): New variable. + (grub_usb_add_hub): Poll interrupt pipe for device handling. + (attach_root_port): Likewise. + (poll_nonroot_hub): Likewise. + (grub_usb_poll_devices): Likewise. + (detach_device): Close transfer. + * grub-core/bus/usb/usbtrans.c (grub_usb_execute_and_wait_transfer): New + function. + (grub_usb_bulk_setup_readwrite): Likewise. + (grub_usb_bulk_finish_readwrite): Likewise. + * grub-core/commands/keylayouts.c: New file. + * grub-core/commands/keystatus.c (grub_getkeystatus): New function. + * grub-core/commands/menuentry.c (hotkey_aliases): All several new + aliases. + * grub-core/term/at_keyboard.c: Restructured to use keylayouts and + support scancode 2. + * grub-core/term/usb_keyboard.c: Restructured to use keylayouts. + * include/grub/keyboard_layouts.h: New file. + * util/grub-mklayout.c: New file. + * util/grub-kbdcomp.in: Likewise. + +2010-09-18 Vladimir Serbinenko + + Unify memory types. + + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Include memory.h. + * grub-core/commands/lsmmap.c (grub_cmd_lsmmap): Output user-readable + types. + * grub-core/kern/i386/multiboot_mmap.c (grub_lower_mem): Removed. + (grub_upper_mem): Likewise. + * grub-core/kern/ieee1275/init.c (grub_upper_mem): Likewise. + * include/grub/memory.h (grub_memory_type_t): New enum. + All users updated. + +2010-09-18 Vladimir Serbinenko + + * grub-core/Makefile.core.def (lsapm): New module. + * grub-core/commands/i386/pc/lsapm.c: New file. + * grub-core/loader/i386/multiboot_mbi.c (make_mbi) [GRUB_MACHINE_PCBIOS]: Pass APM info. + * grub-core/loader/multiboot_mbi2.c (make_mbi) [GRUB_MACHINE_PCBIOS]: + Likewise. + * include/grub/i386/pc/apm.h: New file. + * include/multiboot.h (multiboot_apm_info): New struct. + +2010-09-18 Vladimir Serbinenko + + GRUB-legacy configuration file support. + + * Makefile.util.def (grub-menulst2cfg): New util. + * docs/man/grub-menulst2cfg.h2m: New file. + * grub-core/Makefile.core.def (legacycfg): New module. + * grub-core/commands/legacycfg.c: New file. + * grub-core/commands/menuentry.c (append_menu_entry): Rename to ... + (grub_normal_add_menu_entry): ... this. + * grub-core/commands/password.c (grub_cmd_password): Split main part to ... + (grub_normal_set_password): ...this. + * grub-core/commands/videoinfo.c (grub_cmd_videoinfo): Support MODE. + * grub-core/loader/i386/linux.c (linux_vesafb_res): Move to .., + * grub-core/lib/i386/pc/vesa_modes_table.c: ... here. + * grub-core/lib/legacy_parse.c: New file. + * grub-core/normal/auth.c (grub_cmd_authenticate): New command. + * include/grub/i386/pc/vesa_modes_table.h: New file. + * include/grub/legacy_parse.h: Likewise. + * include/grub/normal.h (grub_normal_add_menu_entry): New proto. + * util/grub-menulst2cfg.c: New file. + +2010-09-17 Colin Watson + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Initialise node. + +2010-09-17 Colin Watson + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Fix devmapper memory pool + leak. + Reported and based on patch by: Modestas Vainius. + +2010-09-17 Colin Watson + + Fix DM-RAID probing with recent versions of device-mapper udev + rules. + + * grub-core/kern/emu/hostdisk.c (read_device_map): Don't + canonicalise device paths under /dev/mapper/. + (convert_system_partition_to_system_disk): Compare the + uncanonicalised path to /dev/mapper/ rather than the canonicalised + path, since device nodes under /dev/mapper/ are often symlinks. + +2010-09-17 Yves Blusseau + + * .bzrignore: *.d removed (old rule), add *.image and symlist.h. + +2010-09-16 Yves Blusseau + + * configure.ac: Avoid some annoying error messages if freetype-config + program is not found. + +2010-09-16 Colin Watson + + Support RAID on virtio devices, and others. + + * grub-core/kern/emu/getroot.c [__MINGW32__] (find_root_device): + Rename to ... + [__MINGW32__] (grub_find_device): ... this. + [! __MINGW32__ && ! __CYGWIN__] (find_root_device): Rename to ... + [! __MINGW32__ && ! __CYGWIN__] (grub_find_device): ... this. Use a + reasonable default if dir is NULL. + [! __MINGW32__ && __CYGWIN__] (find_cygwin_root_device): Rename to + ... + [! __MINGW32__ && __CYGWIN__] (grub_find_device): ... this. + (grub_guess_root_device): Update callers. + * include/grub/emu/getroot.h (grub_find_device): Add prototype. + + * util/raid.c (grub_util_getdiskname): Remove. + (grub_util_raid_getmembers): Use grub_find_device rather than + grub_util_getdiskname. + +2010-09-16 Colin Watson + + * docs/grub.texi (serial): Remove obsolete comment about GRUB + needing to be compiled with serial support. + (ls): Indicate that multiple files are accepted. + * grub-core/commands/ls.c (GRUB_MOD_INIT): Update help text to + indicate that multiple files are accepted. + +2010-09-16 Colin Watson + + * .bzrignore: Add *.1, *.8, grub-shell, grub-shell-tester, + libgrub_a_init.c, and util/bash-completion.d/grub. + +2010-09-15 Vladimir Serbinenko + + * util/grub-setup.c (setup): Fix incorrect container semantics. + +2010-09-15 Vladimir Serbinenko + + * grub-core/commands/parttool.c (grub_cmd_parttool): Fix a variable + misusage. + Reported by: J. Nick Terry + +2010-09-15 Vladimir Serbinenko + + Move embedding routines to partmap sources files. + + * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot) + [GRUB_UTIL]: New variable. + (gpt_partition_map_iterate): Set part.parent. + (gpt_partition_map_embed) [GRUB_UTIL]: New function. + (grub_gpt_partition_map) [GRUB_UTIL]: Set .embed. + * grub-core/partmap/msdos.c (pc_partition_map_embed) [GRUB_UTIL]: + New function. + (grub_msdos_partition_map) [GRUB_UTIL]: Set .embed. + * include/grub/partition.h (grub_embed_type_t) [GRUB_UTIL]: New type. + (grub_partition_map) [GRUB_UTIL]: New field embed. + * util/grub-setup.c (grub_gpt_partition_type_bios_boot): Removed. + (setup): Use ->embed. + +2010-09-15 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): New + function. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_floppy): New proto. + * util/grub-setup.c (setup): Use grub_util_biosdisk_is_floppy. + +2010-09-15 Yves Blusseau + + Add function to get completions from usage. + + * util/bash-completion.d/grub-completion.bash.in: Add function to get + completions from usage. Use LC_ALL=C to get options properly. + +2010-09-15 Vladimir Serbinenko + + * grub-core/gnulib/basename-lgpl.c: Imported. + * grub-core/gnulib/basename.c: Likewise. + * grub-core/gnulib/dirname-lgpl.c: Likewise. + * grub-core/gnulib/dirname.c: Likewise. + * grub-core/gnulib/dirname.h: Likewise. + * grub-core/gnulib/stripslash.c: Likewise. + +2010-09-15 Vladimir Serbinenko + + * grub-core/gnulib/error.c: Resynced. + * grub-core/gnulib/getopt.c: Likewise. + * grub-core/gnulib/getopt_int.h: Likewise. + * grub-core/gnulib/regex.h: Likewise. + * grub-core/gnulib/regex_internal.c: Likewise. + * grub-core/gnulib/regex_internal.h: Likewise. + +2010-09-15 Szymon Janc + + * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block + CRC calculations and validity checks. + * grub-core/lib/xzembed/xz_dec_stream.c (dec_index): Fix index CRC + calculations. + +2010-09-15 Szymon Janc + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_end): Fix memory leak. + +2010-09-14 Vladimir Serbinenko + + Fix incorrect echo options handling. + Reported by: Yves Blusseau. + + * include/grub/command.h (grub_command_flags_t): New flags + GRUB_COMMAND_ACCEPT_DASH and GRUB_COMMAND_OPTIONS_AT_START. + * grub-core/lib/arg.c (grub_arg_parse): Handle new flags. + * grub-core/commands/echo.c (GRUB_MOD_INIT): Use new flags. + +2010-09-14 Vladimir Serbinenko + + * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All + users updated. + (GRUB_COMMAND_FLAG_MENU): Likewise. + (GRUB_COMMAND_FLAG_BOTH): Likewise. + (GRUB_COMMAND_FLAG_TITLE): Removed. + (GRUB_COMMAND_FLAG_NO_ECHO): Likewise. + (GRUB_COMMAND_FLAG_EXTCMD): Moved into enum. + (GRUB_COMMAND_FLAG_DYNCMD): Likewise. + (GRUB_COMMAND_FLAG_BLOCKS): Likewise. + (grub_command_flags_t): New enum. All users updated. + +2010-09-14 Seth Goldberg + + Fix solaris compilation. + + * grub-core/Makefile.core.def (kernel): Include gnulib/error.c on emu. + (grub-emu): Add LIBZFS and LIBNVPAIR to ldadd. + (grub-emu-list): Likewise. + +2010-09-14 Vladimir Serbinenko + + Remove deprecated root command. + + * grub-core/commands/minicmd.c (grub_mini_cmd_root): Removed. All users + updated. + +2010-09-14 Vladimir Serbinenko + + * util/i386/pc/grub-setup.c: Merge this ... + * util/sparc64/ieee1275/grub-setup.c: ... and this ... + * util/grub-setup.c: ... into this. + * include/grub/sparc64/ieee1275/boot.h (grub_boot_blocklist) [ASM_FILE]: + New struct. + +2010-09-14 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext2_open): Use return error value when + possible. + +2010-09-14 Vladimir Serbinenko + + * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly + allocate p. + +2010-09-14 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add + explicit root argument to set to prevent UUID to be interpreted as + argument to set. + +2010-09-14 Vladimir Serbinenko + + * grub-core/kern/sparc64/ieee1275/crt0.S: Align stack. + +2010-09-14 Vladimir Serbinenko + + Don't export grub_gate_a20. + + * grub-core/kern/i386/pc/init.c: Remove leftovers. + * grub-core/kern/i386/pc/startup.S (FUNCTION(grub_gate_a20)): Rename + to ... + (grub_gate_a20): ... this. All users updated. + * include/grub/i386/pc/init.h: Removed. All users updated. + +2010-09-14 Vladimir Serbinenko + + Create euro.pf2 which supports most European languages. + + * Makefile.am (grubdata_DATA): Add euro.pf2. + (euro.pf2): New target. + (CLEANFILES): Add euro.pf2. + +2010-09-14 Vladimir Serbinenko + + * configure.ac: Disable emu-usb by default to prevent inadvertent + device takeover. + +2010-09-13 Vladimir Serbinenko + + Disable usbserial on grub-emu since our libusb code isn't good enough + yet. + + * grub-core/Makefile.core.def (usbserial_common): Disable on emu. + (usbserial_pl2303): Likewise. + (usbserial_ftdi): Likewise. + +2010-09-13 Vladimir Serbinenko + + * include/grub/disk.h (grub_disk): Remove has_partitions. + All users updated. + * disk/loopback.c (grub_loopback): Remove has_partitions. + All users updated. + (options): Remove partitions. All users updated. + * util/grub-fstest.c (fstest): Don't pass "-p" to loopback. + * util/i386/pc/grub-setup.c (setup): copy partition table only when + actual partition table is found. + +2010-09-13 Vladimir Serbinenko + + Remove readability checks (too many false negatives). + + * util/grub-install.in: Remove readability checks. + * util/grub-mkconfig.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Revert to old + way. + +2010-09-13 Vladimir Serbinenko + + Enable acpi shutdown on all ACPI platforms. + + * grub-core/Makefile.core.def (halt): Inlude commands/acpihalt.c + on coreboo, multiboot and EFI. + * grub-core/commands/acpihalt.c (get_sleep_type): Add missing casts. + (grub_acpi_halt): Likewise. + * grub-core/commands/i386/pc/halt.c (grub_halt): Call grub_acpi_halt. + (grub_cmd_halt): Don't call grub_acpi_halt directly. + * grub-core/lib/efi/halt.c (grub_halt): Call grub_acpi_halt. + * grub-core/lib/i386/halt.c (grub_halt) + [GRUB_MACHINE_COREBOOT || GRUB_MACHINE_MULTIBOOT]: Likewise. + +2010-09-13 Vladimir Serbinenko + + * grub-core/commands/iorw.c (grub_cmd_read): Declare buf in smallest + context. + +2010-09-13 Vladimir Serbinenko + + * grub-core/video/efi_gop.c: Fix over-80-chars line. + * grub-core/video/efi_uga.c: Likewise. + +2010-09-13 Vladimir Serbinenko + + Filter devaliases and never open same device twice. + + * grub-core/disk/ieee1275/ofdisk.c (last_devpath): New variable. + (last_ihandle): Likewise. + (ofdisk_hash_ent): New member shortest. + (ofdisk_hash_add): Add canonical path too. + (scan): New function. + (grub_ofdisk_iterate): Iterate over hashed entries. + (compute_dev_path): Don't add :0. + (grub_ofdisk_open): Don't really open the disk. + (grub_ofdisk_close): Avoid closing unrelated disk. + (grub_ofdisk_read): Implement reopen logic. + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_canonicalise_devname): + New function. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_canonicalise_devname): + New proto. + +2010-09-13 Vladimir Serbinenko + + Fix sparc64. + + * configure.ac (GRUB_KERNEL_MACHINE_LINK_ADDR): Removed. + * grub-core/Makefile.core.def (kernel): Make ldflags just use the + right address. Add sparc64_ieee1275_ldflags. + * grub-core/loader/sparc64/ieee1275/linux.c: Remove leftover include. + * util/grub-mkimagexx.c (locate_sections): Correct grub_host_to_target32 + to grub_host_to_target_addr + (load_image): Likewise. + +2010-09-13 Vladimir Serbinenko + + * grub-core/normal/completion.c (complete_file): Handle device + containing slash. + Fix based on patch by Doug Nazar. + +2010-09-13 Vladimir Serbinenko + + grub-mknetdir script. + + * Makefile.util.def (grub-mknetdir): New module. + * tests/util/grub-shell.in: Support boot=net + * util/grub-mknetdir.in: New file. + +2010-09-13 Vladimir Serbinenko + + videoinfo on non-vbe. + + * grub-core/Makefile.core.def (vbeinfo): Removed. + (vbetest): Removed. + (videoinfo): New module. + * grub-core/commands/i386/pc/vbeinfo.c: Removed. + * grub-core/commands/i386/pc/vbetest.c: Removed. + * grub-core/commands/videoinfo.c: New file. + * grub-core/commands/videotest.c (grub_cmd_videotest): Support mode + specification. + (grub_cmd_videotest) [GRUB_MACHINE_PCBIOS]: Load vbe.mod when invoked + as vbetest. + (GRUB_MOD_INIT) [GRUB_MACHINE_PCBIOS]: New command vbetest. + (GRUB_MOD_FINI) [GRUB_MACHINE_PCBIOS]: Unregister vbetest. + * grub-core/video/efi_gop.c (grub_video_gop_fill_mode_info): Fill + mode_number. New parameter mode. All users updated. + (grub_video_gop_iterate): New function. + (grub_video_efi_gop): New member iterate. + * grub-core/video/i386/pc/vbe.c (framebuffer): Removed leftover fields. + (grub_vbe_set_video_mode): Remove setting useless fields. + (vbe2videoinfo): New function. + (grub_video_vbe_iterate): Likewise. + (grub_video_vbe_setup): Use vbe2videoinfo. + (grub_video_vbe_print_adapter_specific_info): New function. + (grub_video_vbe_adapter): New fields iterate and + print_adapter_specific_info. + * include/grub/video.h (GRUB_VIDEO_MODE_*): Transform into enum. + All users updated. + (grub_video_mode_info): New field mode_number. + (grub_video_adapter): New fields iterate and + print_adapter_specific_info. + +2010-09-13 Tristan Gingold +2010-09-13 Robert Millan +2010-09-13 Vladimir Serbinenko + + * grub-core/commands/efi/lsefisystab.c: New file. + * grub-core/commands/efi/lssal.c: Likewise. + * grub-core/Makefile.core.def (lsacpi): New module. + (lsefisystab): Likewise. + * include/grub/efi/api.h (GRUB_EFI_SAL_TABLE_GUID): New definition. + (GRUB_EFI_HCDP_TABLE_GUID): Likewise. + (grub_efi_sal_system_table): New struct. + (grub_efi_sal_system_table_entrypoint_descriptor): Likewise. + (grub_efi_sal_system_table_memory_descriptor): Likewise. + (grub_efi_sal_system_table_platform_features): Likewise. + (grub_efi_sal_system_table_translation_register_descriptor): Likewise. + (grub_efi_sal_system_table_purge_translation_coherence): Likewise. + (grub_efi_sal_system_table_ap_wakeup): Likewise. + * include/grub/types.h (PRIuGRUB_UINT64_T): New definition. + +2010-09-13 Vladimir Serbinenko + + Support explicit user claim that a device is BIOS-visible. + + * grub-core/kern/emu/getroot.c (grub_util_get_dev_abstraction): + Return GRUB_DEV_ABSTRACTION_NONE if device is in device.map. + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Support mdX. + (find_system_device): New parameter add. All users updated. + (grub_util_biosdisk_is_present): New function. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_present): New + proto. + +2010-09-13 Vladimir Serbinenko + + Search hints support. + + * commands/search.c (FUNC_NAME): New arguments hints and nhints. + All users updated. + +2010-09-13 Yves Blusseau + + Bash completion script for util commands + + * Makefile.am: Add util/bash-completion.d directory + * configure.ac: Likewise. + * util/bash-completion.d/Makefile.am: New file. + * util/bash-completion.d/grub-completion.bash.in: Likewise. + +2010-09-12 Vladimir Serbinenko + + * grub-core/normal/term.c (put_glyphs_terminal): Correct sign. + (print_backlog): set backlog_ucs4 and backlog_glyphs. + Reported by: Yves Blusseau. + +2010-09-12 Vladimir Serbinenko + + * grub-core/normal/misc.c (grub_normal_print_device_info): Show + partition size and offset. + +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (make_regex): Escape brackets. + +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/ls.c (grub_cmd_ls): Accept multiple files. + +2010-09-12 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vprintf): Use va_copy when necessary. + (grub_xvasprintf): Likewise. + +2010-09-12 Vladimir Serbinenko + + * grub-core/kern/emu/main.c (main): Call hostfs_init only after init_all. + +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/menuentry.c (append_menu_entry): Don't rely on + args ending with NULL. + +2010-09-12 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_reset): Preserve context + pointer. + +2010-09-11 Szymon Janc + + * grub-core/commands/lsacpi.c (grub_cmd_lsacpi): Fix prototype. + +2010-09-11 Vladimir Serbinenko + + Shutdown using ACPI. + + * grub-core/Makefile.core.def (halt): Add commands/acpihalt.c on i386-pc. + * grub-core/commands/acpihalt.c: New file. + * grub-core/commands/i386/pc/halt.c (grub_cmd_halt): Call grub_acpi_halt. + * include/grub/acpi.h (grub_acpi_fadt): New member pm1a. + (grub_acpi_halt): New proto. + (GRUB_ACPI_SLP_EN): New const. + (GRUB_ACPI_SLP_TYP_OFFSET): Likewise. + (GRUB_ACPI_OPCODE_*): New enum. + (GRUB_ACPI_EXTOPCODE_*): Likewise. + +2010-09-11 Tristan Gingold +2010-09-11 Robert Millan +2010-09-11 Vladimir Serbinenko + + * commands/lsacpi.c: New file. + * grub-core/Makefile.core.def (lsacpi): New module. + * include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition. + (GRUB_ACPI_MADT_SIGNATURE): Likewise. + (grub_acpi_madt_entry_header): New struct. + (grub_acpi_madt): Likewise. + (grub_acpi_madt_entry_interrupt_override): Likewise. + (grub_acpi_madt_entry_sapic): Likewise. + (grub_acpi_madt_entry_lsapic): Likewise. + (grub_acpi_madt_entry_platform_int_source): Likewise. + * include/grub/types.h (PRIxGRUB_UINT32_T): New definition. + (PRIuGRUB_UINT32_T): Likewise. + (PRIxGRUB_UINT64_T): Likewise. + +2010-09-11 Vladimir Serbinenko + + Implement loading palette on ieee1275_fb. + + * grub-core/video/ieee1275.c (stdout_ihandle): New variable. + (have_setcolors): Likewise. + (grub_video_ieee1275_init): Fill stdout_ihandle and have_setcolors. + (grub_video_ieee1275_setup): Use grub_video_ieee1275_set_palette. + (grub_video_ieee1275_set_palette): Implement. + +2010-09-11 Vladimir Serbinenko +2010-09-11 Colin Watson + + * util/grub-install.in (grub_partition): New variable. + Set prefix_drive on EFI and PC to (,$grub_partition) as last resort. + * util/i386/pc/grub-setup.c (setup): Don't touch prefix. + Fixes a bug reported by Yves Blusseau. + +2010-09-11 Vladimir Serbinenko + + Fix emu on mipsel. + + * conf/Makefile.common (CFLAGS_PLATFORM): Add -mflush-func + =grub_cpu_flush_cache on all mips and not only yeeloong. + * configure.ac (COND_mips): New conditional. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add libgcc on all + platforms. + * grub-core/kern/emu/cache.S (__mips__): Use _flush_cache. + * grub-core/kern/emu/full.c (grub_arch_dl_init_linker) + [GRUB_LINKER_HAVE_INIT]: New function. + (grub_emu_post_init): Likewise. + * grub-core/kern/emu/lite.c (grub_emu_post_init): Likewise. + * grub-core/kern/emu/main.c: Use grub_emu_post_init. + * include/grub/cache.h (_mips): Include mips/cache.h. + * include/grub/disk.h [GRUB_UTIL || GRUB_MACHINE_EMU]: Add missing + LVM and RAID prototypes. + * include/grub/emu/misc.h (grub_emu_post_init): New proto. + * include/grub/mips/time.h (grub_cpu_idle) [GRUB_MACHINE_EMU]: New + function. + +2010-09-10 Colin Watson + + * util/grub-install.in: Don't try to verify core.img until after + running grub-mkimage to create it. + +2010-09-10 Robert Millan + + * util/grub.d/10_hurd.in: Add misc readability checks. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + +2010-09-10 Colin Watson + + * util/grub-install.in: ${imgext} won't be defined here until the + install branch is merged. For the meantime, only verify core.img on + i386-pc and sparc64-ieee1275 platforms. + +2010-09-10 Robert Millan + + Solaris support in grub_find_zpool_from_dir(). Thanks + Seth Goldberg for referring to getextmntent() facility. + + * configure.ac: Check for getextmntent(), `sys/mnttab.h' and + `sys/mkdev.h'. + * grub-core/kern/emu/misc.c [HAVE_SYS_MNTTAB_H]: Include + `'. + [HAVE_SYS_MKDEV_H]: Include `'. + [HAVE_GETEXTMNTENT] (grub_find_zpool_from_dir): Add getextmntent() + method for finding zpool name. + +2010-09-10 Colin Watson + + grub-fstest needs the host and hostfs modules while other utilities + actively require those modules to be absent, so grub-fstest needs + its own initialisation and finalisation code. + + * Makefile.am (grub_fstest.pp): New target. + (grub_fstest_init.lst): Likewise. + (grub_fstest_init.c): Likewise. + * Makefile.util.def (grub-fstest): Add grub_fstest_init.c. + +2010-09-10 Robert Millan + + * configure.ac: Check for `struct statfs.f_fstypename' and + `struct statfs.f_mntfromname'. + + * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Conditionalize + kFreeBSD-specific code. + +2010-09-10 Robert Millan + + * util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization + on ZFS. Now non-main filesystems are supported as / too. + +2010-09-09 Colin Watson + + * Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c + and grub-core/disk/host.c to ... + (grub-fstest): ... here. Having the host disk implementation + present confuses grub-probe and other utility programs. + + * util/grub-mkconfig.in: Only verify readability of grub.cfg.new + when writing to a file, not when writing to stdout. + +2010-09-09 BVK Chaitanya + + * tests/partmap_test.in: New test for partitions. + * Makefile.util.def: Rules for new test. + +2010-09-09 Robert Millan + + * util/grub-probe.c (probe): Fix a pair of unhandled error + conditions. + +2010-09-09 Robert Millan + + Basic Btrfs support (detection and UUID). + + * grub-core/fs/btrfs.c: New file. + * Makefile.util.def (library): Register btrfs.c. + * grub-core/Makefile.core.def: Likewise. + +2010-09-08 Robert Millan + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve + with (optional) parameters to specify device and relative path. + * util/grub-install.in: Use is_path_readable_by_grub() to + verify readability of a few critical files. + * util/grub-mkconfig.in: Use is_path_readable_by_grub() to + verify readability of grub.cfg.new. + +2010-09-08 Vladimir Serbinenko + + Split minix.mod into minix.mod and minix2.mod. + + * Makefile.util.def (libgrub.a): Add grub-core/fs/minix2.c. + * grub-core/Makefile.core.def (minix2): New module. + * grub-core/fs/minix.c: Use definitions instead of runtime version + checking. + * grub-core/fs/minix2.c: New file. + +2010-09-08 Yves Blusseau + + Add new --boot-directory option to replace --root-directory + + * util/grub-install.in: Add new --boot-directory option + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + +2010-09-08 Yves Blusseau + + * util/grub-mkconfig.in: Use new variable. + +2010-09-08 Yves Blusseau + + * configure.ac: Define some useful variables. + +2010-09-08 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF when appropriate. + * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): + Use terminfo and don't use cursor-on/cursor-off unless it's known + to work. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New element + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. + +2010-09-08 Colin Watson + + * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix + starts with "(,", fill the drive containing the loaded image in + between those two characters, but expect that a full partition + specification including partition map names will follow. + +2010-09-08 Robert Millan + + * configure.ac: Remove `--enable-grub-fstest' option. + * Makefile.util.def (grub-fstest): Remove COND_GRUB_FSTEST condition. + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Use + `grub-fstest' instead of `grub-probe' for readability verification. + * util/grub-probe.c (probe): Remove readability verification kludge. + +2010-09-08 Robert Millan + + * util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when + initializing `GRUB_FS'. + +2010-09-08 BVK Chaitanya + + Not command (!) support to GRUB script. + + * tests/grub_script_not.in: New test. + * Makefile.util.def: Rules for new test. + + * grub-core/script/execute.c (grub_script_execute_cmdline): Handle + ! command as a special case. + * grub-core/script/yylex.l (GRUB_PARSER_TOKEN_NOT): Removed. + +2010-09-07 BVK Chaitanya + + * grub-core/commands/wildcard.c (wildcard_expand): Fix wrong + grub_free. + +2010-09-07 BVK Chaitanya + + * docs/grub.texi (Shell-like scripting): Fix @dots to @dots{}. + +2010-09-07 BVK Chaitanya + + * docs/grub.texi (Shell-like scripting): Documentation for break, + continue, shift and return commands. + +2010-09-06 Vladimir Serbinenko + + Rename CD-ROM to cd on BIOS. + + * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_get_drive): Recognise + "cd". + (grub_biosdisk_call_hook): Call with "cd" instead of arbitrary hdX. + +2010-09-05 Vladimir Serbinenko + + * grub-core/kern/emu/main.c (main): Reinit LVM and RAID. + * util/grub-probe.c (main): Likewise. + * util/i386/pc/grub-setup.c (main): Likewise. + * util/sparc64/ieee1275/grub-setup.c (main): Likewise. + Reported and debugged by: alexxy + +2010-09-05 Vladimir Serbinenko + + * grub-core/disk/lvm.c (grub_lvm_scan_device) [GRUB_UTIL]: Output more + diagnostic info. + +2010-09-05 Jo Shields + + * util/grub.d/30_os-prober.in: Add missing classes. + +2010-09-05 Vladimir Serbinenko + + * docs/grub.texi (Theme file format): Document new position format. + +2010-09-05 Vladimir Serbinenko + + * docs/grub.texi (Theme file format): Replace Box_slice_names.png with + a table. Use @code instead of @verbatim. + +2010-09-05 Colin D Bennett + + Gfxmenu documentation. + + * docs/grub.texi (Theme file format): New chapter. + +2010-09-05 Szymon Janc + + * grub-core/Makefile.core.def (xzio): New module. + * grub-core/io/xzio.c: New file. + * grub-core/lib/xzembed/xz.h: New file (from xembed). + * grub-core/lib/xzembed/xz_config.h: Likewise. + * grub-core/lib/xzembed/xz_dec_bcj.c: Likewise. + * grub-core/lib/xzembed/xz_dec_lzma2.c: Likewise. + * grub-core/lib/xzembed/xz_dec_stream.c: Likewise. + * grub-core/lib/xzembed/xz_lzma2.h: Likewise. + * grub-core/lib/xzembed/xz_private.h: Likewise. + * grub-core/lib/xzembed/xz_stream.h: Likewise. + * include/grub/file.h (grub_file_filter_id): New compression filter + GRUB_FILE_FILTER_XZIO. + +2010-09-05 Vladimir Serbinenko + + * include/grub/file.h (GRUB_FILE_SIZE_UNKNOWN): New definition. + * grub-core/disk/loopback.c (grub_loopback_open): Handle unknown file + size. + +2010-09-05 Vladimir Serbinenko + + * include/grub/err.h (grub_err_t): Replace GRUB_ERR_BAD_GZIP_DATA with + GRUB_ERR_BAD_COMPRESSED_DATA. All users updated. + +2010-09-05 Vladimir Serbinenko + + Uncompressed checksum support. + + * grub-core/commands/hashsum.c (options): Add option --uncompress. + (check_list): New parameter uncompress. + (grub_cmd_hashsum): Handle --uncompress. + +2010-09-05 Vladimir Serbinenko + + Reintroduce testload. + + * grub-core/commands/minicmd.c (grub_rescue_cmd_testload) [0]: Moved + from here ... + * grub-core/commands/testload.c (grub_cmd_testload): ... here. + (GRUB_MOD_INIT): New function. + (GRUB_MOD_FINI): Likewise. + * grub-core/Makefile.core.def (testload): New module. + +2010-09-05 Szymon Janc + + * grub-core/lib/posix_wrap/sys/types.h (bool): Transform into an enum. + (uint8_t): New type. + (uint16_t): Likewise. + (uint32_t): Likewise. + (uint64_t): Likewise. + +2010-09-05 Szymon Janc + + * include/grub/crypto.h (GRUB_MD_CRC32): New definition. + +2010-09-05 Vladimir Serbinenko + + * grub-core/io/gzio.c (grub_gzio_open): Removed "transparent" parameter. + Made static. + (grub_gzfile_open): Removed. All users updated. + (GRUB_MOD_INIT): New function. + (GRUB_MOD_FINI): Likewise. + * grub-core/kern/file.c (grub_file_filters_all): New variable. + (grub_file_filters_enabled): Likewise. + (grub_file_open): Handle filters. + * grub-core/loader/i386/bsd.c (GRUB_MOD_INIT): Load gzio. + * grub-core/normal/main.c (GRUB_MOD_INIT): Likewise. + * include/grub/file.h (grub_file_filter_id_t): New type. + (grub_file_filter_t): Likewise. + (grub_file_filters_all): New extern variable. + (grub_file_filters_enabled): Likewise. + (grub_file_filter_register): New inline function. + (grub_file_filter_unregister): Likewise. + (grub_file_filter_disable): Likewise. + (grub_file_filter_disable_compression): Likewise. + * include/grub/gzio.h: Removed. + +2010-09-04 BVK Chaitanya + + Filename expansion support for wildcards in GRUB script. + + * tests/grub_script_expansion.in: New test. + * Makefile.util.def: Rule for new test. + + * grub-core/commands/wildcard.c: New file, implements filename + expansion support for GRUB script. + * grub-core/Makefile.core.def: Rule update for regexp.mod. + * grub-core/script/argv.c: Cosmetic changes. + * grub-core/script/execute.c (grub_script_arglist_to_argv): + Refactored to perform wildcard expansion on arguments. + * include/grub/script_sh.h (grub_script_wildcard_translator): New + struct. + + * tests/util/grub-shell.in: Fix quoting for read input. + +2010-09-04 BVK Chaitanya + + Support for updating environment variables with matched substrings + of regexp. + + * tests/grub_cmd_regexp.in: New test. + * Makefile.util.def: Rule for new test. + + * grub-core/commands/regexp.c: New option -s to update environment + variables with regexp matches. + +2010-09-04 Szymon Janc + + * include/grub/file.h (grub_file): New member not_easly_seekable. + (grub_file_seekable): New inline function. + * grub-core/io/gzio.c (test_header): Don't test end magic if file isn't + easily seekable. + (grub_gzio_open): Set not_easly_seekable. + * grub-core/fs/i386/pc/pxe.c (grub_pxefs_open): Set not_easily_seekable. + * grub-core/io/bufio.c (grub_bufio_open): Propagate not_easily_seekable. + +2010-09-04 BVK Chaitanya + + Support for options to appear multiple times on cmdline. + + * include/grub/lib/arg.h (grub_arg_list_alloc): New prototype. + * grub-core/commands/extcmd.c: Support for repeatable option. + * grub-core/lib/arg.c (grub_arg_list_alloc): New function for + repeatable option support. + + Refactor menuentry into a regular command. + + * grub-core/commands/menuentry.c: New file, menuentry command + implementation. + * grub-core/Makefile.core.def: Rule update for normal.mod. + * grub-core/normal/main.c: Moved menuentry creation to + grub-core/commands/menuentry.c. + * grub-core/normal/menu.c (grub_menu_execute_entry): Removed. + (grub_menu_execute_entry_real): Removed. + * grub-core/script/execute.c (grub_script_execute_sourcecode): New + function. + (grub_script_execute_menuentry): Removed. + * grub-core/script/parser.y (menuentry): Removed. + * grub-core/script/script.c (grub_script_create_cmdmenu): Removed. + * grub-core/script/yylex.l (menuentry): Removed. + * include/grub/menu.h (grub_menu_init): New prototype. + (grub_menu_fini): New prototype. + * include/grub/normal.h (grub_normal_add_menu_entry): Removed. + * include/grub/script_sh.h (grub_script_cmd_menuentry): Removed. + (grub_script_execute_sourcecode): New prototype. + +2010-09-04 BVK Chaitanya + + "return" command for GRUB script functions. + + * tests/grub_script_return.in: New test. + * Makefile.util.def: Rules for new test. + + * grub-core/script/execute.c (grub_script_return): New function. + * grub-core/script/main.c: Register/unregister return commaond. + * include/grub/script_sh.h (grub_script_return): New prototype. + +2010-09-04 BVK Chaitanya + + "setparams" command to update positional parameters. + + * tests/grub_script_setparams.in: New test. + * Makefile.util.def: Rules for new test. + + * grub-core/script/argv.c (grub_script_argv_make): New function. + * grub-core/script/execute.c (replace_scope): New function. + (grub_script_setparams): New function. + * grub-core/script/lexer.c: Remove unused variables. + * grub-core/script/main.c: Register/unregister setparams command. + * include/grub/script_sh.h (grub_script_argv_make): New prototype. + (grub_script_setparams): New prototype. + +2010-09-04 BVK Chaitanya + + * grub-core/normal/completion.c (grub_normal_do_completion): Fix + grub_free order. + +2010-09-04 BVK Chaitanya + + Support for passing block of commands as an argument to extcmds. + + * Makefile.util.def: Rules for new test. + * tests/grub_script_blockarg.in: New test. + * grub-core/tests/test_blockarg.c: New file, block argument + command used in the test. + + * include/grub/extcmd.h (grub_extcmd_context): New struct. + (grub_register_extcmd_prio): New function prototype. + (grub_extcmd_dispatcher): New function prototype. + * include/grub/command.h (GRUB_COMMAND_FLAG_BLOCKS): New command + type. + * include/grub/script_sh.h (struct grub_script): New members + `children', `next_siblings' and `refcnt' for block arguments and + reference counting. + (GRUB_SCRIPT_ARG_TYPE_BLOCK): New argument type. + (grub_script_arg): New member `script' for block argument. + (grub_script_argv): New member `script' for block argument. + (grub_parser_param): New member `scripts' for block argument. + (grub_script_mem_free): New extern function prototype. + (grub_script_ref): New function prototype. + (grub_script_unref): New function prototype. + + * grub-core/normal/dyncmd.c (grub_dyncmd_dispatcher): Moved to + extcmd form to support block arguments. + * grub-core/script/argv.c: Block arguments support. + * grub-core/script/execute.c: Likewise. + * grub-core/script/lexer.c: Likewise. + * grub-core/script/main.c: Likewise. + * grub-core/script/script.c: Likewise. + * grub-core/script/parser.y: Likewise. New `block' and `block0' + non-terminals. + + * grub-core/commands/acpi.c: Update extcmd implementations with + grub_extcmd_context_t. + * grub-core/commands/cat.c: Likewise. + * grub-core/commands/echo.c: Likewise. + * grub-core/commands/extcmd.c: Likewise. + * grub-core/commands/hashsum.c: Likewise. + * grub-core/commands/hdparm.c: Likewise. + * grub-core/commands/help.c: Likewise. + * grub-core/commands/hexdump.c: Likewise. + * grub-core/commands/i386/cpuid.c: Likewise. + * grub-core/commands/i386/pc/drivemap.c: Likewise. + * grub-core/commands/i386/pc/halt.c: Likewise. + * grub-core/commands/i386/pc/sendkey.c: Likewise. + * grub-core/commands/iorw.c: Likewise. + * grub-core/commands/keystatus.c: Likewise. + * grub-core/commands/loadenv.c: Likewise. + * grub-core/commands/ls.c: Likewise. + * grub-core/commands/lspci.c: Likewise. + * grub-core/commands/memrw.c: Likewise. + * grub-core/commands/probe.c: Likewise. + * grub-core/commands/search_wrap.c: Likewise. + * grub-core/commands/setpci.c: Likewise. + * grub-core/commands/sleep.c: Likewise. + * grub-core/disk/loopback.c: Likewise. + * grub-core/hello/hello.c: Likewise. + * grub-core/loader/i386/bsd.c: Likewise. + * grub-core/loader/xnu.c: Likewise. + * grub-core/term/gfxterm.c: Likewise. + * grub-core/term/serial.c: Likewise. + * grub-core/tests/lib/functional_test.c: Likewise. + +2010-09-04 BVK Chaitanya + + Multi-line quoted strings support. + + * grub-core/script/lexer.c (append_newline): Removed. + (grub_script_lexer_yywrap): Refactored. + (grub_script_lexer_init): Refactored. + * grub-core/script/yylex.l (yywrap): New function. + (grub_lexer_resplit): New function. + (grub_lexer_unput): New function. + * include/grub/script_sh.h (grub_lexer_param): New members, unput + and resplit. + * tests/grub_script_echo1.in: Added few more testcases. + +2010-09-04 Vladimir Serbinenko + + * grub-core/kern/misc.c: Don't add abort alias in utils. + Reported by: echoline. + +2010-09-03 BVK Chaitanya + + Add missing files into "make dist" tarball for other platforms. + + * gentpl.py (script): Use dist_noinst_DATA instead of EXTRA_DIST. + * conf/Makefile.common (dist_noinst_DATA): New variable. + * conf/Makefile.extra-dist: Added missing make dist files. + * grub-core/Makefile.core.def: Likewise. + +2010-09-03 Vladimir Serbinenko + + Compress grub_prefix. + + * grub-core/boot/i386/pc/lnxboot.S: Use + GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE. + * grub-core/kern/i386/pc/startup.S: Move grub_prefix to compressed part. + * include/grub/offsets.h: Rename GRUB_MACHINE_DATA_END to + GRUB_MACHINE_PREFIX_END. All users updated. + (GRUB_KERNEL_I386_PC_PREFIX): Set to GRUB_KERNEL_I386_PC_RAW_SIZE. + (GRUB_KERNEL_I386_PC_PREFIX_END): Set to GRUB_KERNEL_I386_PC_PREFIX + + 0x40. + (GRUB_KERNEL_I386_PC_RAW_SIZE): Decrease. + * util/grub-mkimage.c (image_target_desc): Change data_end to + prefix_end. All users updated. + +2010-09-03 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_freebsd_boot): Set %ebp to sane + value. + (grub_openbsd_boot): Likewise. + (grub_netbsd_boot): Likewise. + * grub-core/loader/i386/xnu.c (grub_xnu_boot_resume): Likewise. + (grub_xnu_boot): Likewise. + +2010-09-02 Vladimir Serbinenko + + * configure.ac: Clean LIBS variable after tests. + +2010-09-02 Colin Watson + + * INSTALL: Document that libdevmapper needs to be 1.02.34 or later. + +2010-09-02 Vladimir Serbinenko + + * configure.ac: Check for dm_log_with_errno_init in libdevmapper and + echo if libdevmapper will be used. + +2010-09-02 Ian Turner + + * grub-core/fs/i386/pc/pxe.c (grub_pxefs_read): Keep the blocksize + constant for the same file. + +2010-09-02 Vladimir Serbinenko + + * grub-core/kern/i386/multiboot_mmap.c: Remove leftover include. + +2010-09-02 Colin Watson + + * .bzrignore: Add *.pp, **/.dirstamp, grub-core/*.module, and + grub-core/*.pp. + +2010-09-02 Colin Watson + + Zero %ebp and %edi when entering Linux's 32-bit entry point, as + required by the boot protocol. + + * include/grub/i386/relocator.h (struct grub_relocator32_state): Add + ebp and edi members. + * grub-core/lib/i386/relocator.c (grub_relocator_boot): Handle + state.ebp and state.edi. + * grub-core/lib/i386/relocator32.S (grub_relocator32_start): Set + %ebp and %edi according to grub_relocator32_ebp and + grub_relocator32_edi respectively. + * grub-core/loader/i386/linux.c (grub_linux_boot): Zero state.ebp + and state.edi. + +2010-09-02 Vladimir Serbinenko + + Add i386-pc-pxe image target. + + * util/grub-mkimage.c (image_target_desc): New enum value + IMAGE_I386_PC_PXE. + (image_targets): New target i386-pc-pxe. + (generate_image): Handle i386-pc-pxe image. + +2010-09-02 Vladimir Serbinenko + + Fix grub_pxe_scan. + + * grub-core/fs/i386/pc/pxe.c (grub_pxe_pxenv): Put correct type bangpxe. + (grub_pxe_scan): Fix types and pxe_rm_entry computation. + All users updated. + * include/grub/i386/pc/pxe.h (grub_pxe_bangpxe): New struct. + (grub_pxe_pxenv): Correct type. + +2010-09-01 Colin Watson + + * NEWS: Document most of the important changes since 1.98. + +2010-09-01 Colin Watson + + * util/grub-mkrescue.in (usage): Tidy up usage output (and hence + generated manual page) a little. + +2010-09-01 Colin Watson + + * docs/grub.texi: Add myself as an author. + +2010-09-01 Vladimir Serbinenko + + * Makefile.util.def (libgrub.a): Add missing sunpc. + Reported by: Seth Goldberg. + +2010-08-30 Vladimir Serbinenko + + Interrupt wrapping and code simplifications. + + * Makefile.util.def (grub-mkrescue): Use x86 tg instead of + x86_noieee1275 which are functionaly equivalent in this case. + (grub-install): Make source on each platform explicit. Enable on + all noemu. + * gentpl.py (x86_efi_pc): Removed group. + (x86_noefi): Likewise. + (i386_noefi): Likewise. + (x86_noieee1275): Likewise. + (i386_noieee1275): Likewise. + (i386_noefi_noieee1275): Likewise. + (i386_pc_qemu_coreboot): Likewise. + (i386_coreboot_multiboot): Likewise. + (i386_pc_coreboot_multiboot_qemu): Likewise. + (x86_noefi_mips): Likewise. + (noieee1275): Likewise. + (ieee1275_mips): Likewise. + (noemu_noieee1275): Likewise. + (cmos): New group. + (usb): Likewise. + (videoinkernel): Likewise. + (videomodules): Likewise. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Remove + include/grub/elf.h, include/grub/elfload.h, include/grub/net.h, + include/grub/reader.h, include/grub/symbol.h, include/grub/types.h, + include/grub/loader.h, include/grub/msdos_partition.h, + include/grub/machine/biosdisk.h, include/grub/machine/boot.h, + include/grub/machine/console.h, include/grub/machine/vga.h, + include/grub/machine/vbe.h, include/grub/machine/init.h, + include/grub/machine/kernel.h, include/grub/cpu/time.h, + include/grub/cpu/types.h, include/grub/gzio.h and include/grub/menu.h + (KERNEL_HEADER_FILES) [i386-pc]: Add include/grub/machine/int.h. + (KERNEL_HEADER_FILES) [i386-ieee1275]: Add include/grub/i386/pit.h + * grub-core/Makefile.core.def (kernel): Explicit the source for + startup. Explicit the platforms using kern/generic/rtc_get_time_ms.c. + Split ieee1275_mips. Remove kern/i386/halt.c. Remove kern/i386/misc.S. + Enable kern/i386/pit.c on all x86. Remove kern/i386/ieee1275/init.c. + Use videoinkernel tag. + (usb): Enable on all usb. + (usbserial_common): Likewise. + (usbserial_pl2303): Likewise. + (usbserial_ftdi): Likewise. + (uhci): Enable on all x86. + (ohci): Enable on all pci. + (cmostest): Enable on all CMOS. + (acpi): Include commands/acpi.c on all platforms. + (halt): Add relevant lib/*/halt.c. + (hdparm): Enable on all pci. + (lspci): Likewise. + (usbtest): Enable on all usb. + (ata): Enable on all pci. + (ata_pthru): Likewise. + (usbms): Enable on all usb. + (usb_keyboard): Likewise. + (font): Use tag videomodules. + (bufio): Likewise. + (datetime): Use tag cmos. Enable on all noemu. + (mmap): Use tags common and x86. + (gfxterm): Use tag videomodules. + (bitmap): Likewise. + (bitmap_scale): Likewise. + (video_fb): Likewise. + (video): Likewise. + * grub-core/bus/usb/ohci.c (grub_ohci_td): Make link_td a pointer and + adjust padding accordingly. All users updated. + (grub_ohci_transaction): Fix bad format specification. + (GRUB_MOD_INIT): Add asserts for struct size. + * grub-core/bus/usb/uhci.c (grub_uhci_pci_iter): Add explicit casts. + (grub_alloc_td): Likewise. + (grub_free_queue): Likewise. + (grub_uhci_transfer): Likewise. + (grub_uhci_transaction): Fix bad format specification. + * grub-core/bus/usb/usbtrans.c (grub_usb_control_msg): Likewise. + (grub_usb_bulk_readwrite): Likewise. + * grub-core/kern/i386/misc.S (grub_stop): Moved from here ... + * grub-core/commands/i386/pc/halt.c (stop): ...here. Transformed into C. + Made static. + * grub-core/lib/i386/halt.c (stop): ... and here. Transformed into C. + Made static. + * grub-core/kern/i386/pc/startup.S (grub_halt): Moved from here ... + * grub-core/commands/i386/pc/halt.c (grub_halt): ...here. + Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_biosdisk_rw_int13_extensions): + Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_rw_int13_extensions): + ... here. Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_biosdisk_rw_standard): + Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_rw_standard): + ... here. Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S + (grub_biosdisk_check_int13_extensions): Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c + (grub_biosdisk_check_int13_extensions): ... here. Transformed into C. + Made static. + * grub-core/kern/i386/pc/startup.S + (grub_biosdisk_get_cdinfo_int13_extensions): Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c + (grub_biosdisk_get_cdinfo_int13_extensions): ... here. + Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S + (grub_biosdisk_get_diskinfo_int13_extensions): Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c + (grub_biosdisk_get_diskinfo_int13_extensions): ... here. + Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S + (grub_biosdisk_get_diskinfo_standard): Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c + (grub_biosdisk_get_diskinfo_standard): ... here. + Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S + (grub_biosdisk_get_num_floppies): Moved from here ... + * grub-core/disk/i386/pc/biosdisk.c + (grub_biosdisk_get_num_floppies): ... here. + Transformed into C. Made static. + * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_get_diskinfo_real): + New function. + * grub-core/kern/i386/pc/startup.S (grub_pxe_scan): Moved from here ... + * grub-core/fs/i386/pc/pxe.c (grub_pxe_scan): ... here. + Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_rm_entry): Moved from here ... + * grub-core/fs/i386/pc/pxe.c (grub_rm_entry): ... here. + Transformed into C. Made static. + * grub-core/kern/i386/ieee1275/init.c: Removed. + * grub-core/kern/i386/misc.S: Likewise. + * grub-core/kern/i386/pc/startup.S (grub_get_memsize): + Splitted from here ... + * grub-core/kern/i386/pc/init.c (grub_get_conv_memsize): ... here. + Transformed into C. Made static. All users updated. + * grub-core/kern/i386/pc/mmap.c (grub_get_ext_memsize): ... and here. + Transformed into C. Made static. All users updated. + * grub-core/kern/i386/pc/startup.S (grub_get_eisa_mmap): + Moved from here... + * grub-core/kern/i386/pc/mmap.c (grub_get_eisa_mmap): ... here. + Transformed into C. Made static. All users updated. + * grub-core/kern/i386/pc/startup.S (grub_get_mmap_entry): + Moved from here... + * grub-core/kern/i386/pc/mmap.c (grub_get_mmap_entry): ... here. + Transformed into C. Made static. All users updated. + * grub-core/kern/i386/pc/startup.S (grub_stop_floppy): + Removed (replaced by C version). + * grub-core/kern/i386/pc/startup.S (grub_vga_set_mode): + Moved from here... + * grub-core/video/i386/pc/vga.c (grub_vga_set_mode): ...here. + Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_controller_info): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_controller_info): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_mode_info): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_mode_info): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_mode): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_mode): + ... here. Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_mode): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_mode): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S + (grub_vbe_bios_getset_dac_palette_width):Moved from here... + * grub-core/video/i386/pc/vbe.c + (grub_vbe_bios_getset_dac_palette_width):... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_memory_window): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_memory_window): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_memory_window): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_memory_window): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_scanline_length): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_scanline_length): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_scanline_length): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_scanline_length): + ... here. Transformed into C. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_display_start): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_display_start): + ... here. Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_display_start): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_display_start): + ... here. Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_palette_data): + Moved from here... + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_palette_data): + ... here. Transformed into C. Made static. + * grub-core/kern/i386/pc/startup.S (grub_pxe_call): Receive + pxe_rm_entry as third argument. + (grub_bios_interrupt): New function. + * grub-core/kern/i386/qemu/mmap.c: Remove useless include. + * grub-core/kern/i386/qemu/startup.S (codestart): Do cli;hlt instead + of calling grub_stop. + * grub-core/kern/efi/efi.c (grub_halt): Moved from here ... + * grub-core/lib/efi/halt.c (grub_halt): ...here. + * grub-core/kern/emu/main.c (grub_halt): Moved from here ... + * grub-core/lib/emu/halt.c (grub_halt): ... here. + * grub-core/lib/i386/halt.c: Moved from here ... + * grub-core/lib/i386/halt.c: ... here. + * grub-core/kern/ieee1275/openfw.c (grub_halt): Moved from here ... + * grub-core/lib/ieee1275/halt.c (grub_halt): ... here. + * grub-core/loader/i386/pc/linux.c (grub_linux16_boot): Call + grub_stop_floppy. + * grub-core/loader/i386/xnu.c (guessfsb) [IEEE1275]: Enable. + * include/grub/i386/coreboot/init.h: Removed. + * include/grub/i386/multiboot/init.h: Likewise. + * include/grub/i386/pc/biosdisk.h: Removed all function prototypes. + * include/grub/i386/pc/init.h: Likewise except grub_gate_a20. + * include/grub/i386/pc/int.h: New file. + * include/grub/i386/pc/pxe.h (GRUB_PXE_SIGNATURE): New definition. + (grub_pxe_scan): Removed. + (grub_pxe_call): Update prototype. + * include/grub/i386/pc/vbe.h: Removed EXPORT_FUNC and useless + prototypes. + * include/grub/i386/pc/vga.h (grub_vga_set_mode): Removed. + * include/grub/i386/qemu/init.h: Removed. + * include/grub/mips/yeeloong/kernel.h (grub_reboot): Add missing + noreturn. + (grub_halt): Likewise. + * include/grub/misc.h (grub_halt): Removed EXPORT_FUNC. + (grub_reboot): Likewise. + * grub-core/kern/i386/coreboot/init.c (grub_stop_floppy): Moved from here... + * include/grub/i386/floppy.h (grub_stop_floppy): ...here. Inlined. + * grub-core/kern/i386/pc/startup.S (grub_hard_stop): Removed. + +2010-08-30 Robert Millan + + * NEWS: Document addition of ZFS support in `grub-install' and + `grub-mkconfig'. + +2010-08-30 BVK Chaitanya + + * conf/Makefile.common (CPPFLAGS_DEFAULT): Remove leading / from + dprintf output. + +2010-08-30 Vladimir Serbinenko + + Remove leftover embedding of font objects. + + * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. + * util/grub-install.in (font): Removed. + * util/grub-mkimage.c (generate_image): Remove font support. All users + updated. + +2010-08-30 Vladimir Serbinenko + + Remove leftover embedding of font objects. + + * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. + * util/grub-install.in (font): Removed. + * util/grub-mkimage.c (generate_image): Remove font support. All users + updated. + +2010-08-30 Vladimir Serbinenko + + * docs/grub.texi (Network): Fix reference to pxe_blksize. + Reported by: Ian Turner + +2010-08-30 Vladimir Serbinenko + + * grub-core/normal/menu.c (grub_wait_after_message): Add a 10 second + timeout to avoid indefinite boot stalling. + +2010-08-30 Vladimir Serbinenko + + * grub-core/normal/color.c (grub_env_write_color_normal): Fix a warning. + (grub_env_write_color_highlight): Likewise. + +2010-08-30 Vladimir Serbinenko + + * grub-core/normal/term.c (print_more): Return to normal and not + to standard state after printing "---MORE---". + +2010-08-30 Vladimir Serbinenko + + * grub-core/term/i386/vga_common.c (grub_console_setcolorstate): + Mask out the bit 0x80 since it has other meaning that specifiing color. + +2010-08-29 Vladimir Serbinenko + + New relocator. Allows for more kernel support and more straightforward + loader writing. + + * Makefile.am (BOOTTARGET): New variable. + (QEMU32): Likewise. + (linux.init.x86_64): New target. + (linux.init.i386): Likewise. + (multiboot.elf): Likewise. + (kfreebsd.elf): Likewise. + (kfreebsd.aout): Likewise. + (pc-chainloader.elf): Likewise. + (pc-chainloader.bin): Likewise. + (ntldr.elf): Likewise. + (ntldr.bin): Likewise. + (multiboot2.elf): Likewise. + (kfreebsd.init.x86_64): Likewise. + (kfreebsd.init.i386): Likewise. + (knetbsd.init.i386): Likewise. + (kopenbsd.init.i386): Likewise. + (knetbsd.init.x86_64): Likewise. + (kopenbsd.init.x86_64): Likewise. + (linux-initramfs.i386): Likewise. + (linux-initramfs.x86_64): Likewise. + (kfreebsd-mfsroot.i386.img): Likewise. + (knetbsd.image.i386): Likewise. + (kopenbsd.image.i386): Likewise. + (kopenbsd.image.x86_64): Likewise. + (knetbsd.miniroot-image.i386.img): Likewise. + (kfreebsd-mfsroot.x86_64.img): Likewise. + (knetbsd.image.x86_64): Likewise. + (knetbsd.miniroot-image.x86_64.img): Likewise. + (kfreebsd-mfsroot.i386.gz): Likewise. + (bootcheck-kfreebsd-i386): Likewise. + (kfreebsd-mfsroot.x86_64.gz): Likewise. + (bootcheck-kfreebsd-x86_64): Likewise. + (knetbsd.miniroot-image.i386.gz): Likewise. + (bootcheck-knetbsd-i386): Likewise. + (bootcheck-kopenbsd-i386): Likewise. + (bootcheck-kopenbsd-x86_64): Likewise. + (knetbsd.miniroot-image.x86_64.gz): Likewise. + (bootcheck-knetbsd-x86_64): Likewise. + (bootcheck-linux-i386): Likewise. + (bootcheck-linux-x86_64): Likewise. + (bootcheck-linux16-i386): Likewise. + (bootcheck-linux16-x86_64): Likewise. + (bootcheck-multiboot): Likewise. + (bootcheck-multiboot2): Likewise. + (bootcheck-kfreebsd-aout): Likewise. + (bootcheck-pc-chainloader): Likewise. + (bootcheck-ntldr): Likewise. + (CLEANFILES): Add new targets. + (BOOTCHECKS): New variable. + (.PHONY): Add bootchecks. + (SUCCESSFUL_BOOT_STRING): New variable. + (BOOTCHECK_TIMEOUT): Likewise. + (bootcheck): New target + * Makefile.util.def (grub-mkrescue): Enable on i386-multiboot. + * configure.ac: Correct efiemu excuse. + * docs/grub.texi (Supported kernels): New chapter. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add + include/grub/mm_private.h. Simplify inclusion of + include/grub/boot.h, include/grub/loader.h + and include/grub/msdos_partition.h + (KERNEL_HEADER_FILES) [i386_coreboot]: + Remove include/grub/machine/loader.h. Add include/grub/i386/pit.h. + (KERNEL_HEADER_FILES) [i386_multiboot]: Likewise. + (KERNEL_HEADER_FILES) [i386_qemu]: Likewise. + (KERNEL_HEADER_FILES) [i386_ieee1275]: Remove + include/grub/machine/loader.h. + (KERNEL_HEADER_FILES) [x86_64-efi]: Likewise. + * grub-core/Makefile.core.def (kernel): Remove kern/i386/loader.S from + extra_dist. + (pci.mod): Enable on i386-multiboot. + (acpi.mod): Enable on i386-multiboot and i386-coreboot. + (efiemu.mod): Enable on i386-coreboot, i386-ieee1275, i386-multiboot and + i386-qemu. + (relocator.mod): Rewritten. + (aout.mod): Enable on all x86. + (bsd.mod): Likewise. + (ntldr.mod): New module. + (linux.mod): Use loader/i386/linux.c on all x86. + (xnu.mod): Enable on all x86. + (vga_text.mod): disable on EFI and QEMU. + * grub-core/efiemu/i386/coredetect.c: Remove useless include. + * grub-core/efiemu/i386/pc/cfgtables.c: Likewise. + * grub-core/efiemu/loadcore.c: Likewise. + * grub-core/efiemu/main.c: Likewise. + (grub_efiemu_exit_boot_services): Removed. + (grub_efiemu_finish_boot_services): Likewise. + * grub-core/efiemu/mm.c (grub_efiemu_finish_boot_services): New + function. + * grub-core/efiemu/i386/nocfgtables.c: New file. + * grub-core/kern/dl.c (grub_dl_unload_all): Removed. + * grub-core/kern/efi/efi.c (grub_efi_exit_boot_services): Removed. + (grub_efi_finish_boot_services): Moved from here ... + * grub-core/kern/efi/mm.c (grub_efi_finish_boot_services): ...here. + Fille finish memory map and related data. + (finish_mmap_buf): New variable. + (grub_efi_uintn_t finish_mmap_size): Likewise. + (grub_efi_uintn_t finish_key): Likewise. + (grub_efi_uintn_t finish_desc_size): Likewise. + (grub_efi_uint32_t finish_desc_version): Likewise. + (grub_efi_is_finished): Likewise. + (grub_efi_get_memory_map): Use saved memory map if EFI is already + finished. + * grub-core/kern/elf.c (grub_elf32_phdr_iterate): Make global. + (grub_elf64_phdr_iterate): Likewise. + * grub-core/kern/i386/coreboot/init.c (grub_os_area_addr): Removed. + (grub_os_area_size): Likewise. + (grub_machine_init): Don't reserve os area. + * grub-core/kern/i386/coreboot/startup.S: Don't include loader.S. + * grub-core/kern/i386/ieee1275/startup.S: Likewise. + * grub-core/kern/i386/loader.S: Removed. + * grub-core/kern/i386/pc/init.c (grub_os_area_addr): Removed. + (grub_os_area_size): Likewise. + (grub_machine_init): Don't reserve os area. + * grub-core/kern/i386/pc/startup.S (grub_chainloader_real_boot): + Don't call grub_dl_unload_all. + Don't include loader.S. + * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_iterate): + Declare the memory after _end as available. + * grub-core/kern/mm.c (GRUB_MM_FREE_MAGIC): Moved from here... + * include/grub/mm_private.h (GRUB_MM_FREE_MAGIC): ... here. + (GRUB_MM_ALLOC_MAGIC): Moved from here... + * include/grub/mm_private.h (GRUB_MM_ALLOC_MAGIC): ... here. + * grub-core/kern/mm.c (grub_mm_header): Moved from here... + * include/grub/mm_private.h (grub_mm_header): ... here. + * grub-core/kern/mm.c (GRUB_MM_ALIGN): Moved from here... + * include/grub/mm_private.h (GRUB_MM_ALIGN): ... here. + * grub-core/kern/mm.c (grub_mm_region): Moved from here ... + (grub_mm_region): ..here. Removed addr. Added pre_size. + All users updated. + * grub-core/kern/mm.c (base): Renamed to ... + (grub_mm_base): ... this. Made global. + (grub_real_malloc): Alloc from end of region. + (grub_memalign): Don't attempt to malloc if grub_mm_base is NULL. + * grub-core/kern/powerpc/cache.S (grub_arch_sync_caches): Move to ... + * grub-core/kern/powerpc/cache_flush.S: ... here. + * grub-core/lib/efi/relocator.c: New file. + * grub-core/lib/i386/relocator.c: Rewritten. + * grub-core/lib/i386/relocator16.S: New file. + * grub-core/lib/i386/relocator32.S: Likewise. + * grub-core/lib/i386/relocator64.S: Likewise. + * grub-core/lib/i386/relocator_asm.S: Rewritten. + * grub-core/lib/i386/relocator_common.S: New file. + * grub-core/lib/ieee1275/relocator.c: Likewise. + * grub-core/lib/mips/relocator.c: Rewritten. + * grub-core/lib/mips/relocator_asm.S: Renamed variables and minor + stylistic adjustments. + * grub-core/lib/powerpc/relocator.c: New file. + * grub-core/lib/powerpc/relocator_asm.S: Likewise. + * grub-core/lib/relocator.c: Rewritten. + * grub-core/lib/x86_64/relocator_asm.S: New file. + * grub-core/loader/aout.c (grub_aout_load): Make load_addr a void *. + * grub-core/loader/i386/bsd.c (NETBSD_DEFAULT_VIDEO_MODE): New const. + (bsd_tag): New struct. + (tags): New variable. + (tags_last): Likewise. + (netbsd_module): New struct. + (netbsd_mods): New variable. + (netbsd_mods_last): Likewise. + (openbsd_opts): New parameter "serial". + (OPENBSD_SERIAL_ARG): New definition. + (netbsd_opts): New parameter "serial". + (NETBSD_SERIAL_ARG): New definition. + (grub_freebsd_add_meta): Reorganised into ... + (grub_bsd_add_meta): ...this. All users updated. + (grub_freebsd_add_mmap): Reorganised into ... + (generate_e820_mmap): ...this... + (grub_bsd_add_mmap): ...and this. All users updated. + (grub_freebsd_list_modules): Use tags. + (grub_netbsd_add_meta_module): New function. + (grub_netbsd_list_modules): Likewise. + (grub_freebsd_boot): Use relocator and finish EFI. + (grub_openbsd_boot): Likewise. + (grub_netbsd_setup_video): New function. + (grub_netbsd_add_modules): Likewise. + (grub_netbsd_boot): Use grub_netbsd_add_modules, relocator, netbsd_tags + and finish EFI. + (grub_bsd_unload): Unload tags. + (grub_bsd_load_aout): Use relocator. + (grub_bsd_elf32_size_hook): New function. + (grub_bsd_elf32_hook): Use relocator. + (grub_bsd_elf64_size_hook): New function. + (grub_bsd_elf64_hook): Use relocator. + (grub_bsd_load_elf): Use relocator and call grub_openbsd_find_ramdisk. + (grub_bsd_load): Zero-out openbsd_ramdisk. + (grub_bsd_load): Use relocator. + (grub_cmd_openbsd): Support serial. + (grub_cmd_netbsd): Support modules. + (grub_cmd_freebsd_module): Use relocator. + (grub_netbsd_module_load): New function. + (grub_cmd_netbsd_module): Likewise. + (grub_cmd_openbsd_ramdisk): Likewise. + (GRUB_MOD_INIT): Register knetbsd_module, knetbsd_module_elf and + kopenbsd_ramdisk. + (GRUB_MOD_FINI): Unregister new commands. + * grub-core/loader/i386/bsdXX.c (load): Remove useless checks. + (grub_freebsd_load_elfmodule_obj): Use relocator. + (grub_freebsd_load_elfmodule): Likewise. + (grub_freebsd_load_elf_meta): Likewise. + (grub_netbsd_load_elf_meta): New function. + (grub_openbsd_find_ramdisk): Likewise. + * grub-core/loader/i386/bsd_helper.S: Removed. + * grub-core/loader/i386/bsd_pagetable.c: Support relocator. + * grub-core/loader/i386/bsd_trampoline.S: Removed. + * grub-core/loader/i386/efi/linux.c: Likewise. + * grub-core/loader/i386/ieee1275/linux.c: Likewise. + * grub-core/loader/i386/linux.c (HAS_VGA_TEXT): New const. + (DEFAULT_VIDEO_MODE): Likewise. + (real_mode_target): New variable. + (prot_mode_target): Likewise. + (initrd_mem_target): Likewise. + (relocator): Likewise. + (efi_mmap_buf): Likewise. + (efi_mmap_size): Likewise. + (find_efi_mmap_size): Moved from grub-core/loader/i386/efi/linux.c. + (free_pages): Use relocator. + (allocate_pages): Account for efi_mmap and use relocator. Return error. + (grub_linux_setup_video): Return error. + (grub_linux_trampoline_start): Removed. + (grub_linux_trampoline_end): Likewise. + (grub_linux_boot): Use relocator and DEFAULT_VIDEO_MODE. Pass console + andd video parameters depending on firmware. + [GRUB_MACHINE_IEEE1275]: Pass OFW parameters. + [GRUB_MACHINE_EFI]: Pass EFI parameters. + (grub_cmd_linux) [GRUB_MACHINE_EFI]: Likewise. + (grub_cmd_initrd): Use relocator. + * grub-core/loader/i386/linux_trampoline.S: Removed. + * grub-core/loader/i386/multiboot_mbi.c (elf_sec_num): New variable. + (elf_sec_entsize): Likewise. + (elf_sec_shstrndx): Likewise. + (elf_sections): Likewise. + (grub_multiboot_load): Use relocator. + (grub_multiboot_get_mbi_size): Account for sections. + (grub_multiboot_make_mbi): Use relocator and support sections. + (grub_multiboot_add_elfsyms): New function. + (grub_multiboot_free_mbi): Free sections. + * grub-core/loader/i386/pc/linux.c (relocator): New variable. + (grub_linux_real_target): Likewise. + (grub_linux_real_chunk): Likewise. + (grub_linux16_prot_size): Likewise. + (grub_linux16_boot): Use relocator. + (grub_linux_unload): Unload relocator. + (grub_cmd_linux): Use relocator. + (grub_cmd_initrd): Likewise. + * grub-core/loader/i386/pc/ntldr.c: New file. + * grub-core/loader/i386/xnu.c (guessfsb) [GRUB_MACHINE_IEEE1275]: + Don't try to guess CPU frequency. + (grub_xnu_set_video): Stretch bitmap. + (grub_xnu_boot): Use relocator. + * grub-core/loader/mips/linux.c (grub_linux_boot): Use relocator. + (grub_linux_unload): Free relocator. + (grub_linux_load32): Use relocator. + (grub_linux_load64): Likewise. + (grub_cmd_initrd): Likewise. + * grub-core/loader/multiboot.c (grub_multiboot_boot): Use relocator. + (grub_multiboot_unload): Unload relocator. + (grub_cmd_multiboot): Use relocator. + (grub_cmd_module): Likewise. + * grub-core/loader/multiboot_elfxx.c (grub_multiboot_load_elfXX): + Use relocator and support sections. + * grub-core/loader/multiboot_mbi2.c(elf_sec_num): New variable. + (elf_sec_entsize): Likewise. + (elf_sec_shstrndx): Likewise. + (elf_sections): Likewise. + (grub_multiboot_load): Use relocator. + (grub_multiboot_get_mbi_size): Account for sections. + (grub_multiboot_make_mbi): Use relocator and support sections. + (grub_multiboot_add_elfsyms): New function. + * grub-core/loader/powerpc/ieee1275/linux.c: Remove useless include. + * grub-core/loader/sparc64/ieee1275/linux.c: Likewise. + * grub-core/loader/xnu.c (grub_xnu_heap_malloc): Use relocator. + Prototype changed. All users updated. + (grub_xnu_align_heap): Simplified. + (grub_xnu_writetree_toheap): Likewise. + (grub_xnu_unload): Unload relocator. + (grub_cmd_xnu_kernel): Use relocator. + (grub_cmd_xnu_kernel64): Likewise. + (grub_xnu_register_memory): Simplified. + * grub-core/loader/xnu_resume.c (grub_xnu_resume): Use relocator. + * grub-core/term/efi/console.c (grub_console_putchar): Abort if + EFI is finished. + (grub_console_checkkey): Likewise. + (grub_console_getkey): Likewise. + (grub_console_getwh): Likewise. + (grub_console_getxy): Likewise. + (grub_console_gotoxy): Likewise. + (grub_console_cls): Likewise. + (grub_console_setcolorstate): Likewise. + (grub_console_setcursor): Likewise. + * grub-core/term/ns8250.c (grub_ns8250_hw_get_port): New function. + * grub-core/tests/boot/kbsd.init-i386.S: New file. + * grub-core/tests/boot/kbsd.init-x86_64.S: Likewise. + * grub-core/tests/boot/kbsd.spec.txt: Likewise. + * grub-core/tests/boot/kernel-8086.S: Likewise. + * grub-core/tests/boot/kernel-i386.S: Likewise. + * grub-core/tests/boot/kfreebsd-aout.cfg: Likewise. + * grub-core/tests/boot/kfreebsd.cfg: Likewise. + * grub-core/tests/boot/kfreebsd.init-i386.S: Likewise. + * grub-core/tests/boot/kfreebsd.init-x86_64.S: Likewise. + * grub-core/tests/boot/knetbsd.cfg: Likewise. + * grub-core/tests/boot/kopenbsd.cfg: Likewise. + * grub-core/tests/boot/kopenbsdlabel.txt: Likewise. + * grub-core/tests/boot/linux.cfg: Likewise. + * grub-core/tests/boot/linux.init-i386.S: Likewise. + * grub-core/tests/boot/linux.init-x86_64.S: Likewise. + * grub-core/tests/boot/linux16.cfg: Likewise. + * grub-core/tests/boot/multiboot.cfg: Likewise. + * grub-core/tests/boot/multiboot2.cfg: Likewise. + * grub-core/tests/boot/ntldr.cfg: Likewise. + * grub-core/tests/boot/pc-chainloader.cfg: Likewise. + * include/grub/aout.h (grub_aout_load): Make load_addr a void *. + * include/grub/autoefi.h (grub_autoefi_finish_boot_services): + New definition. + * include/grub/dl.h (grub_dl_unload_all): Removed. + * include/grub/efi/efi.h (grub_efi_exit_boot_services): Likewise. + (grub_efi_finish_boot_services): Change prototype. + (grub_efi_is_finished): New variable. + * include/grub/efiemu/efiemu.h (grub_efiemu_finish_boot_services): + Changed prototype. + (grub_efiemu_finish_boot_services): Removed. + (grub_machine_efiemu_init_tables): New prototype. + * include/grub/elfload.h (grub_elf32_phdr_iterate): Likewise. + (grub_elf64_phdr_iterate): Likewise. + * include/grub/i386/bsd.h: Include relocator.h. + (freebsd_tag_header): New struct. + (grub_openbsd_bios_mmap): Removed. + (grub_unix_real_boot): Removed. + (grub_freebsd_load_elfmodule32): Changed prototype. + (grub_freebsd_load_elfmodule_obj64): Likewise. + (grub_freebsd_load_elf_meta32): Likewise. + (grub_freebsd_load_elf_meta64): Likewise. + (grub_freebsd_add_meta): Removed. + (grub_netbsd_load_elf_meta32): New prototype. + (grub_netbsd_load_elf_meta64): Likewise. + (grub_bsd_add_meta): Likewise. + (grub_openbsd_ramdisk_descriptor): New struct. + (grub_openbsd_find_ramdisk32): New prototype. + (grub_openbsd_find_ramdisk64): Likewise. + * include/grub/i386/coreboot/loader.h: Removed. + * include/grub/i386/efi/loader.h: Likewise. + * include/grub/i386/ieee1275/loader.h: Likewise. + * include/grub/i386/linux.h (linux_kernel_header): Change void * + to grub_uint32_t. + * include/grub/i386/loader.h: Removed. + * include/grub/i386/memory.h (GRUB_MEMORY_CPU_CR4_PAE_ON): Correct the + value. + (GRUB_MEMORY_CPU_CR4_PSE_ON): New definition. + (grub_phys_addr_t): New type. + (grub_vtop): New inline function. + (grub_map_memory): Likewise. + (grub_unmap_memory): Likewise. + * include/grub/i386/multiboot/loader.h: Removed. + * include/grub/i386/netbsd_bootinfo.h (NETBSD_BTINFO_BOOTDISK): Removed. + (NETBSD_BTINFO_CONSOLE): New definition. + (NETBSD_BTINFO_SYMTAB): Likewise. + (NETBSD_BTINFO_MODULES): Likewise. + (NETBSD_BTINFO_FRAMEBUF): Likewise. + (grub_netbsd_bootinfo): New struct. + (grub_netbsd_btinfo_common): Use explicit bitsize. + (grub_netbsd_btinfo_mmap_entry): Removed. + (GRUB_NETBSD_MAX_BOOTPATH_LEN): New definition. + (grub_netbsd_btinfo_bootdisk): New struct. + (grub_netbsd_btinfo_symtab): Likewise. + (grub_netbsd_btinfo_serial): Likewise. + (grub_netbsd_btinfo_modules): Likewise. + (grub_netbsd_btinfo_framebuf): Likewise. + (GRUB_NETBSD_MAX_ROOTDEVICE_LEN): New definition. + * include/grub/i386/openbsd_bootarg.h (OPENBSD_BOOTARG_CONSOLE): + Likewise. + (grub_openbsd_bootargs): Use explicit bitsize. + (grub_openbsd_bootarg_console): New struct. + (GRUB_OPENBSD_COM_MAJOR): New definition. + (GRUB_OPENBSD_VGA_MAJOR): Likewise. + * include/grub/i386/pc/efiemu.h: Removed. + * include/grub/i386/pc/loader.h: Don't include cpu/loader.h. + * include/grub/i386/qemu/loader.h: Removed. + * include/grub/i386/relocator.h: Rewritten. + * include/grub/i386/xnu.h (grub_xnu_heap_will_be_at): Removed. + * include/grub/mips/memory.h: New file. + * include/grub/mips/multiboot.h: Rewritten. + * include/grub/mips/relocator.h: Rewritten. + * include/grub/mips/yeeloong/memory.h (grub_phys_addr_t): New type. + (grub_vtop): New function. + (grub_map_memory): Likewise. + (grub_unmap_memory): Likewise. + * include/grub/misc.h (ALIGN_DOWN): New definition. + * include/grub/mm.h (grub_mm_check_real): New proto. + (GRUB_MM_CHECK): New definition. + * include/grub/mm_private.h: New file. + * include/grub/multiboot.h (grub_multiboot_relocator): New variable. + (grub_multiboot_get_mbi_size): Removed. + (grub_multiboot_make_mbi): Change prottype. + (grub_multiboot_set_accepts_video): New proto. + (grub_multiboot_add_elfsyms): Likewise. + (grub_multiboot_payload_eip): New variable. + * include/grub/ns8250.h (grub_ns8250_hw_get_port) [!ASM_FILE]: + New prototype. + * include/grub/offsets.h (GRUB_KERNEL_I386_MULTIBOOT_PREFIX): + New definition. + (GRUB_KERNEL_I386_MULTIBOOT_DATA_END): Likewise. + (GRUB_KERNEL_I386_MULTIBOOT_MOD_ALIGN): Likewise. + * include/grub/powerpc/ieee1275/loader.h: Removed. + * include/grub/powerpc/memory.h: New file. + * include/grub/powerpc/relocator.h: Likewise. + * include/grub/relocator.h: Likewise. + * include/grub/relocator_private.h: Likewise. + * include/grub/sparc64/ieee1275/loader.h: Removed. + * include/grub/x86_64/memory.h: New file. + * include/grub/xnu.h (grub_xnu_writetree_toheap): Changed prototype. + (grub_xnu_heap_malloc): Likewise. + (grub_xnu_heap_real_start): Removed. + (grub_xnu_heap_start): Likewise. + (grub_xnu_relocator): New variable. + (grub_xnu_heap_target_start): Likewise. + * tests/util/grub-shell.in: Support non-pc. + * util/grub-mkimage.c (image_targets): Fix multiboot target. + +2010-08-29 Vladimir Serbinenko + + * grub-core/normal/charset.c (grub_utf8_to_ucs4_alloc): Avoid deadloop + on malloc error. + (grub_bidi_logical_to_visual): Check that malloc succeded. + * grub-core/normal/term.c (grub_puts_terminal): Fix fallback to dumb + puts. + (grub_xputs_normal): Likewise. + +2010-08-29 Vladimir Serbinenko + + * grub-core/Makefile.core.def (kernel): Add kern/mips/cache_flush.S to + extra_dist. + +2010-08-29 Vladimir Serbinenko + + * grub-core/efiemu/runtime/efiemu.sh: Removed. + +2010-08-29 Vladimir Serbinenko + + * Makefile.util.def (grub-ofpathname): Add missing ldadd. + +2010-08-29 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_real_dprintf): Always refresh after + dprintf. + +2010-08-29 BVK Chaitanya + + * Makefile.util.def: Use ldadd instead of ldflags for libraries. + +2010-08-28 Vladimir Serbinenko + + * grub-core/normal/term.c (print_more): Fix a memory leak. + (grub_puts_terminal): Revert to dumb puts if memory allocation fails. + (grub_xputs_normal): Likewise. + +2010-08-28 Vladimir Serbinenko + + * grub-core/script/lexer.c (grub_script_lexer_init): Don't look before + the begining of the string + +2010-08-28 Vladimir Serbinenko + + * grub-core/script/script.c (grub_script_parse): Free parsed on + failure. + +2010-08-28 Vladimir Serbinenko + + * grub-core/normal/completion.c (grub_normal_do_completion): Free argv + on failure. + +2010-08-28 Vladimir Serbinenko + + * grub-core/normal/cmdline.c (grub_cmdline_get): Free cl_terms on + return. + +2010-08-28 Vladimir Serbinenko + + * grub-core/term/gfxterm.c (grub_gfxterm_term_fini): Free the text buffer. + (scroll_up): Fix a memory leak. + +2010-08-28 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_load_sb): Handle grub_disk_read + errors. + +2010-08-27 Vladimir Serbinenko + + Handle USB pendrives exposed as floppies. + + * grub-core/boot/i386/pc/boot.S: Check LBA even on what appears to be + floppy. + * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_open): Likewise. + Check for partitions on all devices. + +2010-08-25 Vladimir Serbinenko + + * grub-core/term/ieee1275/ofconsole.c (put): Correct prototype. + (readkey): Likewise. + +2010-08-25 BVK Chaitanya + + Multiple variable names support to "export" command. + + * normal/context.c (grub_cmd_export): "export" command supports + multiple variable names. + +2010-08-23 Samuel Thibault + + * util/grub.d/30_os-prober.in: Fix conversion from grub-probe + --target=drive output to Mach device name. + +2010-08-23 BVK Chaitanya + + New Automake based build system for GRUB. + + * ABOUT-NLS: New file. + * Makefile.am: New file. GRUB host utils' rules that doesn't fit + in Makefile.util.def file. + * Makefile.util.def: New file. Autogen build definitions file for + GRUB host utils. + * conf/Makefile.common: New file. Common variables for GRUB host + utils and target modules. + * conf/Makefile.extra-dist: New file. Extra files for make dist. + * docs/Makefile.am: New file. Automake file for docs. + * gentpl.py: New file. Python script to generate Autogen + template. + * grub-core/Makefile.am: New file. GRUB target modules' rules + that doesn't fit in Makefile.core.def file. + * grub-core/Makefile.core.def: New file. Autogen build + definitions file for GRUB target modules. + * grub-core/lib/setjmp.S: New file. Wrapper for target_cpu + specific setjmp.S file. + * po/Makefile.am: New file. + + * .bzrignore: New ignores. + * INSTALL: New requirements, without Ruby. + * acinclude.m4: Use TARGET_IMG_BASE_LDOPT variable instead. + * autogen.sh: Updated to invoke autogen as necessary. + * configure.ac: Separate *FLAGS with HOST_ and TARGET_ prefixes, + and defines for Automake conditionals. + * geninit.sh: Refactoring. + + * include/grub/dl.h: Allow build rules to define GRUB_MOD_* if + necessary. + * include/grub/emu/getroot.h (grub_make_system_path_relative_to_its_root): + New prototype. + + * include/grub/test.h: Fix functional test modules' naming. + * grub-core/tests/example_functional_test.c: Fix test module name. + + * util/misc.c: Hosted versions' of grub functions for libgrub.a + * tests/lib/unit_test.c: Remove hosted versions of grub functions. + * util/grub-editenv.c: Likewise. + * util/grub-fstest.c: Likewise. + * util/grub-mkdevicemap.c: Likewise. + * util/grub-mkfont.c: Likewise. + * util/grub-mkimage.c: Likewise. + * util/grub-mkpasswd-pbkdf2.c: Likewise. + * util/grub-probe.c: Likewise. + * util/grub-script-check.c: Likewise. + * util/i386/pc/grub-setup.c: Likewise. + * util/sparc64/ieee1275/grub-setup.c: Likewise. + + * tests/util/grub-shell.in: Fix override directory path. + * util/grub-mkrescue.in: Replace @pkglib_DATA@ with files. + * util/import_gcry.py: Create Makefile.gcry.def file instead. + + * util/lvm.c: Update #includes. + * util/raid.c: Likewise. + * util/resolve.c: Likewise. + * grub-core/bus/emu/pci.c: Likewise. + * grub-core/lib/posix_wrap/stdlib.h: Likewise. + * grub-core/lib/posix_wrap/string.h: Likewise. + * grub-core/kern/emu/main.c: Likewise. + + * grub-core/gensymlist.sh: New file. Script for generating kernel + symbols file. + * grub-core/genmoddep.awk: Support new kernel_syms.lst format. + + * grub-core/gentrigtables.c: Fix unused variable warnings. + + * Makefile.in: Removed. + * conf/any-emu.rmk: Removed. + * conf/common.rmk: Removed. + * conf/i386-coreboot.rmk: Removed. + * conf/i386-efi.rmk: Removed. + * conf/i386-ieee1275.rmk: Removed. + * conf/i386-multiboot.rmk: Removed. + * conf/i386-pc.rmk: Removed. + * conf/i386-qemu.rmk: Removed. + * conf/i386.rmk: Removed. + * conf/mips-yeeloong.rmk: Removed. + * conf/mips.rmk: Removed. + * conf/powerpc-ieee1275.rmk: Removed. + * conf/sparc64-ieee1275.rmk: Removed. + * conf/tests.rmk: Removed. + * conf/x86-efi.rmk: Removed. + * conf/x86_64-efi.rmk: Removed. + * gendistlist.sh: Removed. + * geninitheader.sh: Removed. + * genkernsyms.sh.in: Removed. + * genmk.rb: Removed. + * gensymlist.sh.in: Removed. + * mkinstalldirs: Removed. + * boot: Moved ... + * grub-core/boot: ... to here. + * bus: Moved ... + * grub-core/bus: ... to here. + * commands: Moved ... + * grub-core/commands: ... to here. + * disk: Moved ... + * grub-core/disk: ... to here. + * efiemu: Moved ... + * grub-core/efiemu: ... to here. + * font: Moved ... + * grub-core/font: ... to here. + * fs: Moved ... + * grub-core/fs: ... to here. + * gencmdlist.sh: Moved ... + * grub-core/gencmdlist.sh: ... to here. + * genemuinit.sh: Moved ... + * grub-core/genemuinit.sh: ... to here. + * genemuinitheader.sh: Moved ... + * grub-core/genemuinitheader.sh: ... to here. + * genfslist.sh: Moved ... + * grub-core/genfslist.sh: ... to here. + * genhandlerlist.sh: Moved ... + * grub-core/genhandlerlist.sh: ... to here. + * genmoddep.awk: Moved ... + * grub-core/genmoddep.awk: ... to here. + * genmodsrc.sh: Moved ... + * grub-core/genmodsrc.sh: ... to here. + * genpartmaplist.sh: Moved ... + * grub-core/genpartmaplist.sh: ... to here. + * genparttoollist.sh: Moved ... + * grub-core/genparttoollist.sh: ... to here. + * genterminallist.sh: Moved ... + * grub-core/genterminallist.sh: ... to here. + * gentrigtables.c: Moved ... + * grub-core/gentrigtables.c: ... to here. + * genvideolist.sh: Moved ... + * grub-core/genvideolist.sh: ... to here. + * gettext: Moved ... + * grub-core/gettext: ... to here. + * gfxmenu: Moved ... + * grub-core/gfxmenu: ... to here. + * gnulib: Moved ... + * grub-core/gnulib: ... to here. + * hello: Moved ... + * grub-core/hello: ... to here. + * hook: Moved ... + * grub-core/hook: ... to here. + * io: Moved ... + * grub-core/io: ... to here. + * kern: Moved ... + * grub-core/kern: ... to here. + * lib: Moved ... + * grub-core/lib: ... to here. + * loader: Moved ... + * grub-core/loader: ... to here. + * mmap: Moved ... + * grub-core/mmap: ... to here. + * normal: Moved ... + * grub-core/normal: ... to here. + * partmap: Moved ... + * grub-core/partmap: ... to here. + * parttool: Moved ... + * grub-core/parttool: ... to here. + * script: Moved ... + * grub-core/script: ... to here. + * term: Moved ... + * grub-core/term: ... to here + * tests/example_functional_test.c: Moved ... + * grub-core/tests/example_functional_test.c: ... to here. + * tests/lib/functional_test.c: Moved ... + * grub-core/tests/lib/functional_test.c: ... to here. + * tests/lib/test.c: Moved ... + * grub-core/tests/lib/test.c: ... to here. + * video: Moved ... + * grub-core/video: ... to here. + +2010-08-23 BVK Chaitanya + + Replace --enable-grub-emu-modules with grub-emu-lite. + + * kern/emu/cache.S: New file. Wrapper for $target_cpu specific + cache.S. + + * include/grub/emu/misc.h (grub_emu_init): New prototype. + * kern/emu/full.c: New file. For grub-emu specific initialization. + * kern/emu/lite.c: New file. For grub-emu-lite initialization. + * kern/emu/main.c: Call initialization function grub_emu_init. + + * Makefile.in: Include grub-emu-lite in install. + * commands/parttool.c: Use grub_no_autoload to differentiate + between grub-emu and grub-emu-lite. + * include/grub/misc.h: New variable grub_no_autoload. + + * conf/any-emu.rmk: New rules for grub-emu-lite. + * configure.ac: Remove --enable-grub-emu-modules. + * genmk.rb: Cleanup unnecessary rules. + * include/grub/dl.h: Remove GRUB_NO_MODULES macro. + + * normal/main.c: Don't load list files on grub-emu-lite. + * util/misc.c (grub_arch_sync_caches): Removed. + +2010-08-23 Colin Watson + + * kern/mips/startup.S (grub_prefix): Update comment to refer to + grub-mkimage rather than grub-mkelfimage. + * kern/powerpc/ieee1275/startup.S (grub_prefix): Likewise. + +2010-08-22 Vladimir Serbinenko + + * term/at_keyboard.c (grub_at_keyboard_getkey_noblock): Don't discard + a key after CapsLock or NumLock. It's just a qemu bug. + +2010-08-21 Vladimir Serbinenko + + * include/grub/usb.h (grub_usb_device): Add 'data' field back. It's + needed by libusb wrapper. + +2010-08-21 Samuel Thibault + + * docs/grub.texi (GNU/Hurd): Document booting GNU/Hurd. + +2010-08-21 Vladimir Serbinenko + + * loader/multiboot.c (grub_cmd_module): Don't unzip module if + --nounzip is passed. + +2010-08-20 Vladimir Serbinenko + + USB hotunplugging and USB serial support. + + * bus/usb/ohci.c (grub_ohci_transfer): Fill *actual and respect timeout. + * bus/usb/uhci.c (grub_free_queue): Compute *actual. + (grub_uhci_transfer): Respect timeout and set *actual. + * bus/usb/usb.c (grub_usb_device_initialize): Correctly skip fields of + non-standard length. + (grub_usb_device_attach): Autoload modules. + (GRUB_MOD_INIT): Set grub_term_poll_usb. + (GRUB_MOD_FINI): Unset grub_term_poll_usb. + * bus/usb/usbhub.c (grub_usb_hub): Replace speed with devices. All + users updated. + (grub_usb_add_hub): Fill nports and children. + (attach_root_port): Receive hub instead of controller. + All users updated. Fill hub->devices. + (grub_usb_root_hub): Allocate hub->devices. + (detach_device): New function. + (poll_nonroot_hub): Fill children and detach devices. + * bus/usb/usbtrans.c (grub_usb_bulk_readwrite): Accept timeout and + actual arguments. All users updated. + (grub_usb_bulk_read_extended): New function. + * bus/usb/serial/common.c: New file. + * bus/usb/serial/ftdi.c: Likewise. + * bus/usb/serial/pl2303.c: Likewise. + * commands/terminal.c (handle_command): Support wildcard. + * commands/usbtest.c: Output "Unknown" instead of empty string. + * conf/any-emu.rmk (pkglib_MODULES): Add usbserial_common.mod. + (usbserial_common_mod_SOURCES): New variable. + (usbserial_common_mod_CFLAGS): Likewise. + (usbserial_common_mod_LDFLAGS): Likewise. + (pkglib_MODULES): Add usbserial_pl2303.mod. + (usbserial_pl2303_mod_SOURCES): New variable. + (usbserial_pl2303_mod_CFLAGS): Likewise. + (usbserial_pl2303_mod_LDFLAGS): Likewise. + (pkglib_MODULES): Add usbserial_ftdi.mod. + (usbserial_ftdi_mod_SOURCES): New variable. + (usbserial_ftdi_mod_CFLAGS): Likewise. + (usbserial_ftdi_mod_LDFLAGS): Likewise. + (pkglib_MODULES): Add serial.mod. + (serial_mod_SOURCES): New variable. + (serial_mod_CFLAGS): Likewise. + (serial_mod_LDFLAGS): Likewise. + * conf/i386-pc.rmk: Likewise. + * conf/mips-yeeloong.rmk: Likewise. + * conf/i386.rmk (serial_mod_SOURCES): Add term/ns8250.c. + * conf/mips-yeeloong.rmk (kernel_img_SOURCES): Likewise. + * disk/usbms.c (first_available_slot): New variable. + (grub_usbms_attach): Don't reuse free slots due to potential cache + problems. + * include/grub/serial.h: Moved to .. + * include/grub/ns8250.h: ...this. + * include/grub/serial.h: New file. + * include/grub/term.h (grub_term_poll_usb): New variable. + * include/grub/terminfo.h (grub_terminfo_input_state): Pass term to + readkey. All users updated. + (grub_terminfo_output_state): Pass term to put. + * include/grub/usb.h (GRUB_USB_REQTYPE): New enum. + (grub_usb_controller_dev): Add timeout and actual arguments to + transfer. All users updated. + (grub_usb_interface): New field detach_data. + (grub_usb_device): New fields children and nports. + (grub_usb_ep_type_t): New type. + (grub_usb_get_ep_type): New function. + (grub_usb_bulk_read_extended): Likewise. + * include/grub/usbdesc.h (grub_usb_desc): New type. + * include/grub/usbserial.h: New file. + * include/grub/usbtrans.h (grub_usb_transaction): New field preceding. + * kern/term.c (grub_term_poll_usb): New variable. + (grub_getkey): Call grub_term_poll_usb if set. + (grub_checkkey): Likewise. + (grub_getkeystatus): Likewise. + * term/serial.c: Moved controller-specific parts to ... + * term/ns8250.c: ... here. + * term/serial.c: Mostly rewritten. + * term/usb_keyboard.c: Reorganised to use GET_REPORT only on attaching + according to spec. + +2010-08-20 Robert Millan + + Make kFreeBSD code more generic to support ext2fs as root, ufs as + a separate module and maybe other interesting combinations. + + * util/grub.d/10_kfreebsd.in (load_kfreebsd_module): New function. + (kfreebsd_entry): Use load_kfreebsd_module() to load modules. + (kfreebsd_entry): Add generic filesystem module load routine. + Map GRUB `ext2' to kFreeBSD `ext2fs'. + +2010-08-20 Colin Watson + + * commands/i386/pc/sendkey.c (keysym_table): Rename "numlock" to + "numcenter" (I misunderstood the purpose of this entry). + * docs/grub.texi (sendkey): Likewise. + +2010-08-20 Colin Watson + + * commands/i386/pc/sendkey.c (options): Remove "keep" from all + status flag options; simply omitting the option is equivalent and + simpler. Rename "wait" to "pause". Rename "sysreq" to "sysrq". + (keysym_table): Rename "num5numlock" to "numlock". + (grub_cmd_sendkey): Reinitialise `andmask' and `ormask', so that we + can uniformly say that only the last of multiple `sendkey' + invocations has any effect. + * docs/grub.texi (sendkey): New section. + +2010-08-19 Colin Watson + + * commands/i386/pc/sendkey.c (options): Fix three typos. + +2010-08-19 Vladimir Serbinenko + + Implement sendkey support. + + * commands/i386/pc/sendkey.c: New file. + * conf/i386-pc.rmk (pkglib_MODULES): Add sendkey.mod. + (sendkey_mod_SOURCES): New variable. + (sendkey_mod_CFLAGS): Likewise. + (sendkey_mod_LDFLAGS): Likewise. + +2010-08-18 Colin Watson + + * configure.ac: Move AM_INIT_AUTOMAKE after AC_CANONICAL_TARGET to + fix warnings from Autoconf. + +2010-08-18 Colin Watson + + * acinclude.m4 (grub_ASM_USCORE): Use a more accurate grep pattern, + to avoid false positives with some assemblers that output things + like "someprefix_func" as part of their output. + +2010-08-15 Robert Millan + + * kern/emu/misc.c (grub_get_libzfs_handle): Handle libzfs_init() + errors. + * kern/emu/getroot.c (find_root_device_from_libzfs): Handle + grub_get_libzfs_handle() errors. + +2010-08-14 Robert Millan + + * kern/emu/misc.c (grub_find_zpool_from_dir): Abort function if + filesystem is not ZFS. + +2010-08-12 BVK Chaitanya + + Fix for misspelled color names defaulting to black/black (bug + reported by Doug Nazar) + + * include/grub/normal.h (grub_parse_color_name_pair): Add return + status to prototype. + * normal/color.c (grub_parse_color_name_pair): Return failure + status. + (grub_env_write_color_normal): Ignore bad color names. + (grub_env_write_color_highlight): Likewise. + * normal/main.c (GRUB_MOD_INIT): Set default color names. + +2010-08-12 BVK Chaitanya + + "shift" command support to GRUB script. + + * include/grub/script_sh.h (grub_script_shift): New prototype. + * script/execute.c (grub_script_shift): New function. + * script/main.c (grub_script_init): Register shift command. + (grub_script_fini): Unregister shift command. + * util/grub-script-check.c (grub_script_cmd_shift): New function. + + * tests/grub_script_shift.in: New testcase. + * conf/tests.rmk: Rules for new testcase. + +2010-08-12 BVK Chaitanya + + "continue" command support to GRUB script. + + * script/execute.c (grub_script_execute_cmdwhile): Continue support. + (grub_script_break): Continue support. + * script/main.c (grub_script_init): Register continue command. + (grub_script_fini): Unregister continue command. + + * tests/grub_script_continue.in: New testcase. + * conf/tests.rmk: Rules for new testcase. + +2010-08-12 BVK Chaitanya + + "break" command support to GRUB script. + + * conf/common.rmk: Rule updates to grub-script-check. + * include/grub/misc.h (grub_min): New function. + * include/grub/script_sh.h (grub_script_init): New prototype. + (grub_script_fini): New prototype. + (grub_script_break): New prototype. + * script/main.c (grub_script_init): New function. + (grub_script_fini): New function. + * script/execute.c (grub_script_break): New function. + * normal/main.c: Calls to grub_script_{init,fini}. + * util/grub-script-check.c (grub_script_break): New function. + + * tests/grub_script_break.in: New testcase. + * conf/tests.rmk: Rules for new test case. + +2010-08-12 BVK Chaitanya + + Function parameters support to GRUB script. + + * script/yylex.l (VARIABLE): Regular expression update. + * script/function.c (grub_script_function_call): Moved ... + * script/execute.c (grub_script_function_call): ... to here. + (grub_script_execute_arglist_to_argv): Removed. + (grub_script_arglist_to_argv): New function. + * script/argv.c: New file. + (grub_script_argv_free): New function. + (grub_script_argv_next): Likewise. + (grub_script_argv_append): Likewise. + (grub_script_argv_split_append): Likewise. + * include/grub/script_sh.h (grub_script_argv): New struct. + (grub_script_argv_free): New function. + (grub_script_argv_next): Likewise. + (grub_script_argv_append): Likewise. + (grub_script_argv_split_append): Likewise. + + * conf/common.rmk (normal.mod): New source script/argv.c. + + * tests/grub_script_echo1.in: More tests. + * tests/grub_script_vars1.in: Likewise. + * tests/grub_script_functions.in: New test case. + * conf/tests.rmk: Rules for new testcase. + +2010-08-12 BVK Chaitanya + + Remove grub_script_cmdblock struct. + + * include/grub/script_sh.h: Remove grub_script_cmdblock. + * script/parser.y: Likewise. + * script/execute.c: Rename cmdblock suffix to cmdlist. + * script/script.c: Likewise. + * util/grub-script-check.c: Likewise. + +2010-08-11 Yves Blusseau + + * .bzrignore: add grub-macho2img + +2010-08-11 Vladimir Serbinenko + + * kern/i386/qemu/init.c (grub_qemu_init_cirrus): Fix compilation error. + +2010-08-11 Vladimir Serbinenko + + Remove the dump of sm712 initialisation sequence. + + * include/grub/pci.h (GRUB_PCI_CLASS_SUBCLASS_VGA): New const. + * include/grub/vga.h (GRUB_VGA_IO_ARX_READ): New register. + (GRUB_VGA_IO_MISC_WRITE): Likewise. + (GRUB_VGA_CR_*): Added many registers. + (GRUB_VGA_SR_*): Likewise. + (GRUB_VGA_GR_*): Likewise. + (grub_vga_write_arx): New function. + (grub_video_hw_config): New struct. + (grub_vga_set_geometry): New function. + * kern/i386/qemu/init.c (load_palette): Use grub_vga_write_arx and + GRUB_PCI_CLASS_SUBCLASS_VGA. + * video/cirrus.c (grub_video_cirrus_setup): Use grub_vga_set_geometry. + * video/sm712.c (grub_sm712_write_reg): New function + (grub_sm712_read_reg): Likewise. + (grub_sm712_sr_write): Likewise. + (grub_sm712_gr_write): Likewise. + (grub_sm712_cr_write): Likewise. + (grub_sm712_write_arx): Likewise. + (grub_sm712_cr_shadow_write): Likewise. + (grub_sm712_write_dda_lookup): Likewise. + (grub_video_sm712_setup): Initialise the video rather then + blindly replay the dump. + (main) [TEST]: Add a routine to be able to compile as standalone for + tests. + * video/sm712_init.c (sm712_init): Removed. + (sm712_sr_seq1): New array. + (sm712_sr_seq2): Likewise. + +2010-08-10 Vladimir Serbinenko + + * include/grub/vga.h: Add missing grub/pci.h include. + +2010-08-10 Yves Blusseau + + * util/grub-macho2img.c (main): fix typo + +2010-08-10 Vladimir Serbinenko + + * include/grub/vga.h (grub_vga_gr_write): Add GRUB_MACHINE_PCI_IO_BASE. + (grub_vga_gr_read): Likewise. + (grub_vga_cr_write): Likewise. + (grub_vga_cr_read): Likewise. + (grub_vga_sr_write): Likewise. + (grub_vga_sr_read): Likewise. + (grub_vga_palette_read): Likewise. + (grub_vga_palette_write): Likewise. + * video/sm712.c (GRUB_SM712_REG_BASE): New definition. + (grub_sm712_sr_read): New function. + (grub_video_sm712_setup): Use grub_vga_sr_write and grub_sm712_sr_read. + * video/sm712_init.c (sm712_init): Substract GRUB_MACHINE_PCI_IO_BASE. + +2010-08-09 Robert Millan + + * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Filter + out unused variables on non-ZFS build. + +2010-08-08 Robert Millan + + Fix path generation for sub-filesystems in ZFS. + + * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Add + missing slash. + +2010-08-08 Robert Millan + + * util/grub-fstest.c (read_file, cmd_cmp): Improve error message. + +2010-08-08 Robert Millan + + * util/grub.d/10_kfreebsd.in: When files required for ZFS do not + exist, issue a proper error message (rely on `ls' for translated + strings). + +2010-08-08 Robert Millan + + Fix grub-probe invocation. + + * util/grub.d/10_kfreebsd.in: s/label/fs_label/g. + +2010-08-04 Robert Millan + + * configure.ac: Remove checks for getfsstat() and getmntany(). + Add checks for `' and `'. + * kern/emu/misc.c [HAVE_GETMNTANY]: Remove `'. + [HAVE_SYS_PARAM_H]: Include `'. + [HAVE_SYS_MOUNT_H]: Include `'. + [HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_mount_point_from_dir): Remove + function. + (grub_find_zpool_from_dir): Use statfs() instead of indirect matching + via find_mount_point_from_dir() and getfsstat() / getmntany(). + +2010-08-04 Robert Millan + + * include/grub/emu/misc.h (grub_find_mount_point_from_dir) + (grub_find_zpool_from_mount_point): Merge into ... + (grub_find_zpool_from_dir): ... this. + * kern/emu/misc.c: Likewise. + + * kern/emu/misc.c + (grub_make_system_path_relative_to_its_root): Replace + grub_find_mount_point_from_dir() / grub_find_zpool_from_mount_point() + with grub_find_zpool_from_dir(). + * kern/emu/getroot.c (find_root_device_from_libzfs): Likewise. + 2010-08-04 Robert Millan Support OpenSolaris in ZFS device resolution. diff --git a/INSTALL b/INSTALL index 44a442253..e325fa2b2 100644 --- a/INSTALL +++ b/INSTALL @@ -21,7 +21,7 @@ configuring the GRUB. On GNU/Linux, you also need: -* libdevmapper (recommended) +* libdevmapper 1.02.34 or later (recommended) To build grub-emu, you need: @@ -37,10 +37,10 @@ To build GRUB's graphical terminal (gfxterm), you need: If you use a development snapshot or want to hack on GRUB you may need the following. -* Ruby 1.6 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: diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..60e041a8d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,324 @@ +AUTOMAKE_OPTIONS = subdir-objects + +DEPDIR = .deps-util +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 + +AM_CFLAGS = $(HOST_CFLAGS) +AM_LDFLAGS = $(HOST_LDFLAGS) +AM_CPPFLAGS = $(HOST_CPPFLAGS) $(CPPFLAGS_DEFAULT) +AM_CCASFLAGS = $(HOST_CCASFLAGS) $(CCASFLAGS_DEFAULT) + +ACLOCAL_AMFLAGS = -I m4 + +CFLAGS_PROGRAM += $(CFLAGS_GNULIB) +LDFLAGS_PROGRAM += $(LDFLAGS_GNULIB) +CPPFLAGS_PROGRAM += $(CPPFLAGS_GNULIB) +CCASFLAGS_PROGRAM += $(CCASFLAGS_GNULIB) + +include $(srcdir)/Makefile.util.am + +# XXX Use Automake's LEX & YACC support +grub_script.tab.h: $(top_srcdir)/grub-core/script/parser.y + $(YACC) -d -p grub_script_yy -b grub_script $(top_srcdir)/grub-core/script/parser.y +grub_script.tab.c: grub_script.tab.h +CLEANFILES += grub_script.tab.c grub_script.tab.h + +# For the lexer. +grub_script.yy.h: $(top_srcdir)/grub-core/script/yylex.l + $(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $(top_srcdir)/grub-core/script/yylex.l +grub_script.yy.c: grub_script.yy.h +CLEANFILES += grub_script.yy.c grub_script.yy.h + +# For libgrub.a +libgrub.pp: grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES) + $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrubmods_a_CPPFLAGS) $(libgrubkern_a_CPPFLAGS) $(CPPFLAGS) \ + -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) +CLEANFILES += libgrub.pp + +libgrub_a_init.lst: libgrub.pp + cat $< | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) +CLEANFILES += libgrub_a_init.lst + +libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh + sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) +CLEANFILES += libgrub_a_init.c + +# For grub-fstest +grub_fstest.pp: $(grub_fstest_SOURCES) + $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \ + -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest.pp + +grub_fstest_init.lst: libgrub.pp grub_fstest.pp + cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest_init.lst + +grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh + sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest_init.c + +if COND_GRUB_MKFONT +if COND_HAVE_FONT_SOURCE +grubdata_DATA = unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h +endif +endif + +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) grub-mkfont + $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) +CLEANFILES += ascii.pf2 + +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.bitmaps: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) +CLEANFILES += ascii.bitmaps + +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 +platform_HEADERS = config.h + +pkglib_DATA += grub-mkconfig_lib +pkglib_DATA += update-grub_lib + + +if COND_i386_coreboot +BOOTTARGET=coreboot +QEMU32=qemu-system-i386 +endif + +if COND_i386_multiboot +BOOTTARGET=cd +QEMU32=qemu-system-i386 +endif + +if COND_i386_ieee1275 +BOOTTARGET=cd +QEMU32=qemu-system-i386 +endif + +if COND_i386_qemu +BOOTTARGET=qemu +QEMU32=qemu-system-i386 +endif + +if COND_i386_pc +BOOTTARGET=cd +QEMU32=qemu-system-i386 +endif + +if COND_i386_efi +QEMU32=qemu-system-i386 +BOOTTARGET=cd +endif + +if COND_x86_64_efi +QEMU32=qemu-system-x86_64 +BOOTTARGET=cd +endif + +linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S + $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + +linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S + $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + +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,-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,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include + +kfreebsd.aout: kfreebsd.elf + $(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id + +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,-N -Wl,-Ttext,0x7c00 -m32 + +pc-chainloader.bin: pc-chainloader.elf + $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@; + +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,-N -Wl,-Ttext,0 -m32 + +ntldr.bin: ntldr.elf + $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@; + +multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S + $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1 + +kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S + $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ + +kfreebsd.init.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 + $(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 + $(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 + $(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 + $(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + +linux-initramfs.i386: linux.init.i386 Makefile + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + +linux-initramfs.x86_64: linux.init.x86_64 Makefile + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + +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 + +knetbsd.image.i386: knetbsd.init.i386 $(srcdir)/grub-core/tests/boot/kbsd.spec.txt + 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 + +kopenbsd.image.i386: kopenbsd.init.i386 $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt + 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 $@ + +kopenbsd.image.x86_64: kopenbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@ + +knetbsd.miniroot-image.i386.img: knetbsd.image.i386 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 + $(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@ + +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 + +knetbsd.image.x86_64: knetbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kbsd.spec.txt + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR + +knetbsd.miniroot-image.x86_64.img: knetbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 + $(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@ + +CLEANFILES += linux.init.i386 kfreebsd.init.i386 linux.init.x86_64 linux-initramfs.i386 linux-initramfs.x86_64 + +kfreebsd-mfsroot.i386.gz: kfreebsd-mfsroot.i386.img + gzip < $< > $@ + +bootcheck-kfreebsd-i386: kfreebsd-mfsroot.i386.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.i386 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +kfreebsd-mfsroot.x86_64.gz: kfreebsd-mfsroot.x86_64.img + gzip < $< > $@ + +bootcheck-kfreebsd-x86_64: kfreebsd-mfsroot.x86_64.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +knetbsd.miniroot-image.i386.gz: knetbsd.miniroot-image.i386.img + gzip < $< > $@ + +bootcheck-knetbsd-i386: knetbsd.miniroot-image.i386.gz $(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +knetbsd.miniroot-image.x86_64.gz: knetbsd.miniroot-image.x86_64.img + gzip < $< > $@ + +bootcheck-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --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 + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --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-linux16-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-multiboot: multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-multiboot2: multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell + timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + +BOOTCHECKS= + +if COND_i386_pc +#pc chainloader by definition is only for i386-pc +BOOTCHECKS += bootcheck-pc-chainloader +#ntldr and bootmgr require BIOS. +BOOTCHECKS += bootcheck-ntldr +#legacy protocol makes early BIOS calls. +BOOTCHECKS += bootcheck-linux16-i386 bootcheck-linux16-x86_64 +# Crashes early on non-BIOS +BOOTCHECKS += bootcheck-knetbsd-i386 +endif + +if !COND_i386_coreboot +# Crashes because memory at 0-0x1000 is occupied +BOOTCHECKS += bootcheck-knetbsd-x86_64 + +# Likewise and require ACPI. +if !COND_i386_multiboot +if !COND_i386_qemu +BOOTCHECKS += bootcheck-kfreebsd-x86_64 +BOOTCHECKS += bootcheck-kfreebsd-i386 +endif +endif +endif + +BOOTCHECKS += bootcheck-kfreebsd-aout + +BOOTCHECKS += bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 + +BOOTCHECKS += bootcheck-multiboot bootcheck-multiboot2 + +BOOTCHECKS += bootcheck-linux-i386 bootcheck-linux-x86_64 + + +.PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64 \ + bootcheck-kfreebsd-i386 bootcheck-kfreebsd-x86_64 \ + bootcheck-knetbsd-i386 bootcheck-knetbsd-x86_64 + +# Randomly generated +SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d +# tianocore cd access is very slow +BOOTCHECK_TIMEOUT=180 + +bootcheck: $(BOOTCHECKS) diff --git a/Makefile.in b/Makefile.in deleted file mode 100644 index 39061be4d..000000000 --- a/Makefile.in +++ /dev/null @@ -1,575 +0,0 @@ -# -*- makefile -*- -# -# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. -# -# This Makefile.in is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -### The configure script will replace these variables. - -SHELL = /bin/sh - -@SET_MAKE@ - -transform = @program_transform_name@ - -srcdir = @srcdir@ -builddir = @builddir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datarootdir = @datarootdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -localedir = @localedir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -pkgdatadir = $(datadir)/`echo @PACKAGE_TARNAME@ | sed '$(transform)'` -pkglibdir = $(libdir)/`echo @PACKAGE_TARNAME@/$(target_cpu)-$(platform) | sed '$(transform)'` - -# Internationalization library. -LIBINTL = @LIBINTL@ -TARGET_NO_MODULES = @TARGET_NO_MODULES@ - -# Util library. -LIBUTIL = @LIBUTIL@ - -XGETTEXT = @XGETTEXT@ -MSGMERGE = @MSGMERGE@ -MSGFMT = @MSGFMT@ - -ifeq (@USE_NLS@,yes) -LINGUAS = $(shell for i in $(srcdir)/po/*.po ; do \ - if test -e $$i ; then echo $$i ; fi ; \ - done | sed -e "s,.*/po/\(.*\)\.po$$,\1,") -else -LINGUAS = -endif - -PACKAGE = @PACKAGE@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ - -host_os = @host_os@ -host_kernel = @host_kernel@ -host_cpu = @host_cpu@ - -target_cpu = @target_cpu@ -platform = @platform@ - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -MKDIR_P = @MKDIR_P@ - -mkinstalldirs = $(srcdir)/mkinstalldirs - -LIBS = @LIBS@ $(LIBINTL) $(LIBUTIL) - -CC = @CC@ -CFLAGS = @CFLAGS@ -POSIX_CFLAGS = -I$(srcdir)/lib/posix_wrap -GNULIB_UTIL_CFLAGS = -Wno-undef -Wno-sign-compare -Wno-unused -D_GL_UNUSED="__attribute__ ((unused))" -I$(srcdir)/gnulib -GNULIB_CFLAGS = $(GNULIB_UTIL_CFLAGS) $(POSIX_CFLAGS) -ASFLAGS = @ASFLAGS@ -LDFLAGS = @LDFLAGS@ $(LIBS) -CPPFLAGS = @CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/gnulib -I$(srcdir)/include -Wall -W \ - -DGRUB_PKGLIBROOTDIR=\"$(libdir)/`echo @PACKAGE_TARNAME@ | sed '$(transform)'`\" -DLOCALEDIR=\"$(localedir)\" -TARGET_CC = @TARGET_CC@ -TARGET_CFLAGS = -ffreestanding @TARGET_CFLAGS@ -TARGET_ASFLAGS = -nostdinc -fno-builtin @TARGET_ASFLAGS@ -TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@ -TARGET_APPLE_CC = @TARGET_APPLE_CC@ -OBJCONV = @OBJCONV@ -TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I$(srcdir)/include -I$(builddir) -I$(builddir)/include \ - -Wall -W -TARGET_LDFLAGS = -nostdlib -static-libgcc @TARGET_LDFLAGS@ -TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@ -TARGET_IMG_LDFLAGS = -nostdlib @TARGET_IMG_LDFLAGS@ -TARGET_IMG_CFLAGS = @TARGET_IMG_CFLAGS@ -TARGET_OBJ2ELF = @TARGET_OBJ2ELF@ -kernel_img_LDFLAGS = -lgcc -EXEEXT = @EXEEXT@ -OBJCOPY = @OBJCOPY@ -STRIP = @STRIP@ -NM = @NM@ -RUBY = @RUBY@ -MAKEINFO = @MAKEINFO@ -ifeq (, $(MAKEINFO)) -MAKEINFO = true -endif -HELP2MAN = @HELP2MAN@ -ifeq (, $(HELP2MAN)) -HELP2MAN = true -else -HELP2MAN := LANG=C $(HELP2MAN) --no-info --source=FSF -endif -AWK = @AWK@ -LIBCURSES = @LIBCURSES@ -LIBUSB = @LIBUSB@ -LIBSDL = @LIBSDL@ -LIBPCIACCESS = @LIBPCIACCESS@ -LEX = @LEX@ -YACC = @YACC@ -FONT_SOURCE = @FONT_SOURCE@ - -# Options. -enable_grub_emu_usb = @enable_grub_emu_usb@ -enable_grub_emu_sdl = @enable_grub_emu_sdl@ -enable_grub_emu_pci = @enable_grub_emu_pci@ -enable_grub_fstest = @enable_grub_fstest@ -enable_grub_pe2elf = @enable_grub_pe2elf@ -enable_grub_mkfont = @enable_grub_mkfont@ -freetype_cflags = @freetype_cflags@ -freetype_libs = @freetype_libs@ -enable_efiemu = @enable_efiemu@ - -### General variables. - -RMKFILES = $(wildcard $(srcdir)/conf/*.rmk) - -MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES)) - -PKGLIB = $(pkglib_IMAGES) $(pkglib_MODULES) $(pkglib_PROGRAMS) \ - $(pkglib_DATA) $(pkglib_BUILDDIR) -PKGDATA = $(pkgdata_DATA) -PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES) -SCRIPTS = $(bin_SCRIPTS) $(sbin_SCRIPTS) $(grub-mkconfig_SCRIPTS) \ - $(lib_SCRIPTS) -INFOS = $(info_INFOS) - -CLEANFILES = -MOSTLYCLEANFILES = -DISTCLEANFILES = config.status config.cache config.log config.h \ - Makefile stamp-h stamp-h1 include/grub/cpu include/grub/machine \ - gensymlist.sh genkernsyms.sh build_env.mk \ - docs/grub.info docs/version.texi docs/stamp-vti - -MAINTAINER_CLEANFILES = $(srcdir)/configure $(srcdir)/aclocal.m4 \ - $(MKFILES) $(srcdir)/config.guess \ - $(srcdir)/config.sub $(srcdir)/install-sh $(srcdir)/missing \ - $(srcdir)/DISTLIST $(srcdir)/config.h.in $(srcdir)/stamp-h.in \ - $(srcdir)/unidata.c \ - $(INFOS) - -# The default target. -all: all-local - -### Include an arch-specific Makefile. -$(addprefix $(srcdir)/,$(MKFILES)): %.mk: %.rmk genmk.rb - if test "x$(RUBY)" = x; then \ - touch $@; \ - else \ - $(RUBY) $(srcdir)/genmk.rb < $< > $@; \ - fi - -ifeq ($(platform), emu) -include $(srcdir)/conf/any-emu.mk -else -include $(srcdir)/conf/$(target_cpu)-$(platform).mk -# For tests. -include $(srcdir)/conf/tests.mk -# For external modules. --include $(wildcard $(GRUB_CONTRIB)/*/conf/common.mk) -endif - -ifeq ($(TARGET_NO_MODULES), yes) - TARGET_CFLAGS += -DGRUB_TARGET_NO_MODULES=1 - CFLAGS += -DGRUB_TARGET_NO_MODULES=1 -endif - -### General targets. - -CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo -ifneq ($(TARGET_NO_MODULES), yes) -pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst -endif -moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk - cat $(DEFSYMFILES) /dev/null \ - | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \ - || (rm -f $@; exit 1) - -command.lst: $(COMMANDFILES) - cat $^ /dev/null | sort > $@ - -fs.lst: $(FSFILES) - cat $^ /dev/null | sort > $@ - -partmap.lst: $(PARTMAPFILES) - cat $^ /dev/null | sort > $@ - -handler.lst: $(HANDLERFILES) - cat $^ /dev/null | sort > $@ - -terminal.lst: $(TERMINALFILES) - cat $^ /dev/null | sort > $@ - -parttool.lst: $(PARTTOOLFILES) - cat $^ /dev/null | sort | uniq > $@ - -video.lst: $(VIDEOFILES) - cat $^ /dev/null | sort | uniq > $@ - -crypto.lst: lib/libgcrypt-grub/cipher/crypto.lst - cp $^ $@ - -ifneq (true, $(MAKEINFO)) -info_INFOS += docs/grub.info -endif - -MOSTLYCLEANFILES += vti.tmp -MAINTAINER_CLEANFILES += docs/stamp-vti docs/version.texi -docs/version.texi: docs/stamp-vti -docs/stamp-vti: docs/grub.texi configure.ac - $(MKDIR_P) docs - (set `$(SHELL) $(srcdir)/docs/mdate-sh $<`; \ - echo "@set UPDATED $$1 $$2 $$3"; \ - echo "@set UPDATED-MONTH $$2 $$3"; \ - echo "@set EDITION $(PACKAGE_VERSION)"; \ - echo "@set VERSION $(PACKAGE_VERSION)") > vti.tmp - @cmp -s vti.tmp $(builddir)/docs/version.texi \ - || (echo "Updating $(builddir)/docs/version.texi"; \ - cp vti.tmp $(builddir)/docs/version.texi) - -@rm -f vti.tmp - @cp $(builddir)/docs/version.texi $@ - -docs/grub.info: docs/grub.texi docs/version.texi docs/fdl.texi - $(MKDIR_P) docs - $(MAKEINFO) -P $(builddir)/docs --no-split $< -o $@ - -ifeq (, $(FONT_SOURCE)) -else - -ifeq ($(enable_grub_mkfont),yes) - -pkgdata_DATA += unicode.pf2 ascii.pf2 ascii.h -CLEANFILES += ascii.bitmaps - -# Arrows and lines are needed to draw the menu, so we always include them -UNICODE_ARROWS=0x2190-0x2193 -UNICODE_LINES=0x2501-0x251B - -unicode.pf2: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) - -ascii.pf2: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) - -ascii.bitmaps: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) - -ascii.h: ascii.bitmaps grub-bin2h - $(builddir)/grub-bin2h ascii_bitmaps < $< > $@ - -widthspec.bin: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont --width-spec -o $@ $(FONT_SOURCE) - -widthspec.h: widthspec.bin grub-bin2h - $(builddir)/grub-bin2h widthspec < $< > $@ - -TARGET_CFLAGS += -DUSE_ASCII_FAILBACK=1 -DHAVE_UNIFONT_WIDTHSPEC=1 -endif -endif - -# Used for building modules externally -pkglib_BUILDDIR += build_env.mk -build_env.mk: Makefile - (\ - echo "TARGET_CC=$(TARGET_CC)" ; \ - echo "TARGET_CFLAGS=$(TARGET_CFLAGS)" ; \ - echo "TARGET_ASFLAGS=$(TARGET_ASFLAGS)" ; \ - echo "TARGET_CPPFLAGS=$(TARGET_CPPFLAGS) -I$(pkglibdir) -I$(includedir)" ; \ - echo "STRIP=$(STRIP)" ; \ - echo "OBJCONV=$(OBJCONV)" ; \ - echo "TARGET_MODULE_FORMAT=$(TARGET_MODULE_FORMAT)" ; \ - echo "TARGET_APPLE_CC=$(TARGET_APPLE_CC)" ; \ - echo "COMMON_ASFLAGS=$(COMMON_ASFLAGS)" ; \ - echo "COMMON_CFLAGS=$(COMMON_CFLAGS)" ; \ - echo "COMMON_LDFLAGS=$(COMMON_LDFLAGS)"\ - ) > $@ -pkglib_BUILDDIR += config.h grub_script.tab.h - -all-local: $(PROGRAMS) $(GRUB_EMU) $(PKGLIB) $(PKGDATA) $(SCRIPTS) $(INFOS) $(MKFILES) $(foreach lang, $(LINGUAS), po/$(lang).mo) - -install: install-local - -install-local: all - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(pkglibdir) - rm -f $(DESTDIR)$(pkglibdir)/* - @list='$(PKGLIB)'; \ - for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkglibdir)/$$dest; \ - done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) - @list='$(PKGDATA)'; \ - for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkgdatadir)/$$dest; \ - done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 - @list='$(bin_UTILITIES) $(GRUB_EMU)'; for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \ - PATH="$(builddir):$$PATH" $(HELP2MAN) --section=1 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man1/$$dest.1 $$file; \ - done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8 - @list='$(sbin_UTILITIES)'; for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \ - PATH="$(builddir):$$PATH" $(HELP2MAN) --section=8 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man8/$$dest.8 $$file; \ - done - @list='$(bin_SCRIPTS)'; for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \ - PATH="$(builddir):$$PATH" $(HELP2MAN) --section=1 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man1/$$dest.1 $$file; \ - done - @list='$(sbin_SCRIPTS)'; for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \ - PATH="$(builddir):$$PATH" $(HELP2MAN) --section=8 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man8/$$dest.8 $$file; \ - done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/grub.d - @list='$(grub-mkconfig_SCRIPTS)'; for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \ - done - @list='$(grub-mkconfig_DATA)'; for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \ - done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(libdir)/grub - @list='$(lib_SCRIPTS)'; \ - for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(libdir)/grub/$$dest; \ - done - @langs='$(LINGUAS)'; \ - for lang in $$langs; do \ - $(SHELL) $(mkinstalldirs) $(DESTDIR)/$(datadir)/locale/$$lang/LC_MESSAGES; \ - file="po/$$lang.mo"; \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)/$(datadir)/locale/$$lang/LC_MESSAGES/$(PACKAGE).mo; \ - done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(infodir) - @list='$(info_INFOS)'; \ - for file in $$list; do \ - if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(infodir); \ - if (install-info --version && \ - install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ - install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$dest" || :; \ - fi; \ - done - -install-strip: - $(MAKE) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" install - -uninstall: - @list='$(PKGLIB)'; \ - for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - rm -f $(DESTDIR)$(pkglibdir)/$$dest; \ - done - @list='$(PKGDATA)'; \ - for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - rm -f $(DESTDIR)$(pkgdatadir)/$$dest; \ - done - @list='$(bin_UTILITIES) $(bin_SCRIPTS) $(GRUB_EMU)'; for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - rm -f $(DESTDIR)$(bindir)/$$dest; \ - rm -f $(DESTDIR)$(mandir)/man1/$$dest.1; \ - done - @list='$(sbin_UTILITIES) $(sbin_SCRIPTS)'; for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - rm -f $(DESTDIR)$(sbindir)/$$dest; \ - rm -f $(DESTDIR)$(mandir)/man8/$$dest.8; \ - done - @list='$(grub-mkconfig_SCRIPTS) $(grub-mkconfig_DATA)'; for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ - rm -f $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \ - done - @list='$(lib_SCRIPTS)'; \ - for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - rm -f $(DESTDIR)$(libdir)/grub/$$dest; \ - done - @list='$(info_INFOS)'; \ - for file in $$list; do \ - dest="`echo $$file | sed 's,.*/,,'`"; \ - if (install-info --version && \ - install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ - if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$dest"; then \ - :; \ - else \ - test ! -f "$(DESTDIR)$(infodir)/$$dest" || exit 1; \ - fi; \ - fi; \ - rm -f $(DESTDIR)$(infodir)/$$dest; \ - done - -clean: $(CLEAN_IMAGE_TARGETS) $(CLEAN_MODULE_TARGETS) $(CLEAN_UTILITY_TARGETS) - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -mostlyclean: clean $(MOSTLYCLEAN_IMAGE_TARGETS) $(MOSTLYCLEAN_MODULE_TARGETS) $(MOSTLYCLEAN_UTILITY_TARGETS) - -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) - -distclean: mostlyclean - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -rm -rf $(srcdir)/autom4te.cache - -maintainer-clean: distclean - -test -z "$(MAINTAINER_CLEANFILES)" || rm -f $(MAINTAINER_CLEANFILES) - -rmdir $(srcdir)/lib/libgcrypt-grub/cipher - -rmdir $(srcdir)/lib/libgcrypt-grub - -info: - -dvi: - -distdir=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION) - -DISTLIST: gendistlist.sh - $(SHELL) $(srcdir)/gendistlist.sh > $(srcdir)/DISTLIST - -distdir: DISTLIST - -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) - $(SHELL) $(mkinstalldirs) $(distdir) - for i in `cat $(srcdir)/DISTLIST`; do \ - dir=`echo "$$i" | sed 's:/[^/]*$$::'`; \ - if test -d $(srcdir)/$$dir; then \ - $(SHELL) $(mkinstalldirs) $(distdir)/$$dir; \ - fi; \ - cp -p $(srcdir)/$$i $(distdir)/$$i || exit 1; \ - done - chmod -R a+r $(distdir) - -GZIP_ENV = --best - -dist: distdir - tar chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) - -distcheck: dist - -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) - GZIP=$(GZIP_ENV) gzip -cd $(distdir).tar.gz | tar xf - - chmod -R a-w $(distdir) - chmod a+w $(distdir) - mkdir $(distdir)/=build - mkdir $(distdir)/=inst - chmod a-w $(distdir) - dc_instdir=`CDPATH=: && cd $(distdir)/=inst && pwd` \ - && cd $(distdir)/=build \ - && $(SHELL) ../configure --srcdir=.. --prefix=$$dc_instdir \ - && $(MAKE) all dvi check install && $(MAKE) uninstall \ - && (test `find $$dc_instdir -type f -print | wc -l` -le 1 \ - || (echo "Error: files left after uninstall" 1>&2; \ - exit 1)) \ - && $(MAKE) dist && $(MAKE) distclean \ - && rm -f $(distdir).tar.gz \ - && (test `find . -type f -print | wc -l` -eq 0 \ - || (echo "Error: files left after distclean" 1>&2; \ - exit 1)) - -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir) - @echo "$(distdir).tar.gz is ready for distribution" | \ - sed 'h;s/./=/g;p;x;p;x' - -check: all $(UNIT_TESTS) $(FUNCTIONAL_TESTS) $(SCRIPTED_TESTS) - @list="$(UNIT_TESTS)"; \ - set -e; \ - for file in $$list; do \ - $(builddir)/$$file; \ - done - @list="$(FUNCTIONAL_TESTS)"; \ - set -e; \ - for file in $$list; do \ - mod=`basename $$file .mod`; \ - echo "insmod functional_test; insmod $$mod; functional_test" \ - | $(builddir)/grub-shell; \ - done - @list="$(SCRIPTED_TESTS)"; \ - set -e; \ - for file in $$list; do \ - $(builddir)/$$file; \ - done - -.SUFFIXES: -.SUFFIXES: .c .o .S .d - -# Regenerate configure and Makefile automatically. -$(srcdir)/aclocal.m4: configure.ac acinclude.m4 - cd $(srcdir) && aclocal - -$(srcdir)/configure: configure.ac aclocal.m4 - cd $(srcdir) && autoconf - -$(srcdir)/config.h.in: stamp-h.in -$(srcdir)/stamp-h.in: configure.ac aclocal.m4 - cd $(srcdir) && autoheader - echo timestamp > $(srcdir)/stamp-h.in - -config.h: stamp-h -stamp-h: config.h.in config.status - $(SHELL) ./config.status - -Makefile: Makefile.in config.status - $(SHELL) ./config.status - -config.status: configure - $(SHELL) ./config.status --recheck - -gensymlist.sh: gensymlist.sh.in config.status - $(SHELL) ./config.status - -genkernsyms.sh: genkernsyms.sh.in config.status - $(SHELL) ./config.status - -$(srcdir)/po/$(PACKAGE).pot: po/POTFILES po/POTFILES-shell - cd $(srcdir) && $(XGETTEXT) -ctranslate --from-code=utf-8 -o po/$(PACKAGE).pot -f po/POTFILES --keyword=_ --keyword=N_ - cd $(srcdir) && $(XGETTEXT) -ctranslate --from-code=utf-8 -o po/$(PACKAGE).pot -f po/POTFILES-shell -j --language=Shell - -$(foreach lang, $(LINGUAS), $(srcdir)/po/$(lang).po): po/$(PACKAGE).pot - $(MSGMERGE) -U $@ $^ - -po/%.mo: po/%.po - $(MKDIR_P) $$(dirname $@) - $(MSGFMT) -c --statistics -o $@ $^ - -.PHONY: all install install-strip uninstall clean mostlyclean distclean -.PHONY: maintainer-clean info dvi dist check - -# Prevent an overflow. -.NOEXPORT: - -.DELETE_ON_ERROR: diff --git a/Makefile.util.def b/Makefile.util.def new file mode 100644 index 000000000..94dfb1044 --- /dev/null +++ b/Makefile.util.def @@ -0,0 +1,624 @@ +AutoGen definitions Makefile.tpl; + +library = { + name = libgrubkern.a; + cflags = '$(CFLAGS_GNULIB)'; + 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/kern/emu/getroot.c; + common = grub-core/kern/emu/hostdisk.c; + common = grub-core/kern/emu/misc.c; + common = grub-core/kern/emu/mm.c; + common = grub-core/kern/env.c; + common = grub-core/kern/err.c; + common = grub-core/kern/file.c; + common = grub-core/kern/fs.c; + common = grub-core/kern/list.c; + common = grub-core/kern/misc.c; + common = grub-core/kern/partition.c; +}; + +library = { + name = libgrubmods.a; + cflags = '$(CFLAGS_GCRY)'; + cppflags = '$(CPPFLAGS_GCRY)'; + + common_nodist = grub_script.tab.c; + common_nodist = grub_script.yy.c; + common_nodist = libgrub_a_init.c; + common_nodist = grub_script.yy.h; + common_nodist = grub_script.tab.h; + + common = grub-core/commands/blocklist.c; + common = grub-core/commands/extcmd.c; + common = grub-core/commands/ls.c; + common = grub-core/disk/dmraid_nvidia.c; + common = grub-core/disk/loopback.c; + common = grub-core/disk/lvm.c; + common = grub-core/disk/mdraid_linux.c; + common = grub-core/disk/mdraid1x_linux.c; + common = grub-core/disk/raid5_recover.c; + common = grub-core/disk/raid6_recover.c; + common = grub-core/disk/raid.c; + common = grub-core/fs/affs.c; + common = grub-core/fs/afs_be.c; + common = grub-core/fs/afs.c; + common = grub-core/fs/befs_be.c; + common = grub-core/fs/befs.c; + common = grub-core/fs/btrfs.c; + common = grub-core/fs/cpio.c; + common = grub-core/fs/ext2.c; + common = grub-core/fs/fat.c; + common = grub-core/fs/fshelp.c; + common = grub-core/fs/hfs.c; + common = grub-core/fs/hfsplus.c; + common = grub-core/fs/iso9660.c; + common = grub-core/fs/jfs.c; + common = grub-core/fs/minix.c; + common = grub-core/fs/minix2.c; + common = grub-core/fs/nilfs2.c; + common = grub-core/fs/ntfs.c; + common = grub-core/fs/ntfscomp.c; + common = grub-core/fs/reiserfs.c; + common = grub-core/fs/sfs.c; + common = grub-core/fs/tar.c; + common = grub-core/fs/udf.c; + common = grub-core/fs/ufs2.c; + common = grub-core/fs/ufs.c; + common = grub-core/fs/xfs.c; + common = grub-core/lib/arg.c; + common = grub-core/lib/crypto.c; + common = grub-core/lib/envblk.c; + common = grub-core/lib/hexdump.c; + common = grub-core/lib/libgcrypt-grub/cipher/sha512.c; + common = grub-core/lib/libgcrypt-grub/cipher/crc.c; + common = grub-core/lib/LzFind.c; + common = grub-core/lib/LzmaEnc.c; + common = grub-core/lib/pbkdf2.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/gpt.c; + common = grub-core/partmap/msdos.c; + common = grub-core/partmap/sun.c; + common = grub-core/partmap/sunpc.c; + common = grub-core/partmap/bsdlabel.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; +}; + +program = { + name = grub-bin2h; + common = util/bin2h.c; + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; + mansection = 1; +}; + +program = { + name = grub-mkimage; + mansection = 1; + + common = util/grub-mkimage.c; + common = util/resolve.c; + extra_dist = util/grub-mkimagexx.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBLZMA)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; + cppflags = '-DGRUB_PKGLIBROOTDIR=\"$(pkglibrootdir)\"'; +}; + +program = { + name = grub-mkrelpath; + mansection = 1; + + common = util/grub-mkrelpath.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; +}; + +program = { + name = grub-script-check; + mansection = 1; + + common = util/grub-script-check.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; +}; + +program = { + name = grub-editenv; + mansection = 1; + + common = util/grub-editenv.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; +}; + +program = { + name = grub-mkpasswd-pbkdf2; + mansection = 1; + + common = util/grub-mkpasswd-pbkdf2.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; + cflags = '$(CFLAGS_GCRY)'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + +program = { + name = grub-macho2img; + mansection = 1; + common = util/grub-macho2img.c; + condition = COND_APPLE_CC; +}; + +program = { + name = grub-pe2elf; + mansection = 1; + common = util/grub-pe2elf.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL)'; + condition = COND_GRUB_PE2ELF; +}; + +program = { + name = grub-fstest; + mansection = 1; + common_nodist = grub_fstest_init.c; + common = util/grub-fstest.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + cflags = '$(CFLAGS_GCRY)'; + cppflags = '$(CPPFLAGS_GCRY)'; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; +}; + +program = { + name = grub-mkfont; + mansection = 1; + common = util/grub-mkfont.c; + common = grub-core/unidata.c; + + cflags = '$(freetype_cflags)'; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(freetype_libs)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; + condition = COND_GRUB_MKFONT; +}; + +program = { + name = grub-mkdevicemap; + installdir = sbin; + mansection = 8; + + common = util/grub-mkdevicemap.c; + common = util/deviceiter.c; + nosparc64 = util/devicemap.c; + + sparc64_ieee1275 = util/ieee1275/ofpath.c; + sparc64_ieee1275 = util/ieee1275/devicemap.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)'; +}; + +program = { + name = grub-probe; + installdir = sbin; + mansection = 8; + common = util/grub-probe.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)'; +}; + +program = { + name = grub-setup; + installdir = sbin; + mansection = 8; + common = util/grub-setup.c; + common = util/raid.c; + common = util/lvm.c; + common = grub-core/lib/reed_solomon.c; + + sparc64_ieee1275 = util/ieee1275/ofpath.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)'; + + enable = i386_pc; + enable = sparc64_ieee1275; +}; + +program = { + name = grub-ofpathname; + installdir = sbin; + ieee1275 = util/ieee1275/grub-ofpathname.c; + ieee1275 = util/ieee1275/ofpath.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)'; + + enable = sparc64_ieee1275; +}; + +program = { + name = grub-mklayout; + mansection = 1; + + common = util/grub-mklayout.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; +}; + +data = { + common = util/grub.d/README; + installdir = grubconf; +}; + +script = { + name = '00_header'; + common = util/grub.d/00_header.in; + installdir = grubconf; +}; + +script = { + name = '10_windows'; + common = util/grub.d/10_windows.in; + installdir = grubconf; + condition = COND_HOST_WINDOWS; +}; + +script = { + name = '10_hurd'; + common = util/grub.d/10_hurd.in; + installdir = grubconf; + condition = COND_HOST_HURD; +}; + +script = { + name = '10_kfreebsd'; + common = util/grub.d/10_kfreebsd.in; + installdir = grubconf; + condition = COND_HOST_KFREEBSD; +}; + +script = { + name = '10_netbsd'; + common = util/grub.d/10_netbsd.in; + installdir = grubconf; + condition = COND_HOST_NETBSD; +}; + +script = { + name = '10_linux'; + common = util/grub.d/10_linux.in; + installdir = grubconf; + condition = COND_HOST_LINUX; +}; + +script = { + name = '20_linux_xen'; + common = util/grub.d/20_linux_xen.in; + installdir = grubconf; + condition = COND_HOST_LINUX; +}; + +script = { + name = '30_os-prober'; + common = util/grub.d/30_os-prober.in; + installdir = grubconf; +}; + +script = { + name = '40_custom'; + common = util/grub.d/40_custom.in; + installdir = grubconf; +}; + +script = { + name = '41_custom'; + common = util/grub.d/41_custom.in; + installdir = grubconf; +}; + +script = { + mansection = 1; + name = grub-mkrescue; + x86 = util/grub-mkrescue.in; + powerpc_ieee1275 = util/powerpc/ieee1275/grub-mkrescue.in; + enable = i386_pc; + enable = x86_efi; + enable = i386_qemu; + enable = i386_multiboot; + enable = i386_coreboot; + enable = powerpc_ieee1275; +}; + +script = { + mansection = 8; + installdir = sbin; + name = grub-install; + + common = util/grub-install.in; + enable = noemu; +}; + +script = { + mansection = 8; + installdir = sbin; + name = grub-mknetdir; + + common = util/grub-mknetdir.in; +}; + +script = { + name = grub-mkconfig; + common = util/grub-mkconfig.in; + mansection = 8; + installdir = sbin; +}; + +script = { + name = grub-set-default; + common = util/grub-set-default.in; + mansection = 8; + installdir = sbin; +}; + +script = { + name = grub-reboot; + common = util/grub-reboot.in; + mansection = 8; + installdir = sbin; +}; + +script = { + name = grub-mkconfig_lib; + common = util/grub-mkconfig_lib.in; + installdir = noinst; +}; + +script = { + name = update-grub_lib; + common = util/update-grub_lib.in; + installdir = noinst; +}; + +script = { + name = grub-kbdcomp; + common = util/grub-kbdcomp.in; +}; + +script = { + name = grub-shell; + common = tests/util/grub-shell.in; + installdir = noinst; +}; + +script = { + name = grub-shell-tester; + common = tests/util/grub-shell-tester.in; + installdir = noinst; +}; + +script = { + testcase; + name = example_scripted_test; + common = tests/example_scripted_test.in; +}; + +script = { + testcase; + name = example_grub_script_test; + common = tests/example_grub_script_test.in; +}; + +script = { + testcase; + name = grub_script_echo1; + common = tests/grub_script_echo1.in; +}; + +script = { + testcase; + name = grub_script_echo_keywords; + common = tests/grub_script_echo_keywords.in; +}; + +script = { + testcase; + name = grub_script_vars1; + common = tests/grub_script_vars1.in; +}; + +script = { + testcase; + name = grub_script_for1; + common = tests/grub_script_for1.in; +}; + +script = { + testcase; + name = grub_script_while1; + common = tests/grub_script_while1.in; +}; + +script = { + testcase; + name = grub_script_if; + common = tests/grub_script_if.in; +}; + +script = { + testcase; + name = grub_script_blanklines; + common = tests/grub_script_blanklines.in; +}; + +script = { + testcase; + name = grub_script_final_semicolon; + common = tests/grub_script_final_semicolon.in; +}; + +script = { + testcase; + name = grub_script_dollar; + common = tests/grub_script_dollar.in; +}; + +script = { + testcase; + name = grub_script_comments; + common = tests/grub_script_comments.in; +}; + +script = { + testcase; + name = grub_script_functions; + common = tests/grub_script_functions.in; +}; + +script = { + testcase; + name = grub_script_break; + common = tests/grub_script_break.in; +}; + +script = { + testcase; + name = grub_script_continue; + common = tests/grub_script_continue.in; +}; + +script = { + testcase; + name = grub_script_shift; + common = tests/grub_script_shift.in; +}; + +script = { + testcase; + name = grub_script_blockarg; + common = tests/grub_script_blockarg.in; +}; + +script = { + testcase; + name = grub_script_setparams; + common = tests/grub_script_setparams.in; +}; + +script = { + testcase; + name = grub_script_return; + common = tests/grub_script_return.in; +}; + +script = { + testcase; + name = grub_cmd_regexp; + common = tests/grub_cmd_regexp.in; +}; + +script = { + testcase; + name = grub_script_expansion; + common = tests/grub_script_expansion.in; +}; + +script = { + testcase; + name = grub_script_not; + common = tests/grub_script_not.in; +}; + +script = { + testcase; + name = partmap_test; + common = tests/partmap_test.in; +}; + +script = { + testcase; + name = grub_cmd_echo; + common = tests/grub_cmd_echo.in; +}; + +program = { + testcase; + name = example_unit_test; + common = tests/example_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; + cflags = -Wno-format; + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBDEVMAPPER)'; +}; + +program = { + name = grub-menulst2cfg; + mansection = 1; + common = util/grub-menulst2cfg.c; + common = grub-core/lib/legacy_parse.c; + common = grub-core/lib/i386/pc/vesa_modes_table.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldflags = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; +}; diff --git a/NEWS b/NEWS index 1e3334f18..7fce921d6 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,142 @@ +New in 1.99: + +* Keyboard layouts support. + +* New `lsapm' command (i386-pc only). + +* Parser for GRUB Legacy configuration files. + +* Support RAID on virtio devices. + +* Remove deprecated `root' command. + +* New `euro.pf2' font which supports most European languages. + +* Avoid opening the same device twice on Open Firmware platforms. + +* Extend `vbeinfo' and `vbetest' commands to non-VBE graphics, as + `videoinfo' and `videotest'. + +* New `lsefisystab', `lssal', and `lsefimmap' commands on EFI platforms. + +* Support explicit user claim that a device is BIOS-visible. Devices + listed in device.map will be assumed to be readable using only BIOS + facilities, rather than anything more complex such as LVM or RAID. + +* New bash-completion script for GRUB utilities. + +* Use ACPI to shut down if possible. + +* New `lsacpi' command. + +* Basic btrfs support (detection and UUID). + +* New `--boot-directory' option to `grub-install', `grub-reboot', and + `grub-set-default', with clearer semantics than the previous + `--root-directory' option. + +* Rename CD-ROM device to "cd" on BIOS platforms. + +* Transparent decompression filters. + +* Simpler PXE image generation. New `grub-mknetdir' utility to generate + netboot directory trees. + +* New relocator. Allows for more kernel support and more + straightforward loader writing. + +* Handle USB pendrives exposed as floppies. + +* New Automake-based build system. + +* Add `sendkey' command (i386-pc only). + +* ZFS support in `grub-install' and `grub-mkconfig'. Note: complete + functionality requires external ZFS implementation (available from + grub-extras). + +* Support 1.x versions of mdadm metadata. + +* Fix corruption when reading Reiserfs directory entries. + +* Bidirectional text and diacritics support. + +* Skip LVM snapshots. + +* MIPS Yeeloong firmware port. + +* Change grub-mkdevicemap to emit /dev/disk/by-id/ names where possible + on GNU/Linux. + +* Add `grub-mkconfig' support for Xen with Linux. + +* Add `grub-mkconfig' support for initrd images on Fedora 13. + +* Support >3GiB and <16MiB RAM in i386-qemu. + +* Add support for Cirrus 5446 and Bochs video cards. + +* Load more appropriate video drivers automatically in `grub-mkconfig'. + +* USB improvements, including hotplugging/hotunplugging, hub support, + and USB serial support. + +* AMD Geode CS5536 support. + +* Extensive updates to the Texinfo documentation. + +* Add `grub-probe' support for the btrfs filesystem, permitting / to + reside on btrfs as long as /boot is on a filesystem natively supported + by GRUB. + +* Handle symbolic links under /dev/mapper on GNU/Linux. + +* Handle installation across multiple partition table types. + +* Add `cmostest' command (i386/x86_64 only). + +* Add support for DM-RAID disk devices on GNU/Linux. + +* Remove `grub-mkisofs'. `grub-mkrescue' now uses GNU xorriso to build + CD images. + +* `grub-mkrescue' support for EFI, coreboot, and QEMU platforms. + +* Unify `grub-mkimage', `grub-setup', and `grub-install' source code + across platforms. + +* Fix VGA (as opposed to VBE) video driver, formerly a terminal driver. + +* Add menu hotkey support. + +* Add support for the nilfs2 filesystem. + +* `grub-probe' and `grub-mkconfig' support for NetBSD. + +* Support setting a background image in `grub-mkconfig'. + +* Support multiple terminals in `grub-mkconfig'. + +* Regexp support. + +* MIPS multiboot2 support. + +* Multiboot2 tag support. + +* sunpc partition table support. + +* Add a number of new language features to GRUB script: `for', `while', + `until', `elif', function parameters, `break', `continue', `shift', + multi-line quoted strings, positional parameters with `setparams', + `return', filename wildcard expansion, and `!'. + +* Support nested partition tables. GRUB now prefers to name partitions + in the form `(hd0,msdos1,bsd1)' rather than `(hd0,1,a)'. + +* Speed up consecutive hostdisk operations on the same device. + +* Compile parts of `grub-emu' as modules. + New in 1.98 - 2010-03-06: * Multiboot on EFI support. diff --git a/acinclude.m4 b/acinclude.m4 index 72483b5d0..7c38155d4 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -38,6 +38,7 @@ dnl Written by Pavel Roskin. Based on grub_ASM_EXT_C written by dnl Erich Boleyn and modified by Yoshinori K. Okuji. AC_DEFUN([grub_ASM_USCORE], [AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_EGREP]) AC_MSG_CHECKING([if C symbols get an underscore after compilation]) AC_CACHE_VAL(grub_cv_asm_uscore, [cat > conftest.c <<\EOF @@ -56,19 +57,16 @@ else AC_MSG_ERROR([${CC-cc} failed to produce assembly code]) fi -if grep _func conftest.s >/dev/null 2>&1; then +if $EGREP '(^|[^_[:alnum]])_func' conftest.s >/dev/null 2>&1; then + HAVE_ASM_USCORE=1 grub_cv_asm_uscore=yes else + HAVE_ASM_USCORE=0 grub_cv_asm_uscore=no fi rm -f conftest*]) -if test "x$grub_cv_asm_uscore" = xyes; then - AC_DEFINE_UNQUOTED([HAVE_ASM_USCORE], $grub_cv_asm_uscore, - [Define if C symbols get an underscore after compilation]) -fi - AC_MSG_RESULT([$grub_cv_asm_uscore]) ]) @@ -93,7 +91,7 @@ else fi grub_cv_prog_objcopy_absolute=yes for link_addr in 0x2000 0x8000 0x7C00; do - if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC}$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 @@ -236,44 +234,12 @@ else grub_tmp_data32="data32;" fi -AC_DEFINE_UNQUOTED([ADDR32], $grub_tmp_addr32, - [Define it to \"addr32\" or \"addr32;\" to make GAS happy]) -AC_DEFINE_UNQUOTED([DATA32], $grub_tmp_data32, - [Define it to \"data32\" or \"data32;\" to make GAS happy]) +ADDR32=$grub_tmp_addr32 +DATA32=$grub_tmp_data32 AC_MSG_RESULT([$grub_cv_i386_asm_prefix_requirement])]) -dnl Older versions of GAS require that absolute indirect calls/jumps are -dnl not prefixed with `*', while later versions warn if not prefixed. -AC_DEFUN([grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING(dnl -[whether an absolute indirect call/jump must not be prefixed with an asterisk]) -AC_CACHE_VAL(grub_cv_i386_asm_absolute_without_asterisk, -[cat > conftest.s <<\EOF - lcall *(offset) -offset: - .long 0 - .word 0 -EOF - -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then - grub_cv_i386_asm_absolute_without_asterisk=no -else - grub_cv_i386_asm_absolute_without_asterisk=yes -fi - -rm -f conftest*]) - -if test "x$grub_cv_i386_asm_absolute_without_asterisk" = xyes; then - AC_DEFINE([ABSOLUTE_WITHOUT_ASTERISK], 1, - [Define it if GAS requires that absolute indirect calls/jumps are not prefixed with an asterisk]) -fi - -AC_MSG_RESULT([$grub_cv_i386_asm_absolute_without_asterisk])]) - - dnl Check what symbol is defined as a bss start symbol. dnl Written by Michael Hohmoth and Yoshinori K. Okuji. AC_DEFUN([grub_CHECK_BSS_START_SYMBOL], @@ -305,14 +271,12 @@ AC_CACHE_VAL(grub_cv_check_uscore_edata_symbol, AC_MSG_RESULT([$grub_cv_check_uscore_edata_symbol]) -AH_TEMPLATE([BSS_START_SYMBOL], [Define it to one of __bss_start, edata and _edata]) - if test "x$grub_cv_check_uscore_uscore_bss_start_symbol" = xyes; then - AC_DEFINE([BSS_START_SYMBOL], [__bss_start]) + BSS_START_SYMBOL=__bss_start elif test "x$grub_cv_check_edata_symbol" = xyes; then - AC_DEFINE([BSS_START_SYMBOL], [edata]) + BSS_START_SYMBOL=edata elif test "x$grub_cv_check_uscore_edata_symbol" = xyes; then - AC_DEFINE([BSS_START_SYMBOL], [_edata]) + BSS_START_SYMBOL=_edata else AC_MSG_ERROR([none of __bss_start, edata or _edata is defined]) fi @@ -340,12 +304,10 @@ AC_CACHE_VAL(grub_cv_check_uscore_end_symbol, AC_MSG_RESULT([$grub_cv_check_uscore_end_symbol]) -AH_TEMPLATE([END_SYMBOL], [Define it to either end or _end]) - if test "x$grub_cv_check_end_symbol" = xyes; then - AC_DEFINE([END_SYMBOL], [end]) + END_SYMBOL=end elif test "x$grub_cv_check_uscore_end_symbol" = xyes; then - AC_DEFINE([END_SYMBOL], [_end]) + END_SYMBOL=_end else AC_MSG_ERROR([neither end nor _end is defined]) fi @@ -368,10 +330,10 @@ else AC_MSG_ERROR([${CC-cc} failed to produce assembly code]) fi if grep __enable_execute_stack conftest.s >/dev/null 2>&1; then - AC_DEFINE([NEED_ENABLE_EXECUTE_STACK], 1, - [Define to 1 if GCC generates calls to __enable_execute_stack()]) + NEED_ENABLE_EXECUTE_STACK=1 AC_MSG_RESULT([yes]) else + NEED_ENABLE_EXECUTE_STACK=0 AC_MSG_RESULT([no]) fi rm -f conftest* diff --git a/autogen.sh b/autogen.sh index f9d55318f..96b1e33e2 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,25 +1,67 @@ -#! /bin/sh +#! /usr/bin/env bash set -e -aclocal -autoconf -autoheader +autogen --version >/dev/null || exit 1 -# FIXME: automake doesn't like that there's no Makefile.am -automake -a -c -f || true +echo "Importing unicode..." +python util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt unicode/ArabicShaping.txt grub-core/unidata.c -echo timestamp > stamp-h.in +echo "Importing libgcrypt..." +python util/import_gcry.py grub-core/lib/libgcrypt/ grub-core -python util/import_gcry.py lib/libgcrypt/ . +echo "Creating Makefile.tpl..." +python gentpl.py | sed -e '/^$/{N;/^\n$/D;}' > Makefile.tpl -python util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt unicode/ArabicShaping.txt unidata.c +echo "Running autogen..." -for rmk in conf/*.rmk ${GRUB_CONTRIB}/*/conf/*.rmk; do - if test -e $rmk ; then - ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'` +# Automake doesn't like including files from a path outside the project. +rm -f contrib grub-core/contrib +if [ "x${GRUB_CONTRIB}" != x ]; then + [ "${GRUB_CONTRIB}" = contrib ] || ln -s "${GRUB_CONTRIB}" contrib + [ "${GRUB_CONTRIB}" = grub-core/contrib ] || ln -s ../contrib grub-core/contrib +fi + +UTIL_DEFS=Makefile.util.def +CORE_DEFS='grub-core/Makefile.core.def grub-core/Makefile.gcry.def' + +for extra in contrib/*/Makefile.util.def; do + if test -e "$extra"; then + UTIL_DEFS="$UTIL_DEFS $extra" fi done -sh gendistlist.sh > DISTLIST +for extra in contrib/*/Makefile.core.def; do + if test -e "$extra"; then + CORE_DEFS="$CORE_DEFS $extra" + fi +done + +cat $UTIL_DEFS | autogen -T Makefile.tpl | sed -e '/^$/{N;/^\n$/D;}' > Makefile.util.am +cat $CORE_DEFS | autogen -T Makefile.tpl | sed -e '/^$/{N;/^\n$/D;}' > grub-core/Makefile.core.am + +for extra in contrib/*/Makefile.common; do + if test -e "$extra"; then + echo "include $extra" >> Makefile.util.am + echo "include $extra" >> grub-core/Makefile.core.am + fi +done + +for extra in contrib/*/Makefile.util.common; do + if test -e "$extra"; then + echo "include $extra" >> Makefile.util.am + fi +done + +for extra in contrib/*/Makefile.core.common; do + if test -e "$extra"; then + echo "include $extra" >> grub-core/Makefile.core.am + fi +done + +echo "Saving timestamps..." +echo timestamp > stamp-h.in + +echo "Running autoreconf..." +autoreconf -vi exit 0 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/config.rpath b/build-aux/config.rpath similarity index 81% rename from config.rpath rename to build-aux/config.rpath index 85c2f209b..c492a93b6 100755 --- a/config.rpath +++ b/build-aux/config.rpath @@ -2,7 +2,7 @@ # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # -# Copyright 1996-2008 Free Software Foundation, Inc. +# Copyright 1996-2006 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # @@ -47,7 +47,7 @@ for cc_temp in $CC""; do done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` -# Code taken from libtool.m4's _LT_COMPILER_PIC. +# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then @@ -64,7 +64,7 @@ else ;; esac ;; - mingw* | cygwin* | pw32* | os2* | cegcc*) + mingw* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' @@ -74,15 +74,9 @@ else ;; newsos6) ;; - linux* | k*bsd*-gnu) + linux*) case $cc_basename in - ecc*) - wl='-Wl,' - ;; - icc* | ifort*) - wl='-Wl,' - ;; - lf95*) + icc* | ecc*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) @@ -106,7 +100,7 @@ else osf3* | osf4* | osf5*) wl='-Wl,' ;; - rdos*) + sco3.2v5*) ;; solaris*) wl='-Wl,' @@ -114,14 +108,11 @@ else sunos4*) wl='-Qoption ld ' ;; - sysv4 | sysv4.2uw2* | sysv4.3*) + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) wl='-Wl,' ;; sysv4*MP*) ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - wl='-Wl,' - ;; unicos*) wl='-Wl,' ;; @@ -130,7 +121,7 @@ else esac fi -# Code taken from libtool.m4's _LT_LINKER_SHLIBS. +# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= @@ -138,7 +129,7 @@ hardcode_direct=no hardcode_minus_L=no case "$host_os" in - cygwin* | mingw* | pw32* | cegcc*) + 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++. @@ -164,7 +155,7 @@ if test "$with_gnu_ld" = yes; then # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in - aix[3-9]*) + aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no @@ -188,7 +179,7 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no fi ;; - cygwin* | mingw* | pw32* | cegcc*) + cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' @@ -198,11 +189,11 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no fi ;; - interix[3-9]*) + interix3*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; - gnu* | linux* | k*bsd*-gnu) + linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else @@ -260,7 +251,7 @@ else hardcode_direct=unsupported fi ;; - aix[4-9]*) + 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. @@ -270,7 +261,7 @@ else # 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].*|aix[5-9]*) + 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 @@ -289,7 +280,7 @@ else strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - : + hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported @@ -332,7 +323,7 @@ else ;; bsdi[45]*) ;; - cygwin* | mingw* | pw32* | cegcc*) + 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 @@ -368,7 +359,7 @@ else hardcode_direct=yes hardcode_minus_L=yes ;; - freebsd* | dragonfly*) + freebsd* | kfreebsd*-gnu | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; @@ -421,22 +412,18 @@ else hardcode_libdir_separator=: ;; openbsd*) - if test -f /usr/libexec/ld.so; then - 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 + 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 - ld_shlibs=no + 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*) @@ -484,7 +471,7 @@ else ld_shlibs=yes fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' @@ -500,52 +487,34 @@ else fi # Check dynamic linker characteristics -# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. -# Unlike libtool.m4, here we don't care about _all_ names of the library, but -# only about the one the linker finds when passed -lNAME. This is the last -# element of library_names_spec in libtool.m4, or possibly two of them if the -# linker has special search rules. -library_names_spec= # the last element of library_names_spec in libtool.m4 +# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. libname_spec='lib$name' case "$host_os" in aix3*) - library_names_spec='$libname.a' ;; - aix[4-9]*) - library_names_spec='$libname$shrext' + aix4* | aix5*) ;; amigaos*) - library_names_spec='$libname.a' ;; beos*) - library_names_spec='$libname$shrext' ;; bsdi[45]*) - library_names_spec='$libname$shrext' ;; - cygwin* | mingw* | pw32* | cegcc*) + cygwin* | mingw* | pw32*) shrext=.dll - library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib - library_names_spec='$libname$shrext' ;; dgux*) - library_names_spec='$libname$shrext' ;; freebsd1*) ;; + kfreebsd*-gnu) + ;; freebsd* | dragonfly*) - case "$host_os" in - freebsd[123]*) - library_names_spec='$libname$shrext$versuffix' ;; - *) - library_names_spec='$libname$shrext' ;; - esac ;; gnu*) - library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in @@ -559,13 +528,10 @@ case "$host_os" in shrext=.sl ;; esac - library_names_spec='$libname$shrext' ;; - interix[3-9]*) - library_names_spec='$libname$shrext' + interix3*) ;; irix5* | irix6* | nonstopux*) - library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= @@ -582,59 +548,41 @@ case "$host_os" in ;; linux*oldld* | linux*aout* | linux*coff*) ;; - linux* | k*bsd*-gnu) - library_names_spec='$libname$shrext' + linux*) ;; knetbsd*-gnu) - library_names_spec='$libname$shrext' ;; netbsd*) - library_names_spec='$libname$shrext' ;; newsos6) - library_names_spec='$libname$shrext' ;; nto-qnx*) - library_names_spec='$libname$shrext' ;; openbsd*) - library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll - library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) - library_names_spec='$libname$shrext' - ;; - rdos*) ;; solaris*) - library_names_spec='$libname$shrext' ;; sunos4*) - library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) - library_names_spec='$libname$shrext' ;; sysv4*MP*) - library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - library_names_spec='$libname$shrext' ;; uts4*) - library_names_spec='$libname$shrext' ;; 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_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` -escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` 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/bus/usb/usbhub.c b/bus/usb/usbhub.c deleted file mode 100644 index 6c14f4b8d..000000000 --- a/bus/usb/usbhub.c +++ /dev/null @@ -1,488 +0,0 @@ -/* usb.c - USB Hub Support. */ -/* - * 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 - -#define GRUB_USBHUB_MAX_DEVICES 128 - -/* USB Supports 127 devices, with device 0 as special case. */ -static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; - -struct grub_usb_hub -{ - struct grub_usb_hub *next; - grub_usb_controller_t controller; - int nports; - grub_usb_speed_t *speed; - grub_usb_device_t dev; -}; - -struct grub_usb_hub *hubs; - -/* 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) -{ - grub_usb_device_t dev; - int i; - grub_usb_err_t err; - - dev = grub_zalloc (sizeof (struct grub_usb_device)); - if (! dev) - return NULL; - - dev->controller = *controller; - dev->speed = speed; - - err = grub_usb_device_initialize (dev); - if (err) - { - grub_free (dev); - return NULL; - } - - /* Assign a new address to the device. */ - for (i = 1; i < GRUB_USBHUB_MAX_DEVICES; i++) - { - if (! grub_usb_devs[i]) - break; - } - if (i == GRUB_USBHUB_MAX_DEVICES) - { - grub_error (GRUB_ERR_IO, "can't assign address to USB device"); - for (i = 0; i < 8; i++) - grub_free (dev->config[i].descconf); - grub_free (dev); - return NULL; - } - - err = grub_usb_control_msg (dev, - (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_STANDARD - | GRUB_USB_REQTYPE_TARGET_DEV), - GRUB_USB_REQ_SET_ADDRESS, - i, 0, 0, NULL); - if (err) - { - for (i = 0; i < 8; i++) - grub_free (dev->config[i].descconf); - grub_free (dev); - return NULL; - } - - dev->addr = i; - dev->initialized = 1; - grub_usb_devs[i] = dev; - - /* Wait "recovery interval", spec. says 2ms */ - grub_millisleep (2); - - grub_usb_device_attach (dev); - - return dev; -} - - -static grub_err_t -grub_usb_add_hub (grub_usb_device_t dev) -{ - struct grub_usb_usb_hubdesc hubdesc; - grub_err_t err; - int i; - grub_uint64_t timeout; - grub_usb_device_t next_dev; - - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_DEV), - GRUB_USB_REQ_GET_DESCRIPTOR, - (GRUB_USB_DESCRIPTOR_HUB << 8) | 0, - 0, sizeof (hubdesc), (char *) &hubdesc); - if (err) - return err; - grub_dprintf ("usb", "Hub descriptor:\n\t\t len:%d, typ:0x%02x, cnt:%d, char:0x%02x, pwg:%d, curr:%d\n", - hubdesc.length, hubdesc.type, hubdesc.portcnt, - hubdesc.characteristics, hubdesc.pwdgood, - hubdesc.current); - - /* Activate the first configuration. Hubs should have only one conf. */ - grub_dprintf ("usb", "Hub set configuration\n"); - grub_usb_set_configuration (dev, 1); - - /* Power on all Hub ports. */ - for (i = 1; i <= hubdesc.portcnt; i++) - { - grub_dprintf ("usb", "Power on - port %d\n", i); - /* Power on the port and wait for possible device connect */ - err = 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_POWER, - i, 0, NULL); - /* Just ignore the device if some error happened */ - if (err) - continue; - } - /* Wait for port power-on */ - if (hubdesc.pwdgood >= 50) - grub_millisleep (hubdesc.pwdgood * 2); - else - grub_millisleep (100); - - /* Iterate over the Hub ports. */ - for (i = 1; i <= hubdesc.portcnt; i++) - { - grub_uint32_t status; - - /* 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 (status), (char *) &status); - /* Just ignore the device if the Hub does not report the - status. */ - if (err) - continue; - grub_dprintf ("usb", "Hub port %d status: 0x%02x\n", i, status); - - /* If connected, reset and enable the port. */ - if (status & GRUB_USB_HUB_STATUS_CONNECTED) - { - grub_usb_speed_t speed; - - /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else - { - if (status & GRUB_USB_HUB_STATUS_HIGHSPEED) - speed = GRUB_USB_SPEED_HIGH; - else - speed = GRUB_USB_SPEED_FULL; - } - - /* A device is actually connected to this port. - * Now do reset of port. */ - grub_dprintf ("usb", "Reset hub port - port %d\n", i); - err = 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); - /* If the Hub does not cooperate for this port, just skip - the port. */ - if (err) - continue; - - /* Wait for reset procedure done */ - timeout = grub_get_time_ms () + 1000; - do - { - /* 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 (status), (char *) &status); - } - while (!err && - !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) && - (grub_get_time_ms() < timeout) ); - if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) - continue; - - /* Wait a recovery time after reset, spec. says 10ms */ - grub_millisleep (10); - - /* Do reset of connection change bit */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_CONNECTED, - i, 0, 0); - /* Just ignore the device if the Hub reports some error */ - if (err) - continue; - grub_dprintf ("usb", "Hub port - cleared connection change\n"); - - /* Add the device and assign a device address to it. */ - grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i); - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); - if (! next_dev) - continue; - - /* If the device is a Hub, scan it for more devices. */ - if (next_dev->descdev.class == 0x09) - grub_usb_add_hub (next_dev); - } - } - - return GRUB_ERR_NONE; -} - -static void -attach_root_port (grub_usb_controller_t controller, int portno, - grub_usb_speed_t speed) -{ - grub_usb_device_t dev; - grub_err_t err; - - /* Disable the port. XXX: Why? */ - err = controller->dev->portstatus (controller, portno, 0); - if (err) - return; - - /* Enable the port. */ - err = controller->dev->portstatus (controller, portno, 1); - if (err) - return; - - /* Enable the port and create a device. */ - dev = grub_usb_hub_add_dev (controller, speed); - if (! dev) - return; - - /* If the device is a Hub, scan it for more devices. */ - if (dev->descdev.class == 0x09) - grub_usb_add_hub (dev); -} - -grub_usb_err_t -grub_usb_root_hub (grub_usb_controller_t controller) -{ - int i; - struct grub_usb_hub *hub; - int changed=0; - - hub = grub_malloc (sizeof (*hub)); - if (!hub) - return GRUB_USB_ERR_INTERNAL; - - hub->next = hubs; - hubs = hub; - hub->controller = grub_malloc (sizeof (*controller)); - if (!hub->controller) - { - grub_free (hub); - return GRUB_USB_ERR_INTERNAL; - } - - grub_memcpy (hub->controller, controller, sizeof (*controller)); - hub->dev = 0; - - /* Query the number of ports the root Hub has. */ - hub->nports = controller->dev->hubports (controller); - hub->speed = grub_malloc (sizeof (hub->speed[0]) * hub->nports); - if (!hub->speed) - { - grub_free (hub->controller); - grub_free (hub); - return GRUB_USB_ERR_INTERNAL; - } - - for (i = 0; i < hub->nports; i++) - { - hub->speed[i] = controller->dev->detect_dev (hub->controller, i, - &changed); - - if (hub->speed[i] != GRUB_USB_SPEED_NONE) - attach_root_port (hub->controller, i, hub->speed[i]); - } - - return GRUB_USB_ERR_NONE; -} - -static void -poll_nonroot_hub (grub_usb_device_t dev) -{ - struct grub_usb_usb_hubdesc hubdesc; - grub_err_t err; - int i; - grub_uint64_t timeout; - grub_usb_device_t next_dev; - - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_DEV), - GRUB_USB_REQ_GET_DESCRIPTOR, - (GRUB_USB_DESCRIPTOR_HUB << 8) | 0, - 0, sizeof (hubdesc), (char *) &hubdesc); - if (err) - return; - - /* Iterate over the Hub ports. */ - for (i = 1; i <= hubdesc.portcnt; i++) - { - grub_uint32_t status; - - /* 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 (status), (char *) &status); - /* Just ignore the device if the Hub does not report the - status. */ - if (err) - continue; - - /* Connected and status of connection changed ? */ - if ((status & GRUB_USB_HUB_STATUS_CONNECTED) - && (status & GRUB_USB_HUB_STATUS_C_CONNECTED)) - { - grub_usb_speed_t speed; - - /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else - { - if (status & GRUB_USB_HUB_STATUS_HIGHSPEED) - speed = GRUB_USB_SPEED_HIGH; - else - speed = GRUB_USB_SPEED_FULL; - } - - /* A device is actually connected to this port. - * Now do reset of port. */ - err = 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); - /* If the Hub does not cooperate for this port, just skip - the port. */ - if (err) - continue; - - /* Wait for reset procedure done */ - timeout = grub_get_time_ms () + 1000; - do - { - /* 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 (status), (char *) &status); - } - while (!err && - !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) && - (grub_get_time_ms() < timeout) ); - if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) - continue; - - /* Wait a recovery time after reset, spec. says 10ms */ - grub_millisleep (10); - - /* Do reset of connection change bit */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_CONNECTED, - i, 0, 0); - /* Just ignore the device if the Hub reports some error */ - if (err) - continue; - - /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); - if (! next_dev) - continue; - - /* If the device is a Hub, scan it for more devices. */ - if (next_dev->descdev.class == 0x09) - grub_usb_add_hub (next_dev); - } - } - - return; -} - -void -grub_usb_poll_devices (void) -{ - struct grub_usb_hub *hub; - int i; - - for (hub = hubs; hub; hub = hub->next) - { - int changed=0; - /* Do we have to recheck number of ports? */ - /* No, it should be never changed, it should be constant. */ - for (i = 0; i < hub->nports; i++) - { - grub_usb_speed_t speed; - - speed = hub->controller->dev->detect_dev (hub->controller, i, - &changed); - - if (speed != GRUB_USB_SPEED_NONE) - { - if (changed) - attach_root_port (hub->controller, i, speed); - } - - /* XXX: There should be also handling - * of disconnected devices. */ - - hub->speed[i] = speed; - } - } - - /* We should check changes of non-root hubs too. */ - for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) - { - grub_usb_device_t dev = grub_usb_devs[i]; - - if (dev && dev->descdev.class == 0x09) - { - poll_nonroot_hub (dev); - } - } - -} - -int -grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) -{ - int i; - - for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) - { - if (grub_usb_devs[i]) - { - if (hook (grub_usb_devs[i])) - return 1; - } - } - - return 0; -} diff --git a/commands/crc.c b/commands/crc.c deleted file mode 100644 index 1c1a690aa..000000000 --- a/commands/crc.c +++ /dev/null @@ -1,71 +0,0 @@ -/* crc.c - command to calculate the crc32 checksum of a file */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008,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 - -static grub_err_t -grub_cmd_crc (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) - -{ - grub_file_t file; - char buf[GRUB_DISK_SECTOR_SIZE]; - grub_ssize_t size; - grub_uint32_t crc; - - if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - - file = grub_file_open (args[0]); - if (! file) - return 0; - - crc = 0; - while ((size = grub_file_read (file, buf, sizeof (buf))) > 0) - crc = grub_getcrc32 (crc, buf, size); - - if (grub_errno) - goto fail; - - grub_printf ("%08x\n", crc); - - fail: - grub_file_close (file); - return 0; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(crc) -{ - cmd = grub_register_command ("crc", grub_cmd_crc, - N_("FILE"), - N_("Calculate the crc32 checksum of a file.")); -} - -GRUB_MOD_FINI(crc) -{ - grub_unregister_command (cmd); -} diff --git a/commands/i386/pc/vbeinfo.c b/commands/i386/pc/vbeinfo.c deleted file mode 100644 index c266bbfcb..000000000 --- a/commands/i386/pc/vbeinfo.c +++ /dev/null @@ -1,185 +0,0 @@ -/* vbeinfo.c - command to list compatible VBE video modes. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,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 - * 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 - -static void * -real2pm (grub_vbe_farptr_t ptr) -{ - return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL) - + ((unsigned long) ptr & 0x0000FFFF)); -} - -static grub_err_t -grub_cmd_vbeinfo (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - struct grub_vbe_info_block controller_info; - struct grub_vbe_mode_info_block mode_info_tmp; - grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; - grub_uint16_t *video_mode_list; - grub_uint16_t *p; - grub_uint16_t *saved_video_mode_list; - grub_size_t video_mode_list_size; - grub_err_t err; - char *modevar; - - err = grub_vbe_probe (&controller_info); - if (err != GRUB_ERR_NONE) - return err; - - grub_printf ("VBE info: version: %d.%d OEM software rev: %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF, - controller_info.oem_software_rev >> 8, - controller_info.oem_software_rev & 0xFF); - - /* The total_memory field is in 64 KiB units. */ - grub_printf (" total memory: %d KiB\n", - (controller_info.total_memory << 16) / 1024); - - /* Because the information on video modes is stored in a temporary place, - it is better to copy it to somewhere safe. */ - p = video_mode_list = real2pm (controller_info.video_mode_ptr); - while (*p++ != 0xFFFF) - ; - - video_mode_list_size = (grub_addr_t) p - (grub_addr_t) video_mode_list; - saved_video_mode_list = grub_malloc (video_mode_list_size); - if (! saved_video_mode_list) - return grub_errno; - - grub_memcpy (saved_video_mode_list, video_mode_list, video_mode_list_size); - - grub_printf ("List of compatible video modes:\n"); - grub_printf ("Legend: P=Packed pixel, D=Direct color, " - "mask/pos=R/G/B/reserved\n"); - - /* Walk through all video modes listed. */ - for (p = saved_video_mode_list; *p != 0xFFFF; p++) - { - const char *memory_model = 0; - grub_uint32_t mode = (grub_uint32_t) *p; - - err = grub_vbe_get_video_mode_info (mode, &mode_info_tmp); - if (err != GRUB_ERR_NONE) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0) - /* If not available, skip it. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0) - /* Not enough information. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0) - /* Monochrome is unusable. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_LFB_AVAIL) == 0) - /* We support only linear frame buffer modes. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_GRAPHICS) == 0) - /* We allow only graphical modes. */ - continue; - - switch (mode_info_tmp.memory_model) - { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - memory_model = "Packed"; - break; - case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - memory_model = "Direct"; - break; - - default: - break; - } - - if (! memory_model) - continue; - - grub_printf ("0x%03x: %4d x %4d x %2d %s", - mode, - mode_info_tmp.x_resolution, - mode_info_tmp.y_resolution, - mode_info_tmp.bits_per_pixel, - memory_model); - - /* Show mask and position details for direct color modes. */ - if (mode_info_tmp.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) - grub_printf (", mask: %d/%d/%d/%d pos: %d/%d/%d/%d", - mode_info_tmp.red_mask_size, - mode_info_tmp.green_mask_size, - mode_info_tmp.blue_mask_size, - mode_info_tmp.rsvd_mask_size, - mode_info_tmp.red_field_position, - mode_info_tmp.green_field_position, - mode_info_tmp.blue_field_position, - mode_info_tmp.rsvd_field_position); - grub_printf ("\n"); - } - - grub_free (saved_video_mode_list); - - /* Check existence of vbe_mode environment variable. */ - modevar = grub_env_get ("vbe_mode"); - - if (modevar != 0) - { - unsigned long value; - - value = grub_strtoul (modevar, 0, 0); - if (grub_errno == GRUB_ERR_NONE) - use_mode = value; - else - grub_errno = GRUB_ERR_NONE; - } - - grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode); - - return 0; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(vbeinfo) -{ - cmd = - grub_register_command ("vbeinfo", grub_cmd_vbeinfo, 0, - N_("List compatible VESA BIOS extension video modes.")); -} - -GRUB_MOD_FINI(vbeinfo) -{ - grub_unregister_command (cmd); -} diff --git a/commands/i386/pc/vbetest.c b/commands/i386/pc/vbetest.c deleted file mode 100644 index d2921c09d..000000000 --- a/commands/i386/pc/vbetest.c +++ /dev/null @@ -1,179 +0,0 @@ -/* vbetest.c - command to test VESA BIOS Extension 2.0+ support. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,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 -#include -#include -#include -#include -#include -#include -#include -#include - -static grub_err_t -grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - grub_err_t err; - char *modevar; - struct grub_vbe_mode_info_block mode_info; - struct grub_vbe_info_block controller_info; - grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; - grub_uint32_t old_mode; - grub_uint8_t *framebuffer = 0; - grub_uint32_t bytes_per_scan_line = 0; - unsigned char *ptr; - int i; - - grub_printf ("Probing for VESA BIOS Extension ... "); - - /* Check if VESA BIOS exists. */ - err = grub_vbe_probe (&controller_info); - if (err != GRUB_ERR_NONE) - return err; - - grub_printf ("found!\n"); - - /* Dump out controller information. */ - grub_printf ("VBE signature = %c%c%c%c\n", - controller_info.signature[0], - controller_info.signature[1], - controller_info.signature[2], - controller_info.signature[3]); - - grub_printf ("VBE version = %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF); - grub_printf ("OEM string ptr = %08x\n", - controller_info.oem_string_ptr); - grub_printf ("Total memory = %d\n", - controller_info.total_memory); - - err = grub_vbe_get_video_mode (&old_mode); - grub_printf ("Get video mode err = %04x\n", err); - - if (err == GRUB_ERR_NONE) - grub_printf ("Old video mode = %04x\n", old_mode); - else - grub_errno = GRUB_ERR_NONE; - - /* Check existence of vbe_mode environment variable. */ - modevar = grub_env_get ("vbe_mode"); - if (modevar != 0) - { - unsigned long value; - - value = grub_strtoul (modevar, 0, 0); - if (grub_errno == GRUB_ERR_NONE) - use_mode = value; - else - grub_errno = GRUB_ERR_NONE; - } - - err = grub_vbe_get_video_mode_info (use_mode, &mode_info); - if (err != GRUB_ERR_NONE) - return err; - - /* Dump out details about the mode being tested. */ - grub_printf ("mode: 0x%03x\n", - use_mode); - grub_printf ("width : %d\n", - mode_info.x_resolution); - grub_printf ("height: %d\n", - mode_info.y_resolution); - grub_printf ("memory model: %02x\n", - mode_info.memory_model); - grub_printf ("bytes/scanline: %d\n", - mode_info.bytes_per_scan_line); - grub_printf ("bytes/scanline (lin): %d\n", - mode_info.lin_bytes_per_scan_line); - grub_printf ("base address: %08x\n", - mode_info.phys_base_addr); - grub_printf ("red mask/pos: %d/%d\n", - mode_info.red_mask_size, - mode_info.red_field_position); - grub_printf ("green mask/pos: %d/%d\n", - mode_info.green_mask_size, - mode_info.green_field_position); - grub_printf ("blue mask/pos: %d/%d\n", - mode_info.blue_mask_size, - mode_info.blue_field_position); - - grub_printf ("Press any key to continue.\n"); - - grub_getkey (); - - /* Setup GFX mode. */ - err = grub_vbe_set_video_mode (use_mode, &mode_info); - if (err != GRUB_ERR_NONE) - return err; - - /* Determine framebuffer address and how many bytes are in scan line. */ - framebuffer = (grub_uint8_t *) mode_info.phys_base_addr; - ptr = framebuffer; - - if (controller_info.version >= 0x300) - { - bytes_per_scan_line = mode_info.lin_bytes_per_scan_line; - } - else - { - bytes_per_scan_line = mode_info.bytes_per_scan_line; - } - - /* Draw some random data to screen. */ - for (i = 0; i < 256 * 256; i++) - { - ptr[i] = i & 0x0F; - } - - /* Draw white line to screen. */ - for (i = 0; i < 100; i++) - { - ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F; - } - - /* Draw another white line to screen. */ - grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line); - - grub_getkey (); - - grub_video_restore (); - - /* Restore old video mode. */ - grub_vbe_set_video_mode (old_mode, 0); - - return grub_errno; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(vbetest) -{ - cmd = grub_register_command ("vbetest", grub_cmd_vbetest, - 0, N_("Test VESA BIOS Extension 2.0+ support.")); -} - -GRUB_MOD_FINI(vbetest) -{ - grub_unregister_command (cmd); -} diff --git a/commands/regexp.c b/commands/regexp.c deleted file mode 100644 index e8e8243b5..000000000 --- a/commands/regexp.c +++ /dev/null @@ -1,80 +0,0 @@ -/* regexp.c -- The regexp command. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,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 -#include -#include -#include -#include - -static grub_err_t -grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) -{ - int argn = 0; - int matches = 0; - regex_t regex; - int ret; - grub_size_t s; - char *comperr; - grub_err_t err; - - if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected"); - - ret = regcomp (®ex, args[0], RE_SYNTAX_GNU_AWK); - if (ret) - goto fail; - - ret = regexec (®ex, args[1], 0, 0, 0); - if (!ret) - { - regfree (®ex); - return GRUB_ERR_NONE; - } - - fail: - s = regerror (ret, ®ex, 0, 0); - comperr = grub_malloc (s); - if (!comperr) - { - regfree (®ex); - return grub_errno; - } - regerror (ret, ®ex, comperr, s); - err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr); - regfree (®ex); - grub_free (comperr); - return err; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(regexp) -{ - cmd = grub_register_command ("regexp", grub_cmd_regexp, - N_("REGEXP STRING"), - N_("Test if REGEXP matches STRING.")); -} - -GRUB_MOD_FINI(regexp) -{ - grub_unregister_command (cmd); -} diff --git a/conf/Makefile.common b/conf/Makefile.common new file mode 100644 index 000000000..73b3d819b --- /dev/null +++ b/conf/Makefile.common @@ -0,0 +1,169 @@ +# -*- makefile -*- + +CFLAGS_PLATFORM= + +# Platform specific options +if COND_i386_pc + CFLAGS_PLATFORM += -mrtd -mregparm=3 +endif +if COND_i386_efi + LDFLAGS_PLATFORM = -melf_i386 +endif +if COND_x86_64_efi + LDFLAGS_PLATFORM = -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_yeeloong + CFLAGS_PLATFORM += -mexplicit-relocs + CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK + CCASFLAGS_PLATFORM = -march=mips3 +endif +if COND_mips + CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache +endif +if COND_sparc64_ieee1275 + CFLAGS_PLATFORM += -mno-app-regs + LDFLAGS_PLATFORM = -melf64_sparc -mno-relax +endif + +# Other options + +CPPFLAGS_DEFAULT = -DGRUB_FILE=\"$(subst $(srcdir)/,,$<)\" +CPPFLAGS_DEFAULT += -I$(builddir) +CPPFLAGS_DEFAULT += -I$(srcdir) +CPPFLAGS_DEFAULT += -I$(top_builddir) +CPPFLAGS_DEFAULT += -I$(top_srcdir) +CPPFLAGS_DEFAULT += -I$(top_srcdir)/include +CPPFLAGS_DEFAULT += -I$(top_builddir)/include +CCASFLAGS_DEFAULT = -DASM_FILE=1 + +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 -Wl,-N -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 + +CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding +LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib -Wl,-N,-r,-d +CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) +CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) + +CFLAGS_IMAGE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -fno-builtin +LDFLAGS_IMAGE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib -Wl,-N,-S +CPPFLAGS_IMAGE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) +CCASFLAGS_IMAGE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) + +CFLAGS_PROGRAM = +LDFLAGS_PROGRAM = +CPPFLAGS_PROGRAM = +CCASFLAGS_PROGRAM = + +CFLAGS_LIBRARY = +CPPFLAGS_LIBRARY = +CCASFLAGS_LIBRARY = + +# Other variables + +grubconfdir = $(sysconfdir)/grub.d +grubdatadir = $(datadir)/`echo @PACKAGE_TARNAME@ | sed '$(transform)'` +platformdir = $(pkglibrootdir)/$(target_cpu)-$(platform) + +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 +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 + +CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime + +# List file macros for recognizing /interesting/ modules +CPPFLAGS_FS_LIST = -Dgrub_fs_register=FS_LIST_MARKER +CPPFLAGS_VIDEO_LIST= -Dgrub_video_register=VIDEO_LIST_MARKER +CPPFLAGS_PARTMAP_LIST = -Dgrub_partition_map_register=PARTMAP_LIST_MARKER +CPPFLAGS_PARTTOOL_LIST = -Dgrub_parttool_register=PARTTOOL_LIST_MARKER +CPPFLAGS_TERMINAL_LIST = '-Dgrub_term_register_input(...)=INPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \ + $(CPPFLAGS_PARTTOOL_LIST) $(CPPFLAGS_PARTMAP_LIST) \ + $(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) + +# Define these variables to calm down automake + +IMG_FILES = +MOD_FILES = +MODULE_FILES = +MARKER_FILES = +KERNEL_HEADER_FILES = + +man_MANS = +noinst_DATA = +pkglib_DATA = +bin_SCRIPTS = +sbin_SCRIPTS = +bin_PROGRAMS = +platform_DATA = +sbin_PROGRAMS = +check_SCRIPTS = +grubconf_DATA = +check_PROGRAMS = +noinst_SCRIPTS = +pkglib_SCRIPTS = +noinst_PROGRAMS = +grubconf_SCRIPTS = +noinst_LIBRARIES = +dist_noinst_DATA = + +TESTS = +EXTRA_DIST = +CLEANFILES = +BUILT_SOURCES = + +# Rules for autogen definition files + +.PRECIOUS: $(top_srcdir)/Makefile.tpl +$(top_srcdir)/Makefile.tpl: $(top_srcdir)/gentpl.py + python $< | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) + mv $@.new $@ + +.PRECIOUS: $(top_srcdir)/Makefile.util.am +$(top_srcdir)/Makefile.util.am: $(top_srcdir)/Makefile.util.def $(top_srcdir)/Makefile.tpl + autogen -T $(top_srcdir)/Makefile.tpl $< | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) + mv $@.new $@ + +.PRECIOUS: $(top_srcdir)/grub-core/Makefile.core.am +$(top_srcdir)/grub-core/Makefile.core.am: $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def $(top_srcdir)/Makefile.tpl + if [ "x$$GRUB_CONTRIB" != x ]; then echo "You need to run ./autogen.sh manually." >&2; exit 1; fi + autogen -T $(top_srcdir)/Makefile.tpl $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) + mv $@.new $@ diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist new file mode 100644 index 000000000..c340bb80e --- /dev/null +++ b/conf/Makefile.extra-dist @@ -0,0 +1,34 @@ +EXTRA_DIST += autogen.sh +EXTRA_DIST += geninit.sh + +EXTRA_DIST += gentpl.py +EXTRA_DIST += Makefile.tpl +EXTRA_DIST += Makefile.util.def + +EXTRA_DIST += unicode + +EXTRA_DIST += util/import_gcry.py +EXTRA_DIST += util/import_unicode.py + +EXTRA_DIST += docs/man +EXTRA_DIST += docs/grub.cfg + +EXTRA_DIST += conf/i386-pc-cygwin-img-ld.sc + +EXTRA_DIST += grub-core/Makefile.core.def +EXTRA_DIST += grub-core/Makefile.gcry.def + +EXTRA_DIST += grub-core/genmoddep.awk +EXTRA_DIST += grub-core/genmod.sh.in +EXTRA_DIST += grub-core/gensyminfo.sh.in +EXTRA_DIST += grub-core/gensymlist.sh +EXTRA_DIST += grub-core/genemuinit.sh +EXTRA_DIST += grub-core/genemuinitheader.sh + +EXTRA_DIST += grub-core/lib/libgcrypt/cipher +EXTRA_DIST += $(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 += $(shell find $(top_srcdir)/grub-core/efiemu -name '*.h') + +EXTRA_DIST += m4/gnulib-cache.m4 diff --git a/conf/any-emu.rmk b/conf/any-emu.rmk deleted file mode 100644 index 958da2bee..000000000 --- a/conf/any-emu.rmk +++ /dev/null @@ -1,112 +0,0 @@ -# -*- makefile -*- - -kernel_img_RELOCATABLE = yes -pkglib_PROGRAMS = kernel.img -kernel_img_SOURCES = kern/device.c kern/disk.c kern/dl.c kern/env.c \ - kern/err.c kern/list.c kern/command.c \ - kern/corecmd.c kern/file.c kern/fs.c kern/main.c kern/misc.c \ - kern/parser.c kern/partition.c kern/term.c \ - kern/rescue_reader.c kern/rescue_parser.c \ - \ - kern/emu/main.c kern/emu/mm.c kern/emu/misc.c \ - kern/emu/getroot.c kern/emu/time.c kern/emu/hostdisk.c \ - kern/emu/hostfs.c kern/emu/console.c \ - \ - gnulib/progname.c disk/host.c -kernel_img_HEADERS += datetime.h emu/misc.h -kernel_img_CFLAGS = $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Wno-char-subscripts -Wno-unused -Wno-deprecated-declarations -Wno-undef -I$(srcdir)/gnulib -kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -TARGET_NO_STRIP = yes - -ifneq ($(TARGET_NO_MODULES), yes) -kernel_img_SOURCES += symlist.c kern/$(target_cpu)/dl.c -else -kernel_img_SOURCES += grub_emu_init.c -endif -ifneq ($(target_cpu), i386) -ifneq ($(target_cpu), x86_64) -kernel_img_SOURCES += kern/$(target_cpu)/cache.S -endif -endif - -# For halt.mod. -pkglib_MODULES += halt.mod -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -ifeq ($(target_cpu), i386) -pkglib_MODULES += cpuid.mod -cpuid_mod_SOURCES = commands/i386/cpuid.c -cpuid_mod_CFLAGS = $(COMMON_CFLAGS) -cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS) -endif - -grub_emu_LDFLAGS = $(LIBCURSES) - -ifeq ($(enable_grub_emu_usb), yes) -kernel_img_HEADERS += libusb.h - -pkglib_MODULES += libusb.mod -libusb_mod_SOURCES = bus/usb/emu/usb.c -libusb_mod_CFLAGS = -libusb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usb.mod -pkglib_MODULES += usb.mod -usb_mod_SOURCES = bus/usb/usb.c -usb_mod_CFLAGS = $(COMMON_CFLAGS) -usb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usbtest.mod -pkglib_MODULES += usbtest.mod -usbtest_mod_SOURCES = commands/usbtest.c -usbtest_mod_CFLAGS = $(COMMON_CFLAGS) -usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usbms.mod -pkglib_MODULES += usbms.mod -usbms_mod_SOURCES = disk/usbms.c -usbms_mod_CFLAGS = $(COMMON_CFLAGS) -usbms_mod_LDFLAGS = $(COMMON_LDFLAGS) - -grub_emu_LDFLAGS += $(LIBUSB) -endif - -ifeq ($(enable_grub_emu_sdl), yes) -pkglib_MODULES += sdl.mod -sdl_mod_SOURCES = video/emu/sdl.c -sdl_mod_CFLAGS = -sdl_mod_LDFLAGS = $(COMMON_LDFLAGS) -grub_emu_LDFLAGS += $(LIBSDL) -kernel_img_HEADERS += sdl.h -endif - -ifeq ($(enable_grub_emu_pci), yes) -pkglib_MODULES += pci.mod -pci_mod_SOURCES = bus/emu/pci.c commands/lspci.c -pci_mod_LDFLAGS = $(COMMON_LDFLAGS) -grub_emu_LDFLAGS += $(LIBPCIACCESS) -kernel_img_HEADERS += libpciaccess.h -endif - -include $(srcdir)/conf/common.mk - -grub_emu_init.h: genemuinitheader.sh $(pkglib_MODULES) - rm -f $@; echo $(pkglib_MODULES) | sh $(srcdir)/genemuinitheader.sh $(NM) > $@ -DISTCLEANFILES += grub_emu_init.h - -grub_emu_init.c: genemuinit.sh $(pkglib_MODULES) grub_emu_init.h - rm -f $@; echo $(pkglib_MODULES) | sh $(srcdir)/genemuinit.sh $(NM) > $@ -DISTCLEANFILES += grub_emu_init.c - -CLEANFILES += grub-emu -ifneq ($(TARGET_NO_MODULES), yes) -grub-emu: $(pkglib_PROGRAMS) - $(CC) -o $@ $^ $(grub_emu_LDFLAGS) $(LDFLAGS) -else -grub-emu: $(pkglib_MODULES) $(pkglib_PROGRAMS) - $(CC) -o $@ $^ $(grub_emu_LDFLAGS) $(LDFLAGS) -endif -GRUB_EMU=grub-emu - diff --git a/conf/common.rmk b/conf/common.rmk deleted file mode 100644 index f92e5bc4c..000000000 --- a/conf/common.rmk +++ /dev/null @@ -1,837 +0,0 @@ -# -*- makefile -*- - -# Used by various components. These rules need to precede them. -script/lexer.c_DEPENDENCIES = grub_script.tab.h grub_script.yy.h - -sbin_UTILITIES += grub-mkdevicemap -grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \ - util/deviceiter.c \ - util/misc.c kern/emu/misc.c \ - kern/env.c kern/err.c kern/list.c kern/misc.c kern/emu/mm.c - -ifeq ($(target_cpu)-$(platform), sparc64-ieee1275) -grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c -else -grub_mkdevicemap_SOURCES += util/devicemap.c -endif - -# For grub-mkimage. -bin_UTILITIES += grub-mkimage -grub_mkimage_SOURCES = gnulib/progname.c util/grub-mkimage.c util/misc.c \ - util/resolve.c kern/emu/misc.c lib/LzmaEnc.c lib/LzFind.c -util/grub-mkimage.c_DEPENDENCIES = Makefile - -# For grub-probe. -sbin_UTILITIES += grub-probe -util/grub-probe.c_DEPENDENCIES = grub_probe_init.h -grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \ - kern/emu/hostdisk.c util/misc.c kern/emu/misc.c kern/emu/getroot.c kern/emu/mm.c \ - kern/device.c kern/disk.c kern/err.c kern/misc.c \ - kern/partition.c kern/file.c kern/list.c \ - \ - fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \ - fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ - fs/nilfs2.c fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c \ - fs/sfs.c fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c \ - fs/afs_be.c fs/befs.c fs/befs_be.c fs/tar.c \ - \ - partmap/msdos.c partmap/bsdlabel.c partmap/apple.c \ - partmap/sun.c partmap/sunpc.c partmap/gpt.c \ - kern/fs.c kern/env.c fs/fshelp.c \ - disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/lvm.c grub_probe_init.c - -ifeq ($(enable_grub_fstest), yes) -bin_UTILITIES += grub-fstest -endif - -# For grub-fstest. -util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h -grub_fstest_SOURCES = gnulib/progname.c util/grub-fstest.c kern/emu/hostfs.c \ - util/misc.c kern/emu/misc.c kern/emu/mm.c \ - kern/file.c kern/device.c kern/disk.c kern/err.c kern/misc.c \ - disk/host.c disk/loopback.c kern/list.c kern/command.c \ - lib/arg.c commands/extcmd.c normal/datetime.c normal/misc.c \ - lib/hexdump.c lib/crc.c commands/blocklist.c commands/ls.c \ - \ - fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \ - fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ - fs/nilfs2.c fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \ - fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c fs/befs.c \ - fs/befs_be.c fs/tar.c \ - \ - kern/partition.c partmap/msdos.c partmap/bsdlabel.c \ - partmap/apple.c partmap/sun.c partmap/sunpc.c partmap/gpt.c \ - kern/fs.c kern/env.c fs/fshelp.c disk/raid.c \ - disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \ - grub_fstest_init.c - -# For grub-mkfont. -ifeq ($(enable_grub_mkfont), yes) -bin_UTILITIES += grub-mkfont -grub_mkfont_SOURCES = gnulib/progname.c util/grub-mkfont.c util/misc.c \ - unidata.c kern/emu/misc.c -grub_mkfont_CFLAGS = $(freetype_cflags) -grub_mkfont_LDFLAGS = $(freetype_libs) -endif - -# For grub-mkrelpath. -bin_UTILITIES += grub-mkrelpath -grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c kern/emu/misc.c - -bin_UTILITIES += grub-bin2h -grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c - -# For the lexer. -grub_script.yy.c grub_script.yy.h: script/yylex.l - $(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $(srcdir)/script/yylex.l -DISTCLEANFILES += grub_script.yy.c grub_script.yy.h - -# For grub-script-check. -bin_UTILITIES += grub-script-check -grub_script_check_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c \ - util/grub-script-check.c util/misc.c kern/emu/misc.c kern/emu/mm.c \ - script/main.c script/script.c script/function.c script/lexer.c \ - kern/err.c kern/list.c \ - kern/misc.c kern/env.c grub_script.tab.c \ - grub_script.yy.c -grub_script_check_CFLAGS = $(GNULIB_UTIL_CFLAGS) -grub_script_check_DEPENDENCIES = grub_script.tab.h -MOSTLYCLEANFILES += symlist.c kernel_syms.lst -DEFSYMFILES += kernel_syms.lst - -kernel_img_HEADERS += boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ - env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \ - list.h command.h i18n.h env_private.h libgcc.h - -ifneq ($(platform), emu) -kernel_img_HEADERS += machine/memory.h machine/loader.h -endif - -symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh - /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) - -kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h genkernsyms.sh - /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) - -# For the parser. -grub_script.tab.c grub_script.tab.h: script/parser.y - $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/parser.y -DISTCLEANFILES += grub_script.tab.c grub_script.tab.h - -# For grub-probe. -grub_probe_init.lst: geninit.sh $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) - rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@ -DISTCLEANFILES += grub_probe_init.lst - -grub_probe_init.h: grub_probe_init.lst $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) geninitheader.sh - rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@ -DISTCLEANFILES += grub_probe_init.h - -grub_probe_init.c: grub_probe_init.lst $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) geninit.sh grub_probe_init.h - rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ -DISTCLEANFILES += grub_probe_init.c - -# For grub-setup. -grub_setup_init.lst: geninit.sh $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) - rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@ -DISTCLEANFILES += grub_setup_init.lst - -grub_setup_init.h: grub_setup_init.lst $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) geninitheader.sh - rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@ -DISTCLEANFILES += grub_setup_init.h - -grub_setup_init.c: grub_setup_init.lst $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) geninit.sh grub_setup_init.h - rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ -DISTCLEANFILES += grub_setup_init.c - -# For grub-fstest. -grub_fstest_init.lst: geninit.sh $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) - rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@ -DISTCLEANFILES += grub_fstest_init.lst - -grub_fstest_init.h: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) geninitheader.sh - rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@ -DISTCLEANFILES += grub_fstest_init.h - -grub_fstest_init.c: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) geninit.sh grub_fstest_init.h - rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ -DISTCLEANFILES += grub_fstest_init.c - -# for grub-editenv -bin_UTILITIES += grub-editenv -grub_editenv_SOURCES = gnulib/progname.c util/grub-editenv.c lib/envblk.c util/misc.c kern/emu/misc.c kern/emu/mm.c kern/misc.c kern/err.c -CLEANFILES += grub-editenv - -# Needed for genmk.rb to work -ifeq (0,1) -bin_UTILITIES += grub-macho2img grub-pe2elf -endif - -grub_pe2elf_SOURCES = gnulib/progname.c util/grub-pe2elf.c util/misc.c kern/emu/misc.c -CLEANFILES += grub-pe2elf - -grub_macho2img_SOURCES = util/grub-macho2img.c -CLEANFILES += grub-macho2img - -# For grub-mkconfig -grub-mkconfig: util/grub-mkconfig.in config.status - ./config.status --file=$@:$< - chmod +x $@ -sbin_SCRIPTS += grub-mkconfig -CLEANFILES += grub-mkconfig - -grub-mkconfig_lib: util/grub-mkconfig_lib.in config.status - ./config.status --file=$@:$< - chmod +x $@ -lib_SCRIPTS += grub-mkconfig_lib -CLEANFILES += grub-mkconfig_lib - -update-grub_lib: util/update-grub_lib.in config.status - ./config.status --file=$@:$< - chmod +x $@ -lib_SCRIPTS += update-grub_lib -CLEANFILES += update-grub_lib - -grub-gettext_lib: util/grub-gettext_lib.in config.status - ./config.status --file=$@:$< - chmod +x $@ -lib_DATA += grub-gettext_lib -CLEANFILES += grub-gettext_lib - -%: util/grub.d/%.in config.status - ./config.status --file=$@:$< - chmod +x $@ -grub-mkconfig_SCRIPTS = 00_header 30_os-prober 40_custom 41_custom -ifneq (, $(host_kernel)) -grub-mkconfig_SCRIPTS += 10_$(host_kernel) -endif -ifeq (linux, $(host_kernel)) -grub-mkconfig_SCRIPTS += 20_linux_xen -endif - -CLEANFILES += $(grub-mkconfig_SCRIPTS) - -grub-mkconfig_DATA += util/grub.d/README - -# For grub-set-default. -grub-set-default: util/grub-set-default.in config.status - ./config.status --file=$@:$< - chmod +x $@ -sbin_SCRIPTS += grub-set-default -CLEANFILES += grub-set-default - -# For grub-reboot. -grub-reboot: util/grub-reboot.in config.status - ./config.status --file=$@:$< - chmod +x $@ -sbin_SCRIPTS += grub-reboot -CLEANFILES += grub-reboot - -# Filing systems. -pkglib_MODULES += fshelp.mod fat.mod ufs1.mod ufs2.mod ext2.mod ntfs.mod \ - ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod \ - affs.mod sfs.mod hfsplus.mod reiserfs.mod cpio.mod tar.mod \ - udf.mod afs.mod afs_be.mod befs.mod befs_be.mod - -# For fshelp.mod. -fshelp_mod_SOURCES = fs/fshelp.c -fshelp_mod_CFLAGS = $(COMMON_CFLAGS) -fshelp_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For fat.mod. -fat_mod_SOURCES = fs/fat.c -fat_mod_CFLAGS = $(COMMON_CFLAGS) -fat_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ufs1.mod. -ufs1_mod_SOURCES = fs/ufs.c -ufs1_mod_CFLAGS = $(COMMON_CFLAGS) -ufs1_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ufs2.mod. -ufs2_mod_SOURCES = fs/ufs2.c -ufs2_mod_CFLAGS = $(COMMON_CFLAGS) -ufs2_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ext2.mod. -ext2_mod_SOURCES = fs/ext2.c -ext2_mod_CFLAGS = $(COMMON_CFLAGS) -ext2_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ntfs.mod. -ntfs_mod_SOURCES = fs/ntfs.c -ntfs_mod_CFLAGS = $(COMMON_CFLAGS) -ntfs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ntfscomp.mod. -ntfscomp_mod_SOURCES = fs/ntfscomp.c -ntfscomp_mod_CFLAGS = $(COMMON_CFLAGS) -ntfscomp_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For minix.mod. -minix_mod_SOURCES = fs/minix.c -minix_mod_CFLAGS = $(COMMON_CFLAGS) -minix_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For nilfs2.mod. -pkglib_MODULES += nilfs2.mod -nilfs2_mod_SOURCES = fs/nilfs2.c -nilfs2_mod_CFLAGS = $(COMMON_CFLAGS) -nilfs2_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For hfs.mod. -hfs_mod_SOURCES = fs/hfs.c -hfs_mod_CFLAGS = $(COMMON_CFLAGS) -hfs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For jfs.mod. -jfs_mod_SOURCES = fs/jfs.c -jfs_mod_CFLAGS = $(COMMON_CFLAGS) -jfs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For iso9660.mod. -iso9660_mod_SOURCES = fs/iso9660.c -iso9660_mod_CFLAGS = $(COMMON_CFLAGS) -iso9660_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For xfs.mod. -xfs_mod_SOURCES = fs/xfs.c -xfs_mod_CFLAGS = $(COMMON_CFLAGS) -xfs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For affs.mod. -affs_mod_SOURCES = fs/affs.c -affs_mod_CFLAGS = $(COMMON_CFLAGS) -affs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For sfs.mod. -sfs_mod_SOURCES = fs/sfs.c -sfs_mod_CFLAGS = $(COMMON_CFLAGS) -sfs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For hfsplus.mod. -hfsplus_mod_SOURCES = fs/hfsplus.c -hfsplus_mod_CFLAGS = $(COMMON_CFLAGS) -hfsplus_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For reiserfs.mod. -reiserfs_mod_SOURCES = fs/reiserfs.c -reiserfs_mod_CFLAGS = $(COMMON_CFLAGS) -reiserfs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For cpio.mod. -cpio_mod_SOURCES = fs/cpio.c -cpio_mod_CFLAGS = $(COMMON_CFLAGS) -cpio_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For tar.mod. -tar_mod_SOURCES = fs/tar.c -tar_mod_CFLAGS = $(COMMON_CFLAGS) -tar_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For udf.mod. -udf_mod_SOURCES = fs/udf.c -udf_mod_CFLAGS = $(COMMON_CFLAGS) -udf_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For afs.mod. -afs_mod_SOURCES = fs/afs.c -afs_mod_CFLAGS = $(COMMON_CFLAGS) -afs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For afs_be.mod. -afs_be_mod_SOURCES = fs/afs_be.c -afs_be_mod_CFLAGS = $(COMMON_CFLAGS) -afs_be_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For befs.mod. -befs_mod_SOURCES = fs/befs.c -befs_mod_CFLAGS = $(COMMON_CFLAGS) -befs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For befs_be.mod. -befs_be_mod_SOURCES = fs/befs_be.c -befs_be_mod_CFLAGS = $(COMMON_CFLAGS) -befs_be_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Partition maps. - -pkglib_MODULES += part_amiga.mod -part_amiga_mod_SOURCES = partmap/amiga.c -part_amiga_mod_CFLAGS = $(COMMON_CFLAGS) -part_amiga_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_apple.mod -part_apple_mod_SOURCES = partmap/apple.c -part_apple_mod_CFLAGS = $(COMMON_CFLAGS) -part_apple_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_msdos.mod -part_msdos_mod_SOURCES = partmap/msdos.c -part_msdos_mod_CFLAGS = $(COMMON_CFLAGS) -part_msdos_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_sun.mod -part_sun_mod_SOURCES = partmap/sun.c -part_sun_mod_CFLAGS = $(COMMON_CFLAGS) -part_sun_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_acorn.mod -part_acorn_mod_SOURCES = partmap/acorn.c -part_acorn_mod_CFLAGS = $(COMMON_CFLAGS) -part_acorn_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_gpt.mod -part_gpt_mod_SOURCES = partmap/gpt.c -part_gpt_mod_CFLAGS = $(COMMON_CFLAGS) -part_gpt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_bsd.mod -part_bsd_mod_SOURCES = partmap/bsdlabel.c -part_bsd_mod_CFLAGS = $(COMMON_CFLAGS) -part_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += part_sunpc.mod -part_sunpc_mod_SOURCES = partmap/sunpc.c -part_sunpc_mod_CFLAGS = $(COMMON_CFLAGS) -part_sunpc_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Special disk structures and generic drivers - -pkglib_MODULES += raid.mod raid5rec.mod raid6rec.mod mdraid.mod dm_nv.mod \ - lvm.mod scsi.mod - -# For raid.mod -raid_mod_SOURCES = disk/raid.c -raid_mod_CFLAGS = $(COMMON_CFLAGS) -raid_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For raid5rec.mod -raid5rec_mod_SOURCES = disk/raid5_recover.c -raid5rec_mod_CFLAGS = $(COMMON_CFLAGS) -raid5rec_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For raid6rec.mod -raid6rec_mod_SOURCES = disk/raid6_recover.c -raid6rec_mod_CFLAGS = $(COMMON_CFLAGS) -raid6rec_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For mdraid.mod -mdraid_mod_SOURCES = disk/mdraid_linux.c -mdraid_mod_CFLAGS = $(COMMON_CFLAGS) -mdraid_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For dm_nv.mod -dm_nv_mod_SOURCES = disk/dmraid_nvidia.c -dm_nv_mod_CFLAGS = $(COMMON_CFLAGS) -dm_nv_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For lvm.mod -lvm_mod_SOURCES = disk/lvm.c -lvm_mod_CFLAGS = $(COMMON_CFLAGS) -lvm_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For scsi.mod -scsi_mod_SOURCES = disk/scsi.c -scsi_mod_CFLAGS = $(COMMON_CFLAGS) -scsi_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Commands. -pkglib_MODULES += minicmd.mod extcmd.mod hello.mod \ - ls.mod cmp.mod cat.mod help.mod search.mod loopback.mod \ - configfile.mod echo.mod \ - test.mod blocklist.mod hexdump.mod \ - read.mod sleep.mod loadenv.mod crc.mod parttool.mod \ - msdospart.mod memrw.mod normal.mod \ - gptsync.mod true.mod probe.mod password.mod \ - keystatus.mod - -# For password.mod. -password_mod_SOURCES = commands/password.c -password_mod_CFLAGS = $(COMMON_CFLAGS) -password_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For gptsync.mod. -gptsync_mod_SOURCES = commands/gptsync.c -gptsync_mod_CFLAGS = $(COMMON_CFLAGS) -gptsync_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For minicmd.mod. -minicmd_mod_SOURCES = commands/minicmd.c -minicmd_mod_CFLAGS = $(COMMON_CFLAGS) -minicmd_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For extcmd.mod. -extcmd_mod_SOURCES = commands/extcmd.c lib/arg.c -extcmd_mod_CFLAGS = $(COMMON_CFLAGS) -extcmd_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For hello.mod. -hello_mod_SOURCES = hello/hello.c -hello_mod_CFLAGS = $(COMMON_CFLAGS) -hello_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For gfxmenu.mod. -pkglib_MODULES += gfxmenu.mod -gfxmenu_mod_SOURCES = \ - gfxmenu/gfxmenu.c \ - gfxmenu/model.c \ - gfxmenu/view.c \ - gfxmenu/icon_manager.c \ - gfxmenu/theme_loader.c \ - gfxmenu/widget-box.c \ - gfxmenu/gui_canvas.c \ - gfxmenu/gui_circular_progress.c \ - gfxmenu/gui_box.c \ - gfxmenu/gui_label.c \ - gfxmenu/gui_list.c \ - gfxmenu/gui_image.c \ - gfxmenu/gui_progress_bar.c \ - gfxmenu/gui_util.c \ - gfxmenu/gui_string_util.c \ - gfxmenu/named_colors.c \ - gfxmenu/font.c -gfxmenu_mod_CFLAGS = $(COMMON_CFLAGS) -gfxmenu_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For parttool.mod. -parttool_mod_SOURCES = commands/parttool.c -parttool_mod_CFLAGS = $(COMMON_CFLAGS) -parttool_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For msdospart.mod. -msdospart_mod_SOURCES = parttool/msdospart.c -msdospart_mod_CFLAGS = $(COMMON_CFLAGS) -msdospart_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ls.mod. -ls_mod_SOURCES = commands/ls.c -ls_mod_CFLAGS = $(COMMON_CFLAGS) -ls_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For cmp.mod. -cmp_mod_SOURCES = commands/cmp.c -cmp_mod_CFLAGS = $(COMMON_CFLAGS) -cmp_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For cat.mod. -cat_mod_SOURCES = commands/cat.c -cat_mod_CFLAGS = $(COMMON_CFLAGS) -cat_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For echo.mod -echo_mod_SOURCES = commands/echo.c -echo_mod_CFLAGS = $(COMMON_CFLAGS) -echo_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For help.mod. -help_mod_SOURCES = commands/help.c -help_mod_CFLAGS = $(COMMON_CFLAGS) -help_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For search.mod. -search_mod_SOURCES = commands/search_wrap.c -search_mod_CFLAGS = $(COMMON_CFLAGS) -search_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += search_fs_file.mod search_fs_uuid.mod search_label.mod - -# For search.mod. -search_fs_file_mod_SOURCES = commands/search_file.c -search_fs_file_mod_CFLAGS = $(COMMON_CFLAGS) -search_fs_file_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For search.mod. -search_label_mod_SOURCES = commands/search_label.c -search_label_mod_CFLAGS = $(COMMON_CFLAGS) -search_label_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For search.mod. -search_fs_uuid_mod_SOURCES = commands/search_uuid.c -search_fs_uuid_mod_CFLAGS = $(COMMON_CFLAGS) -search_fs_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For test.mod. -test_mod_SOURCES = commands/test.c -test_mod_CFLAGS = $(COMMON_CFLAGS) -test_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For loopback.mod -loopback_mod_SOURCES = disk/loopback.c -loopback_mod_CFLAGS = $(COMMON_CFLAGS) -loopback_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For configfile.mod -configfile_mod_SOURCES = commands/configfile.c -configfile_mod_CFLAGS = $(COMMON_CFLAGS) -configfile_mod_LDFLAGS = $(COMMON_LDFLAGS) - -ifneq ($(platform), ieee1275) -# For terminfo.mod. -pkglib_MODULES += terminfo.mod -terminfo_mod_SOURCES = term/terminfo.c term/tparm.c -terminfo_mod_CFLAGS = $(COMMON_CFLAGS) -terminfo_mod_LDFLAGS = $(COMMON_LDFLAGS) -endif - -# For blocklist.mod. -blocklist_mod_SOURCES = commands/blocklist.c -blocklist_mod_CFLAGS = $(COMMON_CFLAGS) -blocklist_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For hexdump.mod. -hexdump_mod_SOURCES = commands/hexdump.c lib/hexdump.c -hexdump_mod_CFLAGS = $(COMMON_CFLAGS) -hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For read.mod. -read_mod_SOURCES = commands/read.c -read_mod_CFLAGS = $(COMMON_CFLAGS) -read_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For sleep.mod. -sleep_mod_SOURCES = commands/sleep.c -sleep_mod_CFLAGS = $(COMMON_CFLAGS) -sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For loadenv.mod. -loadenv_mod_SOURCES = commands/loadenv.c lib/envblk.c -loadenv_mod_CFLAGS = $(COMMON_CFLAGS) -loadenv_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For crc.mod. -crc_mod_SOURCES = commands/crc.c lib/crc.c -crc_mod_CFLAGS = $(COMMON_CFLAGS) -crc_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For memrw.mod. -memrw_mod_SOURCES = commands/memrw.c -memrw_mod_CFLAGS = $(COMMON_CFLAGS) -memrw_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For true.mod -true_mod_SOURCES = commands/true.c -true_mod_CFLAGS = $(COMMON_CFLAGS) -true_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For probe.mod. -probe_mod_SOURCES = commands/probe.c -probe_mod_CFLAGS = $(COMMON_CFLAGS) -probe_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For keystatus.mod. -keystatus_mod_SOURCES = commands/keystatus.c -keystatus_mod_CFLAGS = $(COMMON_CFLAGS) -keystatus_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For normal.mod. -ifneq (, $(FONT_SOURCE)) -normal/charset.c_DEPENDENCIES = widthspec.h -endif -normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ - normal/auth.c normal/autofs.c \ - normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ - normal/menu_entry.c normal/menu_text.c normal/charset.c \ - normal/misc.c normal/crypto.c normal/term.c normal/context.c \ - script/main.c script/script.c script/execute.c unidata.c \ - script/function.c script/lexer.c grub_script.tab.c grub_script.yy.c -normal_mod_CFLAGS = $(COMMON_CFLAGS) $(POSIX_CFLAGS) -Wno-error -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - -ifneq (, $(FONT_SOURCE)) -font/font.c_DEPENDENCIES = ascii.h -endif - -# Common Video Subsystem specific modules. -# On Yeeloong it's part of kernel -ifneq ($(platform), yeeloong) - -# For video.mod. -pkglib_MODULES += video.mod -video_mod_SOURCES = video/video.c -video_mod_CFLAGS = $(COMMON_CFLAGS) -video_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += video_fb.mod -video_fb_mod_SOURCES = video/fb/video_fb.c video/fb/fbblit.c \ - video/fb/fbfill.c video/fb/fbutil.c -video_fb_mod_CFLAGS = $(COMMON_CFLAGS) -video_fb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For bitmap.mod -pkglib_MODULES += bitmap.mod -bitmap_mod_SOURCES = video/bitmap.c -bitmap_mod_CFLAGS = $(COMMON_CFLAGS) -bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For bitmap_scale.mod -pkglib_MODULES += bitmap_scale.mod -bitmap_scale_mod_SOURCES = video/bitmap_scale.c -bitmap_scale_mod_CFLAGS = $(COMMON_CFLAGS) -bitmap_scale_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += font.mod -font_mod_SOURCES = font/font_cmd.c font/font.c -font_mod_CFLAGS = $(COMMON_CFLAGS) -font_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For gfxterm.mod. -pkglib_MODULES += gfxterm.mod -gfxterm_mod_SOURCES = term/gfxterm.c -gfxterm_mod_CFLAGS = $(COMMON_CFLAGS) -gfxterm_mod_LDFLAGS = $(COMMON_LDFLAGS) - -endif - -# For videotest.mod. -pkglib_MODULES += videotest.mod -videotest_mod_SOURCES = commands/videotest.c -videotest_mod_CFLAGS = $(COMMON_CFLAGS) -videotest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For tga.mod -pkglib_MODULES += tga.mod -tga_mod_SOURCES = video/readers/tga.c -tga_mod_CFLAGS = $(COMMON_CFLAGS) -tga_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For jpeg.mod. -pkglib_MODULES += jpeg.mod -jpeg_mod_SOURCES = video/readers/jpeg.c -jpeg_mod_CFLAGS = $(COMMON_CFLAGS) -jpeg_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For png.mod. -pkglib_MODULES += png.mod -png_mod_SOURCES = video/readers/png.c -png_mod_CFLAGS = $(COMMON_CFLAGS) -png_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Misc. -pkglib_MODULES += gzio.mod elf.mod - -# For elf.mod. -elf_mod_SOURCES = kern/elf.c -elf_mod_CFLAGS = $(COMMON_CFLAGS) -elf_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For gzio.mod. -gzio_mod_SOURCES = io/gzio.c -gzio_mod_CFLAGS = $(COMMON_CFLAGS) -gzio_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# On Yeeloong it's part of kernel -ifneq ($(platform), yeeloong) -# For bufio.mod. -pkglib_MODULES += bufio.mod -bufio_mod_SOURCES = io/bufio.c -bufio_mod_CFLAGS = $(COMMON_CFLAGS) -bufio_mod_LDFLAGS = $(COMMON_LDFLAGS) -endif - -# For gettext.mod. -pkglib_MODULES += gettext.mod -gettext_mod_SOURCES = gettext/gettext.c -gettext_mod_CFLAGS = $(COMMON_CFLAGS) -gettext_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Misc. -pkglib_MODULES += xnu_uuid.mod - -# For elf.mod. -xnu_uuid_mod_SOURCES = commands/xnu_uuid.c -xnu_uuid_mod_CFLAGS = $(COMMON_CFLAGS) -xnu_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += trig.mod -trig_mod_SOURCES = trigtables.c -trig_mod_CFLAGS = $(COMMON_CFLAGS) -trig_mod_LDFLAGS = $(COMMON_LDFLAGS) - -trigtables.c: gentrigtables - ./gentrigtables > $@ -DISTCLEANFILES += trigtables.c -gentrigtables: gentrigtables.c - $(CC) -o $@ $^ $(CPPFLAGS) -lm -DISTCLEANFILES += gentrigtables - -pkglib_MODULES += setjmp.mod -setjmp_mod_SOURCES = lib/$(target_cpu)/setjmp.S -setjmp_mod_ASFLAGS = $(COMMON_ASFLAGS) -setjmp_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += regexp.mod -regexp_mod_SOURCES = gnulib/regex.c commands/regexp.c -regexp_mod_CFLAGS = $(COMMON_CFLAGS) $(GNULIB_CFLAGS) -regexp_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += terminal.mod -terminal_mod_SOURCES = commands/terminal.c -terminal_mod_CFLAGS = $(COMMON_CFLAGS) -terminal_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += crypto.mod -crypto_mod_SOURCES = lib/crypto.c -crypto_mod_CFLAGS = $(COMMON_CFLAGS) -crypto_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += hashsum.mod -hashsum_mod_SOURCES = commands/hashsum.c -hashsum_mod_CFLAGS = $(COMMON_CFLAGS) -hashsum_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += pbkdf2.mod -pbkdf2_mod_SOURCES = lib/pbkdf2.c -pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS) -pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For password_pbkdf2.mod. -pkglib_MODULES += password_pbkdf2.mod -password_pbkdf2_mod_SOURCES = commands/password_pbkdf2.c -password_pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS) -password_pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For memdisk.mod. -pkglib_MODULES += memdisk.mod -memdisk_mod_SOURCES = disk/memdisk.c -memdisk_mod_CFLAGS = $(COMMON_CFLAGS) -memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For reboot.mod. -pkglib_MODULES += reboot.mod -reboot_mod_SOURCES = commands/reboot.c -reboot_mod_CFLAGS = $(COMMON_CFLAGS) -reboot_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For date.mod -pkglib_MODULES += date.mod -date_mod_SOURCES = commands/date.c -date_mod_CFLAGS = $(COMMON_CFLAGS) -date_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For datehook.mod -pkglib_MODULES += datehook.mod -datehook_mod_SOURCES = hook/datehook.c -datehook_mod_CFLAGS = $(COMMON_CFLAGS) -datehook_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For lsmmap.mod -pkglib_MODULES += lsmmap.mod -lsmmap_mod_SOURCES = commands/lsmmap.c -lsmmap_mod_CFLAGS = $(COMMON_CFLAGS) -lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For boot.mod. -pkglib_MODULES += boot.mod -boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c -boot_mod_CFLAGS = $(COMMON_CFLAGS) -boot_mod_LDFLAGS = $(COMMON_LDFLAGS) - -bin_UTILITIES += grub-mkpasswd-pbkdf2 -grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/emu/misc.c kern/emu/mm.c kern/err.c -grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1 - -include $(srcdir)/conf/gcry.mk diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk deleted file mode 100644 index 259f4e162..000000000 --- a/conf/i386-coreboot.rmk +++ /dev/null @@ -1,78 +0,0 @@ -# -*- makefile -*- - -COMMON_CFLAGS = -mrtd -mregparm=3 - -# Images. - -pkglib_PROGRAMS += kernel.img -kernel_img_SOURCES = kern/i386/coreboot/startup.S \ - kern/i386/misc.S \ - kern/i386/coreboot/init.c \ - kern/i386/coreboot/mmap.c \ - kern/i386/halt.c \ - kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/command.c kern/corecmd.c \ - kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ - kern/i386/tsc.c kern/i386/pit.c \ - kern/generic/rtc_get_time_ms.c \ - kern/generic/millisleep.c \ - kern/env.c \ - term/i386/pc/vga_text.c term/i386/vga_common.c \ - symlist.c -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x8200,-Bstatic - -sbin_SCRIPTS += grub-install -grub_install_SOURCES = util/grub-install.in - -bin_SCRIPTS += grub-mkrescue -grub_mkrescue_SOURCES = util/grub-mkrescue.in - -# Modules. -pkglib_MODULES = linux.mod aout.mod halt.mod datetime.mod mmap.mod - -# For mmap.mod. -mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For linux.mod. -linux_mod_SOURCES = loader/i386/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod. -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For aout.mod. -aout_mod_SOURCES = loader/aout.c -aout_mod_CFLAGS = $(COMMON_CFLAGS) -aout_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For bsd.mod -pkglib_MODULES += bsd.mod -bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd32.c loader/i386/bsd64.c loader/i386/bsd_helper.S loader/i386/bsd_trampoline.S -bsd_mod_CFLAGS = $(COMMON_CFLAGS) -bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) -bsd_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For datetime.mod -datetime_mod_SOURCES = lib/cmos_datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For cmostest.mod -pkglib_MODULES += cmostest.mod -cmostest_mod_SOURCES = commands/i386/cmostest.c -cmostest_mod_CFLAGS = $(COMMON_CFLAGS) -cmostest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -include $(srcdir)/conf/i386.mk -include $(srcdir)/conf/common.mk diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk deleted file mode 100644 index e826cb333..000000000 --- a/conf/i386-efi.rmk +++ /dev/null @@ -1,5 +0,0 @@ -# -*- makefile -*- - -COMMON_LDFLAGS = -melf_i386 - -include $(srcdir)/conf/x86-efi.mk diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk deleted file mode 100644 index 29b3ade3c..000000000 --- a/conf/i386-ieee1275.rmk +++ /dev/null @@ -1,82 +0,0 @@ -# -*- makefile -*- - -COMMON_CFLAGS = -mrtd -mregparm=3 - -# Images. -pkglib_PROGRAMS = kernel.img - -# For kernel.img. -kernel_img_SOURCES = kern/i386/ieee1275/startup.S \ - kern/i386/misc.S \ - kern/i386/ieee1275/init.c \ - kern/ieee1275/init.c \ - kern/ieee1275/mmap.c \ - kern/ieee1275/cmain.c kern/ieee1275/openfw.c \ - kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ - kern/env.c \ - kern/time.c kern/list.c kern/command.c kern/corecmd.c \ - kern/generic/millisleep.c \ - kern/ieee1275/ieee1275.c \ - term/ieee1275/ofconsole.c \ - term/terminfo.c term/tparm.c \ - disk/ieee1275/ofdisk.c \ - symlist.c -kernel_img_HEADERS += ieee1275/ieee1275.h terminfo.h -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic - -# Scripts. -sbin_SCRIPTS = grub-install - -# For grub-install. -grub_install_SOURCES = util/ieee1275/grub-install.in - -# Modules. -pkglib_MODULES = halt.mod suspend.mod \ - aout.mod linux.mod \ - nand.mod datetime.mod \ - mmap.mod - -# For mmap.mod. -mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For aout.mod. -aout_mod_SOURCES = loader/aout.c -aout_mod_CFLAGS = $(COMMON_CFLAGS) -aout_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For suspend.mod -suspend_mod_SOURCES = commands/ieee1275/suspend.c -suspend_mod_CFLAGS = $(COMMON_CFLAGS) -suspend_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For linux.mod. -linux_mod_SOURCES = loader/i386/ieee1275/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For nand.mod. -nand_mod_SOURCES = disk/ieee1275/nand.c -nand_mod_CFLAGS = $(COMMON_CFLAGS) -nand_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For datetime.mod -datetime_mod_SOURCES = lib/cmos_datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -include $(srcdir)/conf/i386.mk -include $(srcdir)/conf/common.mk diff --git a/conf/i386-multiboot.rmk b/conf/i386-multiboot.rmk deleted file mode 100644 index 69b8e9a48..000000000 --- a/conf/i386-multiboot.rmk +++ /dev/null @@ -1,74 +0,0 @@ -# -*- makefile -*- - -COMMON_CFLAGS = -mrtd -mregparm=3 - -# Images. - -GRUB_KERNEL_MACHINE_LINK_ADDR = 0x8200 - -pkglib_PROGRAMS += kernel.img -kernel_img_SOURCES = kern/i386/coreboot/startup.S \ - kern/i386/misc.S \ - kern/i386/coreboot/init.c \ - kern/i386/multiboot_mmap.c \ - kern/i386/halt.c \ - kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ - kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ - kern/i386/tsc.c kern/i386/pit.c \ - kern/generic/rtc_get_time_ms.c \ - kern/generic/millisleep.c \ - kern/env.c \ - term/i386/pc/vga_text.c term/i386/vga_common.c \ - symlist.c -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR),-Bstatic - -sbin_SCRIPTS += grub-install -grub_install_SOURCES = util/grub-install.in - -bin_SCRIPTS += grub-mkrescue -grub_mkrescue_SOURCES = util/grub-mkrescue.in - -# Modules. -pkglib_MODULES = linux.mod aout.mod halt.mod datetime.mod mmap.mod - -# For mmap.mod. -mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For linux.mod. -linux_mod_SOURCES = loader/i386/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod. -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For aout.mod. -aout_mod_SOURCES = loader/aout.c -aout_mod_CFLAGS = $(COMMON_CFLAGS) -aout_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For bsd.mod -pkglib_MODULES += bsd.mod -bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd32.c loader/i386/bsd64.c loader/i386/bsd_helper.S loader/i386/bsd_trampoline.S -bsd_mod_CFLAGS = $(COMMON_CFLAGS) -bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) -bsd_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For datetime.mod -datetime_mod_SOURCES = lib/cmos_datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -include $(srcdir)/conf/i386.mk -include $(srcdir)/conf/common.mk diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk deleted file mode 100644 index c157aaf01..000000000 --- a/conf/i386-pc.rmk +++ /dev/null @@ -1,301 +0,0 @@ -# -*- makefile -*- - -COMMON_CFLAGS = -mrtd -mregparm=3 - -# Images. -pkglib_IMAGES = boot.img cdboot.img diskboot.img lnxboot.img pxeboot.img - -# For boot.img. -boot_img_SOURCES = boot/i386/pc/boot.S -boot_img_ASFLAGS = $(COMMON_ASFLAGS) -boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x7C00 -boot_img_FORMAT = binary - -# For pxeboot.img -pxeboot_img_SOURCES = boot/i386/pc/pxeboot.S -pxeboot_img_ASFLAGS = $(COMMON_ASFLAGS) -pxeboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x7C00 -pxeboot_img_FORMAT = binary - -# For diskboot.img. -diskboot_img_SOURCES = boot/i386/pc/diskboot.S -diskboot_img_ASFLAGS = $(COMMON_ASFLAGS) -diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x8000 -diskboot_img_FORMAT = binary - -# For lnxboot.img. -lnxboot_img_SOURCES = boot/i386/pc/lnxboot.S -lnxboot_img_ASFLAGS = $(COMMON_ASFLAGS) -lnxboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x6000 -lnxboot_img_FORMAT = binary - -# For cdboot.img. -cdboot_img_SOURCES = boot/i386/pc/cdboot.S -cdboot_img_ASFLAGS = $(COMMON_ASFLAGS) -cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x7C00 -cdboot_img_FORMAT = binary - -# For kernel.img. -pkglib_PROGRAMS = kernel.img -kernel_img_SOURCES = kern/i386/pc/startup.S \ - kern/i386/misc.S \ - kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/command.c kern/corecmd.c \ - kern/$(target_cpu)/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \ - kern/parser.c kern/partition.c \ - kern/i386/tsc.c kern/i386/pit.c \ - kern/generic/rtc_get_time_ms.c \ - kern/generic/millisleep.c \ - kern/env.c \ - term/i386/pc/console.c term/i386/vga_common.c \ - symlist.c -kernel_img_HEADERS += machine/biosdisk.h machine/vga.h machine/vbe.h \ - machine/pxe.h i386/pit.h machine/kernel.h -kernel_img_CFLAGS = $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x8200 $(COMMON_CFLAGS) - -# Utilities. -sbin_UTILITIES = grub-setup - -# For grub-setup. -util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h -grub_setup_SOURCES = gnulib/progname.c util/i386/pc/grub-setup.c \ - util/misc.c kern/emu/misc.c kern/emu/getroot.c \ - kern/emu/hostdisk.c kern/device.c kern/disk.c kern/err.c \ - kern/misc.c kern/partition.c kern/file.c \ - kern/emu/mm.c kern/fs.c kern/env.c kern/list.c fs/fshelp.c \ - \ - fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ - fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ - fs/nilfs2.c fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c \ - fs/sfs.c fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c \ - fs/afs_be.c fs/befs.c fs/befs_be.c fs/tar.c \ - \ - partmap/msdos.c partmap/bsdlabel.c partmap/sunpc.c \ - partmap/gpt.c \ - \ - disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/lvm.c \ - util/raid.c util/lvm.c \ - grub_setup_init.c - -sbin_SCRIPTS += grub-install -grub_install_SOURCES = util/grub-install.in - -bin_SCRIPTS += grub-mkrescue -grub_mkrescue_SOURCES = util/grub-mkrescue.in - -pkglib_MODULES = biosdisk.mod chain.mod \ - halt.mod \ - vbe.mod vbetest.mod vbeinfo.mod \ - vga.mod \ - aout.mod bsd.mod pxe.mod pxecmd.mod datetime.mod \ - ata_pthru.mod hdparm.mod \ - usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \ - efiemu.mod mmap.mod acpi.mod drivemap.mod - -# For drivemap.mod. -drivemap_mod_SOURCES = commands/i386/pc/drivemap.c \ - commands/i386/pc/drivemap_int13h.S -drivemap_mod_ASFLAGS = $(COMMON_ASFLAGS) -drivemap_mod_CFLAGS = $(COMMON_CFLAGS) -drivemap_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For efiemu.mod. -efiemu_mod_SOURCES = efiemu/main.c efiemu/i386/loadcore32.c \ - efiemu/i386/loadcore64.c efiemu/i386/pc/cfgtables.c \ - efiemu/mm.c efiemu/loadcore_common.c efiemu/symbols.c \ - efiemu/loadcore32.c efiemu/loadcore64.c \ - efiemu/prepare32.c efiemu/prepare64.c efiemu/pnvram.c \ - efiemu/i386/coredetect.c -efiemu_mod_CFLAGS = $(COMMON_CFLAGS) -efiemu_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For acpi.mod. -acpi_mod_SOURCES = commands/acpi.c commands/i386/pc/acpi.c -acpi_mod_CFLAGS = $(COMMON_CFLAGS) -acpi_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For mmap.mod. -mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \ - mmap/i386/pc/mmap.c mmap/i386/pc/mmap_helper.S -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For biosdisk.mod. -biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c -biosdisk_mod_CFLAGS = $(COMMON_CFLAGS) -biosdisk_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For chain.mod. -chain_mod_SOURCES = loader/i386/pc/chainloader.c -chain_mod_CFLAGS = $(COMMON_CFLAGS) -chain_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += linux16.mod -linux16_mod_SOURCES = loader/i386/pc/linux.c -linux16_mod_CFLAGS = $(COMMON_CFLAGS) -linux16_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += linux.mod -linux_mod_SOURCES = loader/i386/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += xnu.mod -xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c \ - loader/macho32.c loader/macho64.c loader/macho.c loader/xnu.c -xnu_mod_CFLAGS = $(COMMON_CFLAGS) -xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) -xnu_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For halt.mod. -halt_mod_SOURCES = commands/i386/pc/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For vbe.mod. -vbe_mod_SOURCES = video/i386/pc/vbe.c -vbe_mod_CFLAGS = $(COMMON_CFLAGS) -vbe_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For vbeinfo.mod. -vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c -vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS) -vbeinfo_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For vbetest.mod. -vbetest_mod_SOURCES = commands/i386/pc/vbetest.c -vbetest_mod_CFLAGS = $(COMMON_CFLAGS) -vbetest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For vga.mod. -vga_mod_SOURCES = video/i386/pc/vga.c -vga_mod_CFLAGS = $(COMMON_CFLAGS) -vga_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For aout.mod -aout_mod_SOURCES = loader/aout.c -aout_mod_CFLAGS = $(COMMON_CFLAGS) -aout_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For bsd.mod -bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd32.c loader/i386/bsd64.c loader/i386/bsd_helper.S loader/i386/bsd_trampoline.S -bsd_mod_CFLAGS = $(COMMON_CFLAGS) -bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) -bsd_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For usb.mod -usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c -usb_mod_CFLAGS = $(COMMON_CFLAGS) -usb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usbtest.mod -usbtest_mod_SOURCES = commands/usbtest.c -usbtest_mod_CFLAGS = $(COMMON_CFLAGS) -usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For uhci.mod -uhci_mod_SOURCES = bus/usb/uhci.c -uhci_mod_CFLAGS = $(COMMON_CFLAGS) -uhci_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ohci.mod -ohci_mod_SOURCES = bus/usb/ohci.c -ohci_mod_CFLAGS = $(COMMON_CFLAGS) -ohci_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usbms.mod -usbms_mod_SOURCES = disk/usbms.c -usbms_mod_CFLAGS = $(COMMON_CFLAGS) -usbms_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usb_keyboard.mod -usb_keyboard_mod_SOURCES = term/usb_keyboard.c -usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) -usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For pxe.mod -pxe_mod_SOURCES = fs/i386/pc/pxe.c -pxe_mod_CFLAGS = $(COMMON_CFLAGS) -pxe_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For pxecmd.mod -pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c -pxecmd_mod_CFLAGS = $(COMMON_CFLAGS) -pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For datetime.mod -datetime_mod_SOURCES = lib/cmos_datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ata_pthru.mod. -ata_pthru_mod_SOURCES = disk/ata_pthru.c -ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS) -ata_pthru_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For hdparm.mod. -hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c -hdparm_mod_CFLAGS = $(COMMON_CFLAGS) -hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For cmostest.mod -pkglib_MODULES += cmostest.mod -cmostest_mod_SOURCES = commands/i386/cmostest.c -cmostest_mod_CFLAGS = $(COMMON_CFLAGS) -cmostest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -ifeq ($(enable_efiemu), yes) - -efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) - -rm -f $@ -ifeq ($(TARGET_APPLE_CC), 1) - -rm -f $@.bin - $(TARGET_CC) -c -m32 -DELF32 -DAPPLE_CC -o $@.bin -Wall -Werror $< -nostdlib -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude - $(OBJCONV) -felf32 -nu -nd $@.bin $@ - -rm -f $@.bin -else - $(TARGET_CC) -c -m32 -DELF32 -o $@ -Wall -Werror $< -nostdlib -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude - if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi -endif - -efiemu64_c.o: efiemu/runtime/efiemu.c -ifeq ($(TARGET_APPLE_CC), 1) - $(TARGET_CC) -c -m64 -DAPPLE_CC=1 -DELF64 -o $@ -Wall -Werror $< -nostdlib -mno-red-zone -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude -else - $(TARGET_CC) -c -m64 -DELF64 -o $@ -Wall -Werror $< -nostdlib -mcmodel=large -mno-red-zone -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude -endif - -efiemu64_s.o: efiemu/runtime/efiemu.S - -rm -f $@ -ifeq ($(TARGET_APPLE_CC), 1) - $(TARGET_CC) -c -m64 -DAPPLE_CC=1 -DELF64 -o $@ -Wall -Werror $< -nostdlib -mno-red-zone -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude -else - $(TARGET_CC) -c -m64 -DELF64 -o $@ -Wall -Werror $< -nostdlib -mcmodel=large -mno-red-zone -O2 -I$(srcdir)/efiemu/runtime -I$(srcdir)/include -Iinclude -endif - -efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELF) - -rm -f $@ -ifeq ($(TARGET_APPLE_CC), 1) - -rm -f $@.bin - $(TARGET_CC) -m64 -o $@.bin -Wl,-r $^ -nostdlib - $(OBJCONV) -felf64 -nu -nd $@.bin $@ - -rm -f $@.bin -else - $(TARGET_CC) -m64 -o $@ -Wl,-r $^ -nostdlib - if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi -endif - -CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o -pkglib_DATA += efiemu32.o efiemu64.o - -endif - -include $(srcdir)/conf/i386.mk -include $(srcdir)/conf/common.mk diff --git a/conf/i386-qemu.rmk b/conf/i386-qemu.rmk deleted file mode 100644 index adb5f7f0f..000000000 --- a/conf/i386-qemu.rmk +++ /dev/null @@ -1,86 +0,0 @@ -# -*- makefile -*- - -COMMON_CFLAGS = -mrtd -mregparm=3 - -# Images. - -GRUB_KERNEL_MACHINE_LINK_ADDR = 0x8200 -GRUB_BOOT_MACHINE_LINK_ADDR = 0xffe00 - -pkglib_IMAGES += boot.img -boot_img_SOURCES = boot/i386/qemu/boot.S -boot_img_ASFLAGS = $(COMMON_ASFLAGS) -DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR) -boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_BOOT_MACHINE_LINK_ADDR) -boot_img_FORMAT = binary - -kern/i386/qemu/init.c_DEPENDENCIES = ascii.h - -pkglib_PROGRAMS += kernel.img -kernel_img_SOURCES = kern/i386/qemu/startup.S \ - kern/i386/misc.S \ - kern/i386/coreboot/init.c \ - kern/i386/qemu/init.c \ - kern/i386/qemu/mmap.c \ - kern/i386/halt.c \ - kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/command.c kern/corecmd.c \ - kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ - kern/i386/tsc.c kern/i386/pit.c \ - kern/generic/rtc_get_time_ms.c \ - kern/generic/millisleep.c \ - kern/env.c \ - term/i386/pc/vga_text.c term/i386/vga_common.c bus/pci.c \ - symlist.c -kernel_img_HEADERS += pci.h -kernel_img_CFLAGS = $(COMMON_CFLAGS) -DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) -kernel_img_FORMAT = binary - -sbin_SCRIPTS += grub-install -grub_install_SOURCES = util/grub-install.in - -bin_SCRIPTS += grub-mkrescue -grub_mkrescue_SOURCES = util/grub-mkrescue.in - -# Modules. -pkglib_MODULES = linux.mod aout.mod halt.mod datetime.mod mmap.mod - -# For mmap.mod. -mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For linux.mod. -linux_mod_SOURCES = loader/i386/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod. -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For aout.mod. -aout_mod_SOURCES = loader/aout.c -aout_mod_CFLAGS = $(COMMON_CFLAGS) -aout_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For bsd.mod -pkglib_MODULES += bsd.mod -bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd32.c loader/i386/bsd64.c loader/i386/bsd_helper.S loader/i386/bsd_trampoline.S -bsd_mod_CFLAGS = $(COMMON_CFLAGS) -bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) -bsd_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For datetime.mod -datetime_mod_SOURCES = lib/cmos_datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -include $(srcdir)/conf/i386.mk -include $(srcdir)/conf/common.mk diff --git a/conf/i386.rmk b/conf/i386.rmk deleted file mode 100644 index b1df584a6..000000000 --- a/conf/i386.rmk +++ /dev/null @@ -1,94 +0,0 @@ -# -*- makefile -*- - -pkglib_MODULES += cpuid.mod -cpuid_mod_SOURCES = commands/i386/cpuid.c -cpuid_mod_CFLAGS = $(COMMON_CFLAGS) -cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += at_keyboard.mod -at_keyboard_mod_SOURCES = term/at_keyboard.c -at_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) -at_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += vga_text.mod -vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c -vga_text_mod_CFLAGS = $(COMMON_CFLAGS) -vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += video_cirrus.mod -video_cirrus_mod_SOURCES = video/cirrus.c -video_cirrus_mod_CFLAGS = $(COMMON_CFLAGS) -video_cirrus_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += video_bochs.mod -video_bochs_mod_SOURCES = video/bochs.c -video_bochs_mod_CFLAGS = $(COMMON_CFLAGS) -video_bochs_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += relocator.mod -relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S -relocator_mod_CFLAGS = $(COMMON_CFLAGS) -relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) -relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += ata.mod -ata_mod_SOURCES = disk/ata.c -ata_mod_CFLAGS = $(COMMON_CFLAGS) -ata_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For setpci.mod -pkglib_MODULES += setpci.mod -setpci_mod_SOURCES = commands/setpci.c -setpci_mod_CFLAGS = $(COMMON_CFLAGS) -setpci_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += multiboot.mod -multiboot_mod_SOURCES = loader/multiboot.c loader/i386/multiboot_mbi.c -multiboot_mod_CFLAGS = $(COMMON_CFLAGS) -multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) - -pkglib_MODULES += multiboot2.mod -multiboot2_mod_SOURCES = loader/multiboot.c loader/multiboot_mbi2.c -multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 -multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For serial.mod. -pkglib_MODULES += serial.mod -serial_mod_SOURCES = term/serial.c -serial_mod_CFLAGS = $(COMMON_CFLAGS) -serial_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# On qemu it's compiled in -ifneq ($(platform), qemu) -# For pci.mod -pkglib_MODULES += pci.mod -pci_mod_SOURCES = bus/pci.c -pci_mod_CFLAGS = $(COMMON_CFLAGS) -pci_mod_LDFLAGS = $(COMMON_LDFLAGS) -endif - -# For cs5536.mod -pkglib_MODULES += cs5536.mod -cs5536_mod_SOURCES = bus/cs5536.c -cs5536_mod_CFLAGS = $(COMMON_CFLAGS) -cs5536_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For lspci.mod -pkglib_MODULES += lspci.mod -lspci_mod_SOURCES = commands/lspci.c -lspci_mod_CFLAGS = $(COMMON_CFLAGS) -lspci_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For play.mod. -pkglib_MODULES += play.mod -play_mod_SOURCES = commands/i386/pc/play.c -play_mod_CFLAGS = $(COMMON_CFLAGS) -play_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For iorw.mod. -pkglib_MODULES += iorw.mod -iorw_mod_SOURCES = commands/iorw.c -iorw_mod_CFLAGS = $(COMMON_CFLAGS) -iorw_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/mips-qemu-mips.rmk b/conf/mips-qemu-mips.rmk deleted file mode 100644 index be2b9f555..000000000 --- a/conf/mips-qemu-mips.rmk +++ /dev/null @@ -1,28 +0,0 @@ -# -*- makefile -*- -LINK_BASE = 0x80010000 -target_machine=qemu-mips -COMMON_CFLAGS += -march=mips3 -COMMON_ASFLAGS += -march=mips3 -include $(srcdir)/conf/mips.mk - -pkglib_PROGRAMS = kernel.img -kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ - kern/main.c kern/device.c kern/$(target_cpu)/init.c \ - kern/$(target_cpu)/$(target_machine)/init.c \ - kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/command.c kern/corecmd.c \ - kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ - kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c kern/time.c \ - symlist.c kern/$(target_cpu)/cache.S -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic -kernel_img_FORMAT = binary - -# For serial.mod. -pkglib_MODULES += serial.mod -serial_mod_SOURCES = term/serial.c -serial_mod_CFLAGS = $(COMMON_CFLAGS) -serial_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk deleted file mode 100644 index deb6dd33f..000000000 --- a/conf/mips-yeeloong.rmk +++ /dev/null @@ -1,125 +0,0 @@ -# -*- makefile -*- -LINK_BASE = 0x80200000 -target_machine=yeeloong -COMMON_CFLAGS += -march=mips3 -COMMON_ASFLAGS += -march=mips3 - -kernel_img_HEADERS += pci.h bitmap.h video.h gfxterm.h font.h \ - bitmap_scale.h bufio.h cs5536.h machine/pci.h - -include $(srcdir)/conf/mips.mk - -pkglib_PROGRAMS = kernel.img -kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ - kern/main.c kern/device.c kern/$(target_cpu)/init.c \ - kern/$(target_cpu)/$(target_machine)/init.c \ - kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/command.c kern/corecmd.c \ - kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ - kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c kern/time.c \ - kern/$(target_cpu)/cache.S \ - \ - term/at_keyboard.c \ - font/font_cmd.c font/font.c io/bufio.c \ - video/video.c video/fb/video_fb.c video/fb/fbblit.c \ - video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \ - video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \ - term/gfxterm.c commands/extcmd.c lib/arg.c \ - bus/cs5536.c term/serial.c term/terminfo.c term/tparm.c \ - symlist.c -kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic -kernel_img_FORMAT = binary - -pkglib_IMAGES += fwstart.img -fwstart_img_SOURCES = boot/$(target_cpu)/$(target_machine)/fwstart.S -fwstart_img_CFLAGS = $(COMMON_CFLAGS) -fwstart_img_ASFLAGS = $(COMMON_ASFLAGS) -fwstart_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ - -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic -fwstart_img_FORMAT = binary - -# For ata.mod. -pkglib_MODULES += ata.mod -ata_mod_SOURCES = disk/ata.c -ata_mod_CFLAGS = $(COMMON_CFLAGS) -ata_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For lspci.mod -pkglib_MODULES += lspci.mod -lspci_mod_SOURCES = commands/lspci.c -lspci_mod_CFLAGS = $(COMMON_CFLAGS) -lspci_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ata_pthru.mod. -pkglib_MODULES += ata_pthru.mod -ata_pthru_mod_SOURCES = disk/ata_pthru.c -ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS) -ata_pthru_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For mmap.mod. -pkglib_MODULES += mmap.mod -mmap_mod_SOURCES = mmap/mmap.c mmap/mips/yeeloong/uppermem.c -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) - -# For datetime.mod -pkglib_MODULES += datetime.mod -datetime_mod_SOURCES = lib/cmos_datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For lsspd.mod -pkglib_MODULES += lsspd.mod -lsspd_mod_SOURCES = commands/mips/yeeloong/lsspd.c -lsspd_mod_CFLAGS = $(COMMON_CFLAGS) -lsspd_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += linux.mod -linux_mod_SOURCES = loader/$(target_cpu)/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_ASFLAGS = $(COMMON_ASFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod. -pkglib_MODULES += halt.mod -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usb.mod -pkglib_MODULES += usb.mod -usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c -usb_mod_CFLAGS = $(COMMON_CFLAGS) -usb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usbtest.mod -pkglib_MODULES += usbtest.mod -usbtest_mod_SOURCES = commands/usbtest.c -usbtest_mod_CFLAGS = $(COMMON_CFLAGS) -usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For ohci.mod -pkglib_MODULES += ohci.mod -ohci_mod_SOURCES = bus/usb/ohci.c -ohci_mod_CFLAGS = $(COMMON_CFLAGS) -ohci_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usbms.mod -pkglib_MODULES += usbms.mod -usbms_mod_SOURCES = disk/usbms.c -usbms_mod_CFLAGS = $(COMMON_CFLAGS) -usbms_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For usb_keyboard.mod -pkglib_MODULES += usb_keyboard.mod -usb_keyboard_mod_SOURCES = term/usb_keyboard.c -usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) -usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) - -sbin_SCRIPTS += grub-install -grub_install_SOURCES = util/grub-install.in diff --git a/conf/mips.rmk b/conf/mips.rmk deleted file mode 100644 index 26c516fc4..000000000 --- a/conf/mips.rmk +++ /dev/null @@ -1,27 +0,0 @@ - -# -*- makefile -*- - -COMMON_CFLAGS += -mexplicit-relocs -mflush-func=grub_cpu_flush_cache - -# Images. -kernel_img_HEADERS += cpu/cache.h - -# Scripts. -sbin_SCRIPTS = -bin_SCRIPTS = - -# For relocator.mod. -pkglib_MODULES += relocator.mod -relocator_mod_SOURCES = lib/$(target_cpu)/relocator.c lib/$(target_cpu)/relocator_asm.S -relocator_mod_CFLAGS = $(COMMON_CFLAGS) -relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) -relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += multiboot2.mod -multiboot2_mod_SOURCES = loader/multiboot.c \ - loader/multiboot_mbi2.c -multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 -multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) - -include $(srcdir)/conf/common.mk diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk deleted file mode 100644 index 3ec5ec906..000000000 --- a/conf/powerpc-ieee1275.rmk +++ /dev/null @@ -1,68 +0,0 @@ - -# -*- makefile -*- - -# Images. - -kernel_img_HEADERS += ieee1275/ieee1275.h - -# Programs -pkglib_PROGRAMS = kernel.img - -kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ - kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/command.c kern/corecmd.c \ - kern/ieee1275/init.c \ - kern/ieee1275/mmap.c \ - term/ieee1275/ofconsole.c term/terminfo.c term/tparm.c \ - kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ - kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ - kern/generic/millisleep.c kern/time.c \ - symlist.c kern/$(target_cpu)/cache.S -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic - -# Scripts. -sbin_SCRIPTS = grub-install -bin_SCRIPTS = grub-mkrescue - -# For grub-install. -grub_install_SOURCES = util/ieee1275/grub-install.in - -# For grub-mkrescue. -grub_mkrescue_SOURCES = util/powerpc/ieee1275/grub-mkrescue.in - -# Modules. -pkglib_MODULES += ieee1275_fb.mod -ieee1275_fb_mod_SOURCES = video/ieee1275.c -ieee1275_fb_mod_CFLAGS = $(COMMON_CFLAGS) -ieee1275_fb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For linux.mod. -pkglib_MODULES += linux.mod -linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For suspend.mod -pkglib_MODULES += suspend.mod -suspend_mod_SOURCES = commands/ieee1275/suspend.c -suspend_mod_CFLAGS = $(COMMON_CFLAGS) -suspend_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod -pkglib_MODULES += halt.mod -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For datetime.mod -pkglib_MODULES += datetime.mod -datetime_mod_SOURCES = lib/ieee1275/datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -include $(srcdir)/conf/common.mk diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk deleted file mode 100644 index d343ac349..000000000 --- a/conf/sparc64-ieee1275.rmk +++ /dev/null @@ -1,104 +0,0 @@ - -# -*- makefile -*- - -COMMON_CFLAGS = -mno-app-regs -COMMON_LDFLAGS = -melf64_sparc -mno-relax - -# Images. -pkglib_IMAGES = boot.img diskboot.img -pkglib_PROGRAMS = kernel.img - -# For boot.img. -boot_img_SOURCES = boot/sparc64/ieee1275/boot.S -boot_img_ASFLAGS = $(COMMON_ASFLAGS) -boot_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,0x4000 -boot_img_FORMAT = a.out-sunos-big - -# For diskboot.img. -diskboot_img_SOURCES = boot/sparc64/ieee1275/diskboot.S -diskboot_img_ASFLAGS = $(COMMON_ASFLAGS) -diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,0x4200 -diskboot_img_FORMAT = binary - -kernel_img_HEADERS += ieee1275/ieee1275.h cpu/ieee1275/ieee1275.h -kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ - kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/command.c kern/corecmd.c \ - kern/sparc64/ieee1275/ieee1275.c \ - kern/sparc64/ieee1275/init.c \ - kern/ieee1275/mmap.c \ - term/ieee1275/ofconsole.c \ - kern/ieee1275/openfw.c term/terminfo.c term/tparm.c \ - disk/ieee1275/ofdisk.c \ - kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ - kern/generic/millisleep.c kern/time.c \ - symlist.c kern/$(target_cpu)/cache.S -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += -nostdlib -Wl,-N,-Ttext,0x4400,-Bstatic,-melf64_sparc -kernel_img_FORMAT = binary - -# Utilities. -sbin_UTILITIES = grub-setup grub-ofpathname - -# For grub-setup. -util/sparc64/ieee1275/grub-setup.c_DEPENDENCIES = grub_setup_init.h -grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c \ - util/ieee1275/ofpath.c util/misc.c kern/emu/hostdisk.c \ - kern/emu/misc.c kern/emu/getroot.c kern/emu/mm.c kern/device.c \ - kern/disk.c kern/err.c kern/misc.c \ - kern/partition.c kern/file.c kern/fs.c kern/env.c kern/list.c \ - fs/fshelp.c \ - \ - fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ - fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ - fs/nilfs2.c fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c \ - fs/sfs.c fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c \ - fs/afs_be.c fs/befs.c fs/befs_be.c fs/tar.c \ - \ - partmap/amiga.c partmap/apple.c partmap/msdos.c \ - partmap/bsdlabel.c partmap/sun.c partmap/acorn.c \ - \ - disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/lvm.c util/raid.c \ - util/lvm.c gnulib/progname.c grub_setup_init.c - -# For grub-ofpathname. -grub_ofpathname_SOURCES = util/ieee1275/grub-ofpathname.c \ - util/ieee1275/ofpath.c util/misc.c kern/emu/misc.c \ - gnulib/progname.c - -# Scripts. -sbin_SCRIPTS = grub-install - -# For grub-install. -grub_install_SOURCES = util/grub-install.in - -# Modules. -pkglib_MODULES += ieee1275_fb.mod -ieee1275_fb_mod_SOURCES = video/ieee1275.c -ieee1275_fb_mod_CFLAGS = $(COMMON_CFLAGS) -ieee1275_fb_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For linux.mod. -pkglib_MODULES += linux.mod -linux_mod_SOURCES = loader/sparc64/ieee1275/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For halt.mod. -pkglib_MODULES += halt.mod -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For datetime.mod -pkglib_MODULES += datetime.mod -datetime_mod_SOURCES = lib/ieee1275/datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -include $(srcdir)/conf/common.mk diff --git a/conf/tests.rmk b/conf/tests.rmk deleted file mode 100644 index 9af2f8f86..000000000 --- a/conf/tests.rmk +++ /dev/null @@ -1,94 +0,0 @@ -# -*- makefile -*- - -# For grub-shell -grub-shell: tests/util/grub-shell.in config.status - ./config.status --file=$@:$< - chmod +x $@ -check_SCRIPTS += grub-shell -CLEANFILES += grub-shell - -# For grub-shell-tester -grub-shell-tester: tests/util/grub-shell-tester.in config.status - ./config.status --file=$@:$< - chmod +x $@ -check_SCRIPTS += grub-shell-tester -CLEANFILES += grub-shell-tester - -pkglib_MODULES += functional_test.mod -functional_test_mod_SOURCES = tests/lib/functional_test.c tests/lib/test.c -functional_test_mod_CFLAGS = $(COMMON_CFLAGS) -functional_test_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Rules for unit tests -check_UTILITIES += example_unit_test -example_unit_test_SOURCES = tests/example_unit_test.c kern/list.c kern/misc.c tests/lib/test.c tests/lib/unit_test.c -example_unit_test_CFLAGS = -Wno-format - -# Rules for functional tests -pkglib_MODULES += example_functional_test.mod -example_functional_test_mod_SOURCES = tests/example_functional_test.c -example_functional_test_mod_CFLAGS = -Wno-format $(COMMON_CFLAGS) -example_functional_test_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Rules for scripted tests -check_SCRIPTS += example_scripted_test -example_scripted_test_SOURCES = tests/example_scripted_test.in - -check_SCRIPTS += example_grub_script_test -example_grub_script_test_SOURCES = tests/example_grub_script_test.in - -# -# Rules for real tests -# - -check_SCRIPTS += grub_script_echo1 -grub_script_echo1_SOURCES = tests/grub_script_echo1.in - -check_SCRIPTS += grub_script_echo_keywords -grub_script_echo_keywords_SOURCES = tests/grub_script_echo_keywords.in - -check_SCRIPTS += grub_script_vars1 -grub_script_vars1_SOURCES = tests/grub_script_vars1.in - -check_SCRIPTS += grub_script_for1 -grub_script_for1_SOURCES = tests/grub_script_for1.in - -check_SCRIPTS += grub_script_while1 -grub_script_while1_SOURCES = tests/grub_script_while1.in - -check_SCRIPTS += grub_script_if -grub_script_if_SOURCES = tests/grub_script_if.in - -check_SCRIPTS += grub_script_blanklines -grub_script_blanklines_SOURCES = tests/grub_script_blanklines.in - -check_SCRIPTS += grub_script_final_semicolon -grub_script_final_semicolon_SOURCES = tests/grub_script_final_semicolon.in - -check_SCRIPTS += grub_script_dollar -grub_script_dollar_SOURCES = tests/grub_script_dollar.in - -check_SCRIPTS += grub_script_comments -grub_script_comments_SOURCES = tests/grub_script_comments.in - -# List of tests to execute on "make check" -# SCRIPTED_TESTS = example_scripted_test -# SCRIPTED_TESTS += example_grub_script_test -# UNIT_TESTS = example_unit_test -# FUNCTIONAL_TESTS = example_functional_test.mod - -SCRIPTED_TESTS = grub_script_echo1 -SCRIPTED_TESTS += grub_script_echo_keywords -SCRIPTED_TESTS += grub_script_vars1 -SCRIPTED_TESTS += grub_script_for1 -SCRIPTED_TESTS += grub_script_while1 -SCRIPTED_TESTS += grub_script_if -SCRIPTED_TESTS += grub_script_blanklines -SCRIPTED_TESTS += grub_script_final_semicolon -SCRIPTED_TESTS += grub_script_dollar -SCRIPTED_TESTS += grub_script_comments - -# dependencies between tests and testing-tools -$(SCRIPTED_TESTS): grub-shell grub-shell-tester -$(FUNCTIONAL_TESTS): functional_test.mod - diff --git a/conf/x86-efi.rmk b/conf/x86-efi.rmk deleted file mode 100644 index f9f07684e..000000000 --- a/conf/x86-efi.rmk +++ /dev/null @@ -1,112 +0,0 @@ -# -*- makefile -*- - -# Scripts. -sbin_SCRIPTS = grub-install - -# For grub-install. -grub_install_SOURCES = util/i386/efi/grub-install.in - -bin_SCRIPTS += grub-mkrescue -grub_mkrescue_SOURCES = util/grub-mkrescue.in - -# Modules. -pkglib_PROGRAMS = kernel.img -pkglib_MODULES = chain.mod appleldr.mod \ - linux.mod halt.mod \ - datetime.mod loadbios.mod \ - fixvideo.mod mmap.mod acpi.mod - -# For kernel.img. -kernel_img_RELOCATABLE = yes -kernel_img_SOURCES = kern/$(target_cpu)/efi/startup.S kern/main.c kern/device.c \ - kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/term.c \ - kern/rescue_parser.c kern/rescue_reader.c \ - kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ - kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ - term/efi/console.c disk/efi/efidisk.c \ - kern/time.c kern/list.c kern/command.c kern/corecmd.c \ - kern/i386/tsc.c kern/i386/pit.c \ - kern/generic/rtc_get_time_ms.c \ - kern/generic/millisleep.c -ifeq ($(target_cpu),x86_64) -kernel_img_SOURCES += kern/x86_64/efi/callwrap.S -endif -kernel_img_HEADERS += efi/efi.h efi/time.h efi/disk.h i386/pit.h -kernel_img_CFLAGS = $(COMMON_CFLAGS) -kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS += $(COMMON_LDFLAGS) - -# For acpi.mod. -acpi_mod_SOURCES = commands/acpi.c commands/efi/acpi.c -acpi_mod_CFLAGS = $(COMMON_CFLAGS) -acpi_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For mmap.mod. -mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \ - mmap/efi/mmap.c -mmap_mod_CFLAGS = $(COMMON_CFLAGS) -mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For chain.mod. -chain_mod_SOURCES = loader/efi/chainloader.c -chain_mod_CFLAGS = $(COMMON_CFLAGS) -chain_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For appleldr.mod. -appleldr_mod_SOURCES = loader/efi/appleloader.c -appleldr_mod_CFLAGS = $(COMMON_CFLAGS) -appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For linux.mod. -ifeq ($(target_cpu), x86_64) -linux_mod_SOURCES = loader/i386/efi/linux.c loader/i386/linux_trampoline.S -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_ASFLAGS = $(COMMON_ASFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) -else -linux_mod_SOURCES = loader/i386/efi/linux.c -linux_mod_CFLAGS = $(COMMON_CFLAGS) -linux_mod_ASFLAGS = $(COMMON_ASFLAGS) -linux_mod_LDFLAGS = $(COMMON_LDFLAGS) -endif - -# For halt.mod. -halt_mod_SOURCES = commands/halt.c -halt_mod_CFLAGS = $(COMMON_CFLAGS) -halt_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For datetime.mod -datetime_mod_SOURCES = lib/efi/datetime.c -datetime_mod_CFLAGS = $(COMMON_CFLAGS) -datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For loadbios.mod -loadbios_mod_SOURCES = commands/efi/loadbios.c -loadbios_mod_CFLAGS = $(COMMON_CFLAGS) -loadbios_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For fixvideo.mod -fixvideo_mod_SOURCES = commands/efi/fixvideo.c -fixvideo_mod_CFLAGS = $(COMMON_CFLAGS) -fixvideo_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += efi_uga.mod -efi_uga_mod_SOURCES = video/efi_uga.c -efi_uga_mod_CFLAGS = $(COMMON_CFLAGS) -efi_uga_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += efi_gop.mod -efi_gop_mod_SOURCES = video/efi_gop.c -efi_gop_mod_CFLAGS = $(COMMON_CFLAGS) -efi_gop_mod_LDFLAGS = $(COMMON_LDFLAGS) - -pkglib_MODULES += xnu.mod -xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c \ - loader/macho32.c loader/macho64.c loader/macho.c loader/xnu.c -xnu_mod_CFLAGS = $(COMMON_CFLAGS) -xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) -xnu_mod_ASFLAGS = $(COMMON_ASFLAGS) - -include $(srcdir)/conf/i386.mk -include $(srcdir)/conf/common.mk diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk deleted file mode 100644 index 200621280..000000000 --- a/conf/x86_64-efi.rmk +++ /dev/null @@ -1,5 +0,0 @@ -# -*- makefile -*- - -COMMON_LDFLAGS = -melf_x86_64 - -include $(srcdir)/conf/x86-efi.mk diff --git a/config.h.in b/config.h.in new file mode 100644 index 000000000..6d7d95dec --- /dev/null +++ b/config.h.in @@ -0,0 +1,42 @@ +#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) +#include +#define NESTED_FUNC_ATTR +#else +/* Define if C symbols get an underscore after compilation. */ +#define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ +/* Define it to \"addr32\" or \"addr32;\" to make GAS happy. */ +#define ADDR32 @ADDR32@ +/* Define it to \"data32\" or \"data32;\" to make GAS happy. */ +#define DATA32 @DATA32@ +/* Define it to one of __bss_start, edata and _edata. */ +#define BSS_START_SYMBOL @BSS_START_SYMBOL@ +/* Define it to either end or _end. */ +#define END_SYMBOL @END_SYMBOL@ +/* Name of package. */ +#define PACKAGE "@PACKAGE@" +/* Version number of package. */ +#define VERSION "@VERSION@" +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_STRING@" +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" +/* Default boot directory name" */ +#define GRUB_BOOT_DIR_NAME "@bootdirname@" +/* Default grub directory name */ +#define GRUB_DIR_NAME "@grubdirname@" +/* Define to 1 if GCC generates calls to __enable_execute_stack(). */ +#define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@ +/* Define to 1 if GCC generates calls to __register_frame_info(). */ +#define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@ + +#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 c1aa44e65..1d0333a74 100644 --- a/configure.ac +++ b/configure.ac @@ -1,3 +1,5 @@ +# -*- autoconf -*- + # Process this file with autoconf to produce a configure script. # Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. @@ -30,17 +32,22 @@ 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],[0],[bug-grub@gnu.org]) dnl version is filled by debian/rules -AM_INIT_AUTOMAKE() -AC_PREREQ(2.60) -AC_CONFIG_SRCDIR([include/grub/dl.h]) -AC_CONFIG_HEADER([config.h]) + +AC_CONFIG_AUX_DIR([build-aux]) + +# We don't want -g -O2 by default in CFLAGS +: ${CFLAGS=""} # Checks for host and target systems. AC_CANONICAL_HOST AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE() +AC_PREREQ(2.60) +AC_CONFIG_SRCDIR([include/grub/dl.h]) +AC_CONFIG_HEADER([config-util.h]) + # Program name transformations AC_ARG_PROGRAM @@ -49,19 +56,28 @@ if test "x$TARGET_CFLAGS" = x; then TARGET_CFLAGS="$TARGET_CFLAGS -Os" fi +# 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=mips; - TARGET_CFLAGS="$TARGET_CFLAGS -DGRUB_CPU_MIPSEL=1"; - CFLAGS="$CFLAGS -DGRUB_CPU_MIPSEL=1"; + target_cpu=mips; + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1"; ;; mips|mips64) - target_cpu=mips; - TARGET_CFLAGS="$TARGET_CFLAGS -DGRUB_CPU_MIPS=1"; - CFLAGS="$CFLAGS -DGRUB_CPU_MIPS=1"; + target_cpu=mips; + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS=1"; ;; esac @@ -136,25 +152,24 @@ case "$host_os" in esac case "$platform" in - coreboot) machine_CFLAGS="-DGRUB_MACHINE_COREBOOT=1" ;; - multiboot) machine_CFLAGS="-DGRUB_MACHINE_MULTIBOOT=1" ;; - efi) machine_CFLAGS="-DGRUB_MACHINE_EFI=1" ;; - ieee1275) machine_CFLAGS="-DGRUB_MACHINE_IEEE1275=1" ;; - qemu) machine_CFLAGS="-DGRUB_MACHINE_QEMU=1" ;; - pc) machine_CFLAGS="-DGRUB_MACHINE_PCBIOS=1" ;; - emu) machine_CFLAGS="-DGRUB_MACHINE_EMU=1" ;; - yeeloong) machine_CFLAGS="-DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; - qemu-mips) machine_CFLAGS="-DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; + 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" ;; + ieee1275) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_IEEE1275=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" ;; + yeeloong) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; + qemu-mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; esac case "$target_cpu" in - mips) machine_CFLAGS="$machine_CFLAGS -DGRUB_MACHINE_MIPS=1" ;; - sparc64) machine_CFLAGS="$machine_CFLAGS -DGRUB_MACHINE_SPARC64=1" ;; + mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; + sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;; esac -machine_CFLAGS="$machine_CFLAGS -DMACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" +machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" -CFLAGS="$CFLAGS $machine_CFLAGS" -TARGET_ASFLAGS="$TARGET_ASFLAGS $machine_CFLAGS" -TARGET_CFLAGS="$TARGET_CFLAGS $machine_CFLAGS" +HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS" +TARGET_CPPFLAGS="$TARGET_CPPFLAGS $machine_CPPFLAGS" AC_SUBST(host_cpu) AC_SUBST(host_os) @@ -163,6 +178,23 @@ AC_SUBST(host_kernel) AC_SUBST(target_cpu) AC_SUBST(platform) +# Define default variables +case "$host_os" in + netbsd* | openbsd*) + # Because /boot is used for the boot block in NetBSD and OpenBSD, + bootdirname='' ;; + *) bootdirname='boot' ;; +esac +bootdirname=`echo "$bootdirname" | sed "$program_transform_name"` +AC_SUBST(bootdirname) +AC_DEFINE_UNQUOTED(GRUB_BOOT_DIR_NAME, "$bootdirname", + [Default boot directory name]") + +grubdirname=`echo "$PACKAGE" | sed "$program_transform_name"` +AC_SUBST(grubdirname) +AC_DEFINE_UNQUOTED(GRUB_DIR_NAME, "$grubdirname", + [Default grub directory name]) + # # Checks for build programs. # @@ -194,13 +226,16 @@ if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" AC_MSG_ERROR([qemu and yeeloong ports need unifont]) fi -AC_SUBST([FONT_SOURCE]) +AC_SUBST([FONT_SOURCE]) +AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_AWK AC_PROG_LEX +AC_PROG_YACC AC_PROG_MAKE_SET AC_PROG_MKDIR_P +AC_PROG_LN_S if test "x$LEX" = "x:"; then AC_MSG_ERROR([flex is not found]) @@ -214,7 +249,6 @@ else fi # These are not a "must". -AC_PATH_PROG(RUBY, ruby) AC_PATH_PROG(MAKEINFO, makeinfo) # @@ -222,6 +256,10 @@ AC_PATH_PROG(MAKEINFO, makeinfo) # AC_PROG_CC +gl_EARLY +AM_PROG_CC_C_O +AM_PROG_AS + # Must be GCC. test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required]) @@ -236,8 +274,8 @@ AC_CHECK_SIZEOF(long) grub_apple_cc if test x$grub_cv_apple_cc = xyes ; then - CFLAGS="$CFLAGS -DAPPLE_CC=1 -fnested-functions" - ASFLAGS="$ASFLAGS -DAPPLE_CC=1" + HOST_CPPFLAGS="$HOST_CPPFLAGS -DAPPLE_CC=1" + HOST_CFLAGS="$HOST_CFLAGS -fnested-functions" fi if test "x$cross_compiling" = xyes; then @@ -247,8 +285,16 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat getmntany) -AC_CHECK_HEADERS(libzfs.h libnvpair.h) +AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent) +AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h) + +AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default +#include +#include ]) + +AC_CHECK_MEMBERS([struct statfs.f_mntfromname],,,[$ac_includes_default +#include +#include ]) # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. @@ -264,6 +310,16 @@ AC_CHECK_HEADER([util.h], [ ]) AC_SUBST([LIBUTIL]) +# +# Check for host and build compilers. +# +HOST_CC=$CC +AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc], + [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.])]) + +# For gnulib. +gl_INIT + # # Check for target programs. # @@ -288,9 +344,10 @@ else AC_CHECK_TOOL(STRIP, strip) AC_CHECK_TOOL(NM, nm) fi +AC_SUBST(HOST_CC) +AC_SUBST(BUILD_CC) AC_SUBST(TARGET_CC) - # Test the C compiler for the target environment. tmp_CC="$CC" tmp_CFLAGS="$CFLAGS" @@ -304,8 +361,8 @@ LDFLAGS="$TARGET_LDFLAGS" LIBS="" # debug flags. -TARGET_CFLAGS="$TARGET_CFLAGS -Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \ - -Wundef -Wstrict-prototypes -g" +TARGET_CFLAGS="$TARGET_CFLAGS -Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes -Wundef -Wstrict-prototypes -g" +TARGET_CCASFLAGS="$TARGET_CCASFLAGS -g" # Force no alignment to save space on i386. if test "x$target_cpu" = xi386; then @@ -344,11 +401,29 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" fi +if test "${target_cpu}-${platform}" = mips-yeeloong; then + AC_CACHE_CHECK([whether -march=loongson2f works], [grub_cv_cc_march_loongson2f], [ + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -march=loongson2f" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_march_loongson2f=yes], + [grub_cv_cc_march_loongson2f=no]) + CFLAGS="$SAVE_CFLAGS" + ]) + + if test "x$grub_cv_cc_march_loongson2f" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -march=loongson2f" + else + TARGET_CFLAGS="$TARGET_CFLAGS -march=mips3" + fi +fi + grub_apple_target_cc if test x$grub_cv_apple_target_cc = xyes ; then - TARGET_CFLAGS="$TARGET_CFLAGS -DAPPLE_CC=1 -fnested-functions" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1" + TARGET_CFLAGS="$TARGET_CFLAGS -fnested-functions" + CFLAGS="$CFLAGS -DAPPLE_CC=1 -fnested-functions" - TARGET_ASFLAGS="$TARGET_ASFLAGS -DAPPLE_CC=1" TARGET_APPLE_CC=1 AC_CHECK_PROG([OBJCONV], [objconv], [objconv], []) if test "x$OBJCONV" = x ; then @@ -359,45 +434,41 @@ if test x$grub_cv_apple_target_cc = xyes ; then fi TARGET_IMG_LDSCRIPT= TARGET_IMG_CFLAGS="-static" - TARGET_IMG_LDFLAGS='-nostdlib -static -Wl,-preload -Wl,-segalign,20 -Wl,-image_base,' - TARGET_IMG_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20 -Wl,-image_base,' + 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" else TARGET_APPLE_CC=0 # Use linker script if present, otherwise use builtin -N script. -if test -f "${srcdir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"; then - TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc" - TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT} -Wl,-Ttext," - TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc -Wl,-Ttext," +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 -Wl,-Ttext,' - TARGET_IMG_LDFLAGS_AC='-Wl,-N -Wl,-Ttext,' + 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_IMG_LDSCRIPT) -AC_SUBST(TARGET_IMG_LDFLAGS) -AC_SUBST(TARGET_IMG_CFLAGS) - # 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='grub-pe2elf'; + cygwin) TARGET_OBJ2ELF='$(grub_utildir)/grub-pe2elf'; # FIXME: put proper test here - AC_DEFINE([NEED_REGISTER_FRAME_INFO], 1, - [Define to 1 if GCC generates calls to __register_frame_info()]) + NEED_REGISTER_FRAME_INFO=1 ;; - *) ;; + *) NEED_REGISTER_FRAME_INFO=0 ;; esac -AC_SUBST(TARGET_OBJ2ELF) AC_MSG_RESULT([$TARGET_OBJ2ELF]) - if test "x$target_m32" = x1; then # Force 32-bit mode. TARGET_CFLAGS="$TARGET_CFLAGS -m32" - TARGET_ASFLAGS="$TARGET_CFLAGS -m32" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32" TARGET_LDFLAGS="$TARGET_LDFLAGS -m32" TARGET_MODULE_FORMAT="elf32" fi @@ -405,7 +476,7 @@ fi if test "x$target_m64" = x1; then # Force 64-bit mode. TARGET_CFLAGS="$TARGET_CFLAGS -m64" - TARGET_ASFLAGS="$TARGET_ASFLAGS -m64" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64" TARGET_LDFLAGS="$TARGET_LDFLAGS -m64" TARGET_MODULE_FORMAT="elf64" fi @@ -475,13 +546,30 @@ if test x"$enable_werror" != xno ; then TARGET_CFLAGS="$TARGET_CFLAGS -Werror" fi -AC_SUBST(TARGET_CFLAGS) -AC_SUBST(TARGET_MODULE_FORMAT) +TARGET_CPP="$TARGET_CC -E" +TARGET_CCAS=$TARGET_CC + AC_SUBST(OBJCONV) +AC_SUBST(TARGET_CPP) +AC_SUBST(TARGET_CCAS) +AC_SUBST(TARGET_OBJ2ELF) AC_SUBST(TARGET_APPLE_CC) -AC_SUBST(TARGET_ASFLAGS) -AC_SUBST(TARGET_CPPFLAGS) +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" @@ -491,8 +579,11 @@ else CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100 -Wno-error" fi CPPFLAGS="$TARGET_CPPFLAGS" -LDFLAGS="$TARGET_LDFLAGS" +if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 ; then +LIBS= +else LIBS=-lgcc +fi grub_ASM_USCORE if test x$grub_cv_asm_uscore = xyes; then @@ -521,7 +612,7 @@ if test "x$target_cpu" = xi386; 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}8000 -Wl,--defsym,___main=0x8100" + 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 @@ -529,23 +620,20 @@ if test "x$target_cpu" = xi386; then CFLAGS="$TARGET_CFLAGS" grub_I386_ASM_PREFIX_REQUIREMENT grub_I386_ASM_ADDR32 - grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK -else - AC_DEFINE([NESTED_FUNC_ATTR], [], [Catch gcc bug]) fi -AH_BOTTOM([#if defined(__i386__) && !defined(GRUB_UTIL) -#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) -#else -#define NESTED_FUNC_ATTR -#endif]) - 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, [ CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib" @@ -583,6 +671,20 @@ if test x"$grub_cv_cc_isystem" = xyes ; then fi fi +AC_CACHE_CHECK([whether -Wno-trampolines work], [grub_cv_cc_wnotrampolines], [ + SAVED_CFLAGS="$CFLAGS" + CFLAGS="$TARGET_CFLAGS -Wno-trampolines" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +int va_arg_func (int fixed, va_list args);]], [[]])], + [grub_cv_cc_wnotrampolines=yes], + [grub_cv_cc_wnotrampolines=no]) + CFLAGS="$SAVED_CFLAGS" +]) + +if test x"$grub_cv_cc_wnotrampolines" = xyes ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Wno-trampolines" +fi + # Restore the flags. CC="$tmp_CC" CFLAGS="$tmp_CFLAGS" @@ -613,10 +715,6 @@ AC_ARG_ENABLE([grub-emu-pci], [AS_HELP_STRING([--enable-grub-emu-pci], [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])]) -AC_ARG_ENABLE([grub-emu-modules], - [AS_HELP_STRING([--enable-grub-emu-modules], - [Support module loading in `grub-emu' debugging utility (default=no)])]) - if test "$platform" = emu; then missing_ncurses= [# Check for curses libraries.] @@ -635,21 +733,8 @@ 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_modules" = xyes ; then - TARGET_NO_MODULES=no -else - TARGET_NO_MODULES=yes -fi -AC_SUBST(TARGET_NO_MODULES) - -if test "$TARGET_NO_MODULES" = yes ; then - # Do not convert modules, otherwise linkage may fail (Cygwin only). - # FIXME: Should be checked above before TARGET_OBJ2ELF is set first. - TARGET_OBJ2ELF= -fi - -if test x"$enable_grub_emu_usb" = xno ; then - grub_emu_usb_excuse="explicitly disabled" +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 @@ -733,19 +818,6 @@ AC_SUBST([enable_grub_emu_usb]) AC_SUBST([enable_grub_emu_pci]) fi -AC_ARG_ENABLE([grub-fstest], - [AS_HELP_STRING([--enable-grub-fstest], - [build and install the `grub-fstest' debugging utility (default=guessed)])]) -if test x"$enable_grub_fstest" = xno ; then - grub_fstest_excuse="explicitly disabled" -fi -if test x"$grub_fstest_excuse" = x ; then -enable_grub_fstest=yes -else -enable_grub_fstest=no -fi -AC_SUBST([enable_grub_fstest]) - AC_ARG_ENABLE([grub-mkfont], [AS_HELP_STRING([--enable-grub-mkfont], [build and install the `grub-mkfont' utility (default=guessed)])]) @@ -759,12 +831,12 @@ if test x"$grub_mkfont_excuse" = x ; then if test "x$FREETYPE" = x ; then grub_mkfont_excuse=["need freetype2 library"] fi - freetype_cflags=`freetype-config --cflags` - freetype_libs=`freetype-config --libs` fi if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. + freetype_cflags=`freetype-config --cflags` + freetype_libs=`freetype-config --libs` SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $freetype_cflags" AC_CHECK_HEADERS([ft2build.h], [], @@ -793,23 +865,99 @@ fi if test x"$device_mapper_excuse" = x ; then # Check for device-mapper library. - AC_CHECK_LIB([devmapper], [dm_task_create], - [LDFLAGS="$LDFLAGS -ldevmapper" - AC_DEFINE([HAVE_DEVICE_MAPPER], [1], - [Define to 1 if you have the devmapper library.])], + AC_CHECK_LIB([devmapper], [dm_task_create], [], [device_mapper_excuse="need devmapper library"]) fi +if test x"$device_mapper_excuse" = x ; then + # Check for device-mapper library. + AC_CHECK_LIB([devmapper], [dm_log_with_errno_init], + [], + [device_mapper_excuse="need devmapper library"]) +fi + +if test x"$device_mapper_excuse" = x ; then + LIBDEVMAPPER="-ldevmapper"; + AC_DEFINE([HAVE_DEVICE_MAPPER], [1], + [Define to 1 if you have the devmapper library.]) +fi + +AC_SUBST([LIBDEVMAPPER]) + +AC_CHECK_LIB([lzma], [lzma_code], + [LIBLZMA="-llzma" + AC_DEFINE([HAVE_LIBLZMA], [1], + [Define to 1 if you have the LZMA library.])],) +AC_SUBST([LIBLZMA]) + AC_CHECK_LIB([zfs], [libzfs_init], - [LDFLAGS="$LDFLAGS -lzfs" + [LIBZFS="-lzfs" AC_DEFINE([HAVE_LIBZFS], [1], [Define to 1 if you have the ZFS library.])],) +AC_SUBST([LIBZFS]) + AC_CHECK_LIB([nvpair], [nvlist_print], - [LDFLAGS="$LDFLAGS -lnvpair" + [LIBNVPAIR="-lnvpair" AC_DEFINE([HAVE_LIBNVPAIR], [1], [Define to 1 if you have the NVPAIR library.])],) +AC_SUBST([LIBNVPAIR]) -AC_SUBST(ASFLAGS) +LIBS="" + +pkglibrootdir='$(libdir)'/`echo $PACKAGE | sed "$program_transform_name"` +AC_SUBST(pkglibrootdir) + +AC_SUBST([FONT_SOURCE]) +AS_IF([test x$target_cpu = xi386 -a x$platform = xqemu], + [AC_SUBST([GRUB_BOOT_MACHINE_LINK_ADDR], 0xffe00)]) +AS_IF([test x$TARGET_APPLE_CC = x1], + [AC_SUBST([USE_APPLE_CC_FIXES], yes)]) + +AC_SUBST(HAVE_ASM_USCORE) +AC_SUBST(ADDR32) +AC_SUBST(DATA32) +AC_SUBST(BSS_START_SYMBOL) +AC_SUBST(END_SYMBOL) +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) +AC_SUBST(NEED_ENABLE_EXECUTE_STACK) +AC_SUBST(NEED_REGISTER_FRAME_INFO) + +# +# Automake conditionals +# + +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]) +AM_CONDITIONAL([COND_i386_qemu], [test x$target_cpu = xi386 -a x$platform = xqemu]) +AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_i386_coreboot], [test x$target_cpu = xi386 -a x$platform = xcoreboot]) +AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = xmultiboot]) +AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform = xyeeloong]) +AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips]) +AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips]) + +AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) +AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) +AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd]) +AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows]) +AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd]) + +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_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) +AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) +AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) +AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) + +AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) # Output files. grub_CHECK_LINK_DIR @@ -827,8 +975,16 @@ else cp -rp $srcdir/include/grub/$target_cpu/$platform include/grub/machine 2>/dev/null fi fi -AC_CONFIG_FILES([Makefile gensymlist.sh genkernsyms.sh]) + +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([grub-core/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]) AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) +AC_CONFIG_FILES([config.h]) + AC_OUTPUT [ echo "*******************************************************" @@ -850,11 +1006,11 @@ echo PCI support for grub-emu: Yes else echo PCI support for grub-emu: No "($grub_emu_pci_excuse)" fi -if [ x"$TARGET_NO_MODULES" = xno ]; then -echo Module support for grub-emu: Yes -else -echo Module support for grub-emu: No fi +if test x"$device_mapper_excuse" = x ; then +echo With devmapper support: Yes +else +echo With devmapper support: No "($device_mapper_excuse)" fi if [ x"$enable_mm_debug" = xyes ]; then echo With memory debugging: Yes @@ -866,11 +1022,6 @@ echo efiemu runtime: Yes else echo efiemu runtime: No "($efiemu_excuse)" fi -if [ x"$grub_fstest_excuse" = x ]; then -echo grub-fstest: Yes -else -echo grub-fstest: No "($grub_fstest_excuse)" -fi if [ x"$grub_mkfont_excuse" = x ]; then echo grub-mkfont: Yes else diff --git a/debian/changelog b/debian/changelog index 1c93e1dac..ef90107bc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,42 @@ -grub2 (1.98+20100804-9) UNRELEASED; urgency=low +grub2 (1.99~20101116-1) UNRELEASED; urgency=low + * New Bazaar snapshot. Too many changes to list in full, but some of the + more user-visible ones are as follows: + - GRUB script: + + Function parameters, "break", "continue", "shift", "setparams", + "return", and "!". + + "export" command supports multiple variable names. + + Multi-line quoted strings support. + + Wildcard expansion. + - sendkey support. + - USB hotunplugging and USB serial support. + - Rename CD-ROM to cd on BIOS. + - Add new --boot-directory option to grub-install, grub-reboot, and + grub-set-default; the old --root-directory option is still accepted + but was often confusing. + - Basic btrfs detection/UUID support (but no file reading yet). + - bash-completion for utilities. + - If a device is listed in device.map, always assume that it is + BIOS-visible rather than using extra layers such as LVM or RAID. + - Add grub-mknetdir script (closes: #550658). + - Remove deprecated "root" command. + - Handle RAID devices containing virtio components. + - GRUB Legacy configuration file support (via grub-menulst2cfg). + - Keyboard layout support (via grub-mklayout and grub-kbdcomp). + - Check generated grub.cfg for syntax errors before saving. + - Pause execution for at most ten seconds if any errors are displayed, + so that the user has a chance to see them. + - Support submenus. + - Write embedding zone using Reed-Solomon, so that it's robust against + being partially overwritten (closes: #550702, #591416, #593347). + - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged + into a single GRUB_DISABLE_RECOVERY variable. + - Fix loader memory allocation failure (closes: #551627). + - Don't call savedefault on recovery entries (closes: #589325). + - Support triple-indirect blocks on ext2 (closes: #543924). + - Recognise DDF1 fake RAID (closes: #603354). + + [ Robert Millan ] * Import from upstream: - refuse_embedingless_cross_disk.patch: Refuse to do a cross-disk embeddingless install rather than creating a broken install. diff --git a/debian/control b/debian/control index 7b9137b08..931067bc7 100644 --- a/debian/control +++ b/debian/control @@ -9,8 +9,8 @@ Build-Depends: debhelper (>= 7.0.50~), patchutils, autoconf, automake, + autogen (>= 1:5.10), python, - ruby, flex (>= 2.5.35), bison, po-debconf, @@ -23,7 +23,7 @@ Build-Depends: debhelper (>= 7.0.50~), libfreetype6-dev, gettext, libusb-dev [!hurd-i386], - libdevmapper-dev [amd64 i386 powerpc mipsel sparc], + libdevmapper-dev (>= 2:1.02.34) [amd64 i386 powerpc mipsel sparc], libzfs-dev [kfreebsd-i386 kfreebsd-amd64], libnvpair-dev [kfreebsd-i386 kfreebsd-amd64], libsdl1.2-dev [!hurd-i386], diff --git a/debian/patches/boot_blocklist_hack.patch b/debian/patches/boot_blocklist_hack.patch index f308af917..9c67c853a 100644 --- a/debian/patches/boot_blocklist_hack.patch +++ b/debian/patches/boot_blocklist_hack.patch @@ -1,10 +1,10 @@ -Index: b/util/i386/pc/grub-setup.c +Index: b/util/grub-setup.c =================================================================== ---- a/util/i386/pc/grub-setup.c -+++ b/util/i386/pc/grub-setup.c -@@ -482,6 +482,15 @@ - grub_disk_cache_invalidate_all (); +--- a/util/grub-setup.c ++++ b/util/grub-setup.c +@@ -525,6 +525,15 @@ + grub_file_filter_disable_compression (); file = grub_file_open (core_path_dev); + + if (grub_errno == GRUB_ERR_FILE_NOT_FOUND) diff --git a/debian/patches/core_in_fs.patch b/debian/patches/core_in_fs.patch index 021075a0d..fbf6c145b 100644 --- a/debian/patches/core_in_fs.patch +++ b/debian/patches/core_in_fs.patch @@ -1,27 +1,27 @@ -Index: b/util/i386/pc/grub-setup.c +Index: b/util/grub-setup.c =================================================================== ---- a/util/i386/pc/grub-setup.c -+++ b/util/i386/pc/grub-setup.c -@@ -56,6 +56,7 @@ +--- a/util/grub-setup.c ++++ b/util/grub-setup.c +@@ -75,6 +75,7 @@ #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" +#define CORE_IMG_IN_FS "setup_left_core_image_in_filesystem" - #define grub_target_to_host16(x) grub_le_to_cpu16(x) - #define grub_target_to_host32(x) grub_le_to_cpu32(x) -@@ -441,6 +442,8 @@ - boot_img)) - grub_util_error ("%s", grub_errmsg); + #ifdef GRUB_MACHINE_SPARC64 + #define grub_target_to_host16(x) grub_be_to_cpu16(x) +@@ -472,6 +473,8 @@ -+ unlink (DEFAULT_DIRECTORY "/" CORE_IMG_IN_FS); + grub_free (sectors); + ++ unlink (DEFAULT_DIRECTORY "/" CORE_IMG_IN_FS); + - goto finish; - - unable_to_embed: -@@ -455,6 +458,9 @@ - if (! force) - grub_util_error (_("if you really want blocklists, use --force")); + goto finish; + } + #endif +@@ -497,6 +500,9 @@ + /* The core image must be put on a filesystem unfortunately. */ + grub_util_info ("will leave the core image on the filesystem"); + fp = fopen (DEFAULT_DIRECTORY "/" CORE_IMG_IN_FS, "w"); + fclose (fp); diff --git a/debian/patches/disable_floppies.patch b/debian/patches/disable_floppies.patch index 74a9337a8..e97b030bb 100644 --- a/debian/patches/disable_floppies.patch +++ b/debian/patches/disable_floppies.patch @@ -3,11 +3,11 @@ Author: Robert Millan An ugly kludge. Should this be merged upstream? -Index: b/kern/emu/hostdisk.c +Index: b/grub-core/kern/emu/hostdisk.c =================================================================== ---- a/kern/emu/hostdisk.c -+++ b/kern/emu/hostdisk.c -@@ -953,6 +953,18 @@ +--- a/grub-core/kern/emu/hostdisk.c ++++ b/grub-core/kern/emu/hostdisk.c +@@ -963,6 +963,18 @@ continue; } diff --git a/debian/patches/dmraid_mapper_paths.patch b/debian/patches/dmraid_mapper_paths.patch deleted file mode 100644 index 7f31c3268..000000000 --- a/debian/patches/dmraid_mapper_paths.patch +++ /dev/null @@ -1,46 +0,0 @@ -Description: Fix DM-RAID probing with recent device-mapper udev rules -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/2780 -Forwarded: yes -Last-Update: 2010-09-17 - -Index: b/kern/emu/hostdisk.c -=================================================================== ---- a/kern/emu/hostdisk.c -+++ b/kern/emu/hostdisk.c -@@ -968,13 +968,16 @@ - #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 = xmalloc (PATH_MAX); -- if (! realpath (p, map[drive].device)) -- grub_util_error ("cannot get the real path of `%s'", p); --#else -- 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 ("cannot get the real path of `%s'", p); -+ } -+ else - #endif -+ map[drive].device = xstrdup (p); - } - - fclose (fp); -@@ -1156,8 +1159,10 @@ - } - - #ifdef HAVE_DEVICE_MAPPER -- /* If this is a DM-RAID device. */ -- if ((strncmp ("mapper/", p, 7) == 0)) -+ /* If this is a DM-RAID device. -+ Compare os_dev rather than path here, since nodes under -+ /dev/mapper/ are often symlinks. */ -+ if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) - { - static struct dm_tree *tree = NULL; - uint32_t maj, min; diff --git a/debian/patches/dmraid_pool_leak.patch b/debian/patches/dmraid_pool_leak.patch deleted file mode 100644 index 21620b3f6..000000000 --- a/debian/patches/dmraid_pool_leak.patch +++ /dev/null @@ -1,99 +0,0 @@ -Description: Fix devmapper memory pool leak with DM-RAID -Author: Modestas Vainius -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/2781 -Forwarded: yes -Last-Update: 2010-09-17 - -Index: b/kern/emu/hostdisk.c -=================================================================== ---- a/kern/emu/hostdisk.c -+++ b/kern/emu/hostdisk.c -@@ -1164,19 +1164,17 @@ - /dev/mapper/ are often symlinks. */ - if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) - { -- static struct dm_tree *tree = NULL; -+ struct dm_tree *tree; - uint32_t maj, min; -- struct dm_tree_node *node, *child; -+ struct dm_tree_node *node = NULL, *child; - void *handle; -- const char *node_uuid, *mapper_name, *child_uuid, *child_name; -- -- if (! tree) -- tree = dm_tree_create (); -+ const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; - -+ tree = dm_tree_create (); - if (! tree) - { - grub_dprintf ("hostdisk", "dm_tree_create failed\n"); -- return NULL; -+ goto devmapper_out; - } - - maj = major (st->st_rdev); -@@ -1184,29 +1182,30 @@ - if (! dm_tree_add_dev (tree, maj, min)) - { - grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); -- return NULL; -+ goto devmapper_out; - } - - node = dm_tree_find_node (tree, maj, min); - if (! node) - { - grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); -- return NULL; -+ goto devmapper_out; - } - node_uuid = dm_tree_node_get_uuid (node); - if (! node_uuid) - { - grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); -- return NULL; -+ node = NULL; -+ goto devmapper_out; - } - else if (strncmp (node_uuid, "DMRAID-", 7) != 0) - { - grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); -- return NULL; -+ node = NULL; -+ goto devmapper_out; - } - - handle = NULL; -- mapper_name = NULL; - /* Counter-intuitively, device-mapper refers to the disk-like - device containing a DM-RAID partition device as a "child" of - the partition device. */ -@@ -1236,17 +1235,20 @@ - mapper_name = child_name; - - devmapper_out: -- if (! mapper_name) -+ if (! mapper_name && node) - { - /* This is a DM-RAID disk, not a partition. */ - mapper_name = dm_tree_node_get_name (node); - if (! mapper_name) -- { -- grub_dprintf ("hostdisk", "%s has no DM name\n", path); -- return NULL; -- } -+ grub_dprintf ("hostdisk", "%s has no DM name\n", path); - } -- return xasprintf ("/dev/mapper/%s", mapper_name); -+ if (tree) -+ dm_tree_free (tree); -+ free (path); -+ if (mapper_name) -+ return xasprintf ("/dev/mapper/%s", mapper_name); -+ else -+ return NULL; - } - #endif /* HAVE_DEVICE_MAPPER */ - } diff --git a/debian/patches/enable_zfs.patch b/debian/patches/enable_zfs.patch deleted file mode 100644 index d4e1411f2..000000000 --- a/debian/patches/enable_zfs.patch +++ /dev/null @@ -1,90 +0,0 @@ -Description: Enable ZFS support in grub-probe and grub-setup -Author: Robert Millan -Forwarded: not-needed -Last-Update: 2010-09-10 - ---- a/conf/common.rmk 2010-07-06 18:27:55 +0000 -+++ b/conf/common.rmk 2010-07-29 14:19:10 +0000 -@@ -35,11 +35,17 @@ - fs/sfs.c fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c \ - fs/afs_be.c fs/befs.c fs/befs_be.c fs/tar.c \ - \ -+ $(GRUB_CONTRIB)/zfs/zfs.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_lzjb.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_sha256.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_fletcher.c \ -+ \ - partmap/msdos.c partmap/bsdlabel.c partmap/apple.c \ - partmap/sun.c partmap/sunpc.c partmap/gpt.c \ - kern/fs.c kern/env.c fs/fshelp.c \ - disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/lvm.c grub_probe_init.c -+grub_probe_CFLAGS = -I$(GRUB_CONTRIB)/zfs/include - - ifeq ($(enable_grub_fstest), yes) - bin_UTILITIES += grub-fstest -@@ -60,6 +66,11 @@ - fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c fs/befs.c \ - fs/befs_be.c fs/tar.c \ - \ -+ $(GRUB_CONTRIB)/zfs/zfs.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_lzjb.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_sha256.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_fletcher.c \ -+ \ - kern/partition.c partmap/msdos.c partmap/bsdlabel.c \ - partmap/apple.c partmap/sun.c partmap/sunpc.c partmap/gpt.c \ - kern/fs.c kern/env.c fs/fshelp.c disk/raid.c \ - disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \ - grub_fstest_init.c -+grub_fstest_CFLAGS = -I$(GRUB_CONTRIB)/zfs/include - - # For grub-mkfont. - ifeq ($(enable_grub_mkfont), yes) ---- a/conf/i386-pc.rmk 2010-07-06 18:27:55 +0000 -+++ b/conf/i386-pc.rmk 2010-07-29 14:19:31 +0000 -@@ -75,6 +75,12 @@ - fs/sfs.c fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c \ - fs/afs_be.c fs/befs.c fs/befs_be.c fs/tar.c \ - \ -+ $(GRUB_CONTRIB)/zfs/zfs.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_lzjb.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_sha256.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_fletcher.c \ -+ \ -+ \ - partmap/msdos.c partmap/bsdlabel.c partmap/sunpc.c \ - partmap/gpt.c \ - \ -@@ -82,6 +88,7 @@ - disk/mdraid_linux.c disk/lvm.c \ - util/raid.c util/lvm.c \ - grub_setup_init.c -+grub_setup_CFLAGS = -I$(GRUB_CONTRIB)/zfs/include - - sbin_SCRIPTS += grub-install - grub_install_SOURCES = util/grub-install.in - ---- a/conf/sparc64-ieee1275.rmk 2010-07-06 18:27:55 +0000 -+++ b/conf/sparc64-ieee1275.rmk 2010-07-29 14:19:40 +0000 -@@ -59,12 +59,18 @@ - fs/sfs.c fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c \ - fs/afs_be.c fs/befs.c fs/befs_be.c fs/tar.c \ - \ -+ $(GRUB_CONTRIB)/zfs/zfs.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_lzjb.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_sha256.c \ -+ $(GRUB_CONTRIB)/zfs/zfs_fletcher.c \ -+ \ - partmap/amiga.c partmap/apple.c partmap/msdos.c \ - partmap/bsdlabel.c partmap/sun.c partmap/acorn.c \ - \ - disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \ - disk/mdraid_linux.c disk/lvm.c util/raid.c \ - util/lvm.c gnulib/progname.c grub_setup_init.c -+grub_setup_CFLAGS = -I$(GRUB_CONTRIB)/zfs/include - - # For grub-ofpathname. - grub_ofpathname_SOURCES = util/ieee1275/grub-ofpathname.c \ - diff --git a/debian/patches/fix_grub_install_error_msg.patch b/debian/patches/fix_grub_install_error_msg.patch deleted file mode 100644 index b39c9cf70..000000000 --- a/debian/patches/fix_grub_install_error_msg.patch +++ /dev/null @@ -1,20 +0,0 @@ -Description: Replace useless recomendation to pass --modules - with a recomendation to report a bug. -Author: Vladimir 'phcoder' Serbinenko -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-11-13 - ---- a/util/grub-install.in -+++ b/util/grub-install.in -@@ -466,9 +466,9 @@ - - # Create the core image. First, auto-detect the filesystem module. - fs_module=`$grub_probe --target=fs --device ${grub_device}` --if test "x$fs_module" = x -a "x$modules" = x; then -- echo "Auto-detection of a filesystem module failed." 1>&2 -- echo "Please specify the module with the option \`--modules' explicitly." 1>&2 -+if test "x$fs_module" = x ; then -+ echo "Auto-detection of a filesystem of ${grub_device} failed." 1>&2 -+ echo "Please report this together with the output of \"$grub_probe --target=fs -v ${grubdir}\" to " 1>&2 - exit 1 - fi diff --git a/debian/patches/fix_usb_boot.patch b/debian/patches/fix_usb_boot.patch deleted file mode 100644 index 40b45580b..000000000 --- a/debian/patches/fix_usb_boot.patch +++ /dev/null @@ -1,17 +0,0 @@ -Description: Fix boot on USB devices, for BIOSes that expose them as floppies. -Author: Robert Millan -Forwarded: not-needed, this is a safer / less intrusive version of upstream - commit (upstream change also affects CD-ROM boot). -Last-Update: 2010-10-21 - ---- a/disk/i386/pc/biosdisk.c -+++ b/disk/i386/pc/biosdisk.c -@@ -107,7 +107,7 @@ - if (drive < 0) - return grub_errno; - -- disk->has_partitions = ((drive & 0x80) && (drive != cd_drive)); -+ disk->has_partitions = cd_drive ? (drive != cd_drive) : 1; - disk->id = drive; - - data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data)); diff --git a/debian/patches/gfxpayload_keep_default.patch b/debian/patches/gfxpayload_keep_default.patch index cbbdf5d31..10fc39e46 100644 --- a/debian/patches/gfxpayload_keep_default.patch +++ b/debian/patches/gfxpayload_keep_default.patch @@ -17,7 +17,7 @@ Index: b/util/grub.d/10_linux.in =================================================================== --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in -@@ -67,17 +67,7 @@ +@@ -69,17 +69,7 @@ # Use ELILO's generic "efifb" when it's known to be available. # FIXME: We need an interface to select vesafb in case efifb can't be used. @@ -33,6 +33,6 @@ Index: b/util/grub.d/10_linux.in - fi - else + if [ "x$GRUB_GFXPAYLOAD_LINUX" != x ]; then + if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then cat << EOF - set gfxpayload=$GRUB_GFXPAYLOAD_LINUX - EOF + load_video diff --git a/debian/patches/grub.cfg_400.patch b/debian/patches/grub.cfg_400.patch index 9c1553d51..0293b8cae 100644 --- a/debian/patches/grub.cfg_400.patch +++ b/debian/patches/grub.cfg_400.patch @@ -2,7 +2,7 @@ Index: b/util/grub-mkconfig.in =================================================================== --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in -@@ -313,6 +313,10 @@ +@@ -291,6 +291,10 @@ esac done @@ -11,5 +11,5 @@ Index: b/util/grub-mkconfig.in +fi + if test "x${grub_cfg}" != "x" ; then - # none of the children aborted with error, install the new grub.cfg - mv -f ${grub_cfg}.new ${grub_cfg} + if ! ${grub_script_check} ${grub_cfg}.new; then + echo "Syntax errors are detected in generated GRUB config file." >&2 diff --git a/debian/patches/grub_legacy_0_based_partitions.patch b/debian/patches/grub_legacy_0_based_partitions.patch index c1546378d..a8d594d32 100644 --- a/debian/patches/grub_legacy_0_based_partitions.patch +++ b/debian/patches/grub_legacy_0_based_partitions.patch @@ -1,8 +1,8 @@ -Index: b/kern/emu/hostdisk.c +Index: b/grub-core/kern/emu/hostdisk.c =================================================================== ---- a/kern/emu/hostdisk.c -+++ b/kern/emu/hostdisk.c -@@ -1005,7 +1005,7 @@ +--- a/grub-core/kern/emu/hostdisk.c ++++ b/grub-core/kern/emu/hostdisk.c +@@ -1017,7 +1017,7 @@ char *bsd_part_str = NULL; if (dos_part >= 0) @@ -11,7 +11,7 @@ Index: b/kern/emu/hostdisk.c if (bsd_part >= 0) bsd_part_str = xasprintf (",%d", bsd_part + 1); -@@ -1422,6 +1422,29 @@ +@@ -1492,6 +1492,29 @@ if (start == part_start) { diff --git a/debian/patches/increase_disk_limit.patch b/debian/patches/increase_disk_limit.patch deleted file mode 100644 index cd0e5a567..000000000 --- a/debian/patches/increase_disk_limit.patch +++ /dev/null @@ -1,25 +0,0 @@ -Description: Increase SCSI limit to 48 and IDE limit to 96 (to cope with Sun Fire X4500) -Author: Robert Millan -Forwarded: not-needed, patch from upstream -Last-Update: 2010-11-04 - ---- a/util/deviceiter.c -+++ b/util/deviceiter.c -@@ -601,7 +601,7 @@ grub_util_iterate_devices (int NESTED_FU - #endif /* __linux__ */ - - /* IDE disks. */ -- for (i = 0; i < 26; i++) -+ for (i = 0; i < 96; i++) - { - char name[16]; - -@@ -655,7 +655,7 @@ grub_util_iterate_devices (int NESTED_FU - #endif /* __linux__ */ - - /* The rest is SCSI disks. */ -- for (i = 0; i < 26; i++) -+ for (i = 0; i < 48; i++) - { - char name[16]; - diff --git a/debian/patches/install_stage2_confusion.patch b/debian/patches/install_stage2_confusion.patch index 69c6db919..4842ea3c3 100644 --- a/debian/patches/install_stage2_confusion.patch +++ b/debian/patches/install_stage2_confusion.patch @@ -8,8 +8,8 @@ Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -420,6 +420,12 @@ - $grub_mkimage -O ${mkimage_target} ${config_opt} -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +@@ -653,6 +653,12 @@ + fi fi +# If vestiges of GRUB Legacy still exist, tell the Debian packaging that diff --git a/debian/patches/kfreebsd_ext2.patch b/debian/patches/kfreebsd_ext2.patch deleted file mode 100644 index 8d66bfffd..000000000 --- a/debian/patches/kfreebsd_ext2.patch +++ /dev/null @@ -1,33 +0,0 @@ -Description: Add support for ext2 root on GNU/kFreeBSD -Author: Aurelien Jarno -Bug-Debian: http://bugs.debian.org/593467 -Forwarded: http://lists.gnu.org/archive/html/grub-devel/2010-08/msg00038.html -Last-Update: 2010-08-19 - -Index: b/util/grub.d/10_kfreebsd.in -=================================================================== ---- a/util/grub.d/10_kfreebsd.in -+++ b/util/grub.d/10_kfreebsd.in -@@ -75,6 +75,14 @@ - fi - - case "${kfreebsd_fs}" in -+ ext2fs) -+ test -e "${module_dir}/ext2fs.ko" -+ -+ printf '%s\n' "${prepare_module_dir_cache}" -+ cat << EOF -+ kfreebsd_module_elf ${module_dir_rel}/ext2fs.ko -+EOF -+ ;; - zfs) - test -e "${module_dir}/opensolaris.ko" - test -e "${module_dir}/zfs.ko" -@@ -121,6 +129,7 @@ - - case ${GRUB_FS} in - ufs1 | ufs2) kfreebsd_fs=ufs ;; -+ ext2) kfreebsd_fs=ext2fs ;; - *) kfreebsd_fs=${GRUB_FS} ;; - esac - diff --git a/debian/patches/linux_mdraid_1x.patch b/debian/patches/linux_mdraid_1x.patch deleted file mode 100644 index 9b50a0fc0..000000000 --- a/debian/patches/linux_mdraid_1x.patch +++ /dev/null @@ -1,307 +0,0 @@ -Description: Support mdraid 1.x -Author: Robert Millan -Forwarded: not-needed, patch from upstream -Last-Update: 2010-11-04 - ---- a/disk/mdraid_linux.c -+++ b/disk/mdraid_linux.c -@@ -254,6 +254,9 @@ grub_mdraid_detect_09 (grub_disk_addr_t - sb->level != 5 && sb->level != 6 && sb->level != 10) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported RAID level: %d", sb->level); -+ if (sb->this_disk.number == 0xffff || sb->this_disk.number == 0xfffe) -+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "spares aren't implemented"); - - array->name = NULL; - array->number = sb->md_minor; -@@ -328,12 +331,13 @@ grub_mdraid_detect_1x (grub_disk_t disk, - array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); - array->disk_size = grub_le_to_cpu64 (real_sb->size); - array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); -- if (grub_le_to_cpu32 (real_sb->dev_number) < -+ if (grub_le_to_cpu32 (real_sb->dev_number) >= - grub_le_to_cpu32 (real_sb->max_dev)) -- array->index = grub_le_to_cpu16 -- (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); -- else -- array->index = 0xffff; /* disk will be later not used! */ -+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ "spares aren't implemented"); -+ -+ array->index = grub_le_to_cpu16 -+ (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); - array->uuid_len = 16; - array->uuid = grub_malloc (16); - if (!array->uuid) - ---- a/disk/raid.c -+++ b/disk/raid.c -@@ -97,10 +97,10 @@ grub_raid_memberlist (grub_disk_t disk) - unsigned int i; - - for (i = 0; i < array->total_devs; i++) -- if (array->device[i]) -+ if (array->members[i].device) - { - tmp = grub_malloc (sizeof (*tmp)); -- tmp->disk = array->device[i]; -+ tmp->disk = array->members[i].device; - tmp->next = list; - list = tmp; - } -@@ -248,13 +248,13 @@ grub_raid_read (grub_disk_t disk, grub_d - k = disknr; - for (j = 0; j < far; j++) - { -- if (array->device[k]) -+ if (array->members[k].device) - { - if (grub_errno == GRUB_ERR_READ_ERROR) - grub_errno = GRUB_ERR_NONE; - -- err = grub_disk_read (array->device[k], -- array->start_sector[k] + -+ err = grub_disk_read (array->members[k].device, -+ array->members[k].start_sector + - read_sector + j * far_ofs + b, - 0, - read_size << GRUB_DISK_SECTOR_BITS, -@@ -360,14 +360,14 @@ grub_raid_read (grub_disk_t disk, grub_d - read_size = size; - - e = 0; -- if (array->device[disknr]) -+ if (array->members[disknr].device) - { - /* Reset read error. */ - if (grub_errno == GRUB_ERR_READ_ERROR) - grub_errno = GRUB_ERR_NONE; - -- err = grub_disk_read (array->device[disknr], -- array->start_sector[disknr] + -+ err = grub_disk_read (array->members[disknr].device, -+ array->members[disknr].start_sector + - read_sector + b, 0, - read_size << GRUB_DISK_SECTOR_BITS, - buf); -@@ -492,6 +492,21 @@ insert_array (grub_disk_t disk, struct g - - /* Do some checks before adding the device to the array. */ - -+ if (new_array->index >= array->allocated_devs) -+ { -+ void *tmp; -+ unsigned int newnum = 2 * (new_array->index + 1); -+ tmp = grub_realloc (array->members, newnum -+ * sizeof (array->members[0])); -+ if (!tmp) -+ return grub_errno; -+ array->members = tmp; -+ grub_memset (array->members + array->allocated_devs, -+ 0, (newnum - array->allocated_devs) -+ * sizeof (array->members[0])); -+ array->allocated_devs = newnum; -+ } -+ - /* FIXME: Check whether the update time of the superblocks are - the same. */ - -@@ -502,7 +517,7 @@ insert_array (grub_disk_t disk, struct g - grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?", - array->total_devs); - -- if (array->device[new_array->index] != NULL) -+ if (array->members[new_array->index].device != NULL) - /* We found multiple devices with the same number. Again, - this shouldn't happen. */ - grub_dprintf ("raid", "Found two disks with the number %d?!?", -@@ -525,8 +540,18 @@ insert_array (grub_disk_t disk, struct g - - *array = *new_array; - array->nr_devs = 0; -- grub_memset (&array->device, 0, sizeof (array->device)); -- grub_memset (&array->start_sector, 0, sizeof (array->start_sector)); -+ array->allocated_devs = 32; -+ if (new_array->index >= array->allocated_devs) -+ array->allocated_devs = 2 * (new_array->index + 1); -+ -+ array->members = grub_zalloc (array->allocated_devs -+ * sizeof (array->members[0])); -+ -+ if (!array->members) -+ { -+ grub_free (new_array->uuid); -+ return grub_errno; -+ } - - if (! array->name) - { -@@ -571,6 +596,7 @@ insert_array (grub_disk_t disk, struct g - array->name = grub_xasprintf ("md%d", array->number); - if (! array->name) - { -+ grub_free (array->members); - grub_free (array->uuid); - grub_free (array); - -@@ -586,6 +612,7 @@ insert_array (grub_disk_t disk, struct g - - if (! new_name) - { -+ grub_free (array->members); - grub_free (array->uuid); - grub_free (array); - -@@ -610,8 +637,8 @@ insert_array (grub_disk_t disk, struct g - } - - /* Add the device to the array. */ -- array->device[new_array->index] = disk; -- array->start_sector[new_array->index] = start_sector; -+ array->members[new_array->index].device = disk; -+ array->members[new_array->index].start_sector = start_sector; - array->nr_devs++; - - return 0; -@@ -628,14 +655,15 @@ free_array (void) - while (array) - { - struct grub_raid_array *p; -- int i; -+ unsigned int i; - - p = array; - array = array->next; - -- for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++) -- if (p->device[i]) -- grub_disk_close (p->device[i]); -+ for (i = 0; i < p->allocated_devs; i++) -+ if (p->members[i].device) -+ grub_disk_close (p->members[i].device); -+ grub_free (p->members); - - grub_free (p->uuid); - grub_free (p->name); - ---- a/disk/raid5_recover.c -+++ b/disk/raid5_recover.c -@@ -45,7 +45,7 @@ grub_raid5_recover (struct grub_raid_arr - if (i == disknr) - continue; - -- err = grub_disk_read (array->device[i], sector, 0, size, buf2); -+ err = grub_disk_read (array->members[i].device, sector, 0, size, buf2); - - if (err) - { - ---- a/disk/raid6_recover.c -+++ b/disk/raid6_recover.c -@@ -118,8 +118,9 @@ grub_raid6_recover (struct grub_raid_arr - bad1 = i; - else - { -- if ((array->device[pos]) && -- (! grub_disk_read (array->device[pos], sector, 0, size, buf))) -+ if ((array->members[pos].device) && -+ (! grub_disk_read (array->members[pos].device, sector, -+ 0, size, buf))) - { - grub_raid_block_xor (pbuf, buf, size); - grub_raid_block_mul (raid6_table2[i][i], buf, size); -@@ -148,21 +149,21 @@ grub_raid6_recover (struct grub_raid_arr - if (bad2 < 0) - { - /* One bad device */ -- if ((array->device[p]) && -- (! grub_disk_read (array->device[p], sector, 0, size, buf))) -+ if ((array->members[p].device) && -+ (! grub_disk_read (array->members[p].device, sector, 0, size, buf))) - { - grub_raid_block_xor (buf, pbuf, size); - goto quit; - } - -- if (! array->device[q]) -+ if (! array->members[q].device) - { - grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); - goto quit; - } - - grub_errno = GRUB_ERR_NONE; -- if (grub_disk_read (array->device[q], sector, 0, size, buf)) -+ if (grub_disk_read (array->members[q].device, sector, 0, size, buf)) - goto quit; - - grub_raid_block_xor (buf, qbuf, size); -@@ -174,18 +175,18 @@ grub_raid6_recover (struct grub_raid_arr - /* Two bad devices */ - grub_uint8_t c; - -- if ((! array->device[p]) || (! array->device[q])) -+ if ((! array->members[p].device) || (! array->members[q].device)) - { - grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); - goto quit; - } - -- if (grub_disk_read (array->device[p], sector, 0, size, buf)) -+ if (grub_disk_read (array->members[p].device, sector, 0, size, buf)) - goto quit; - - grub_raid_block_xor (pbuf, buf, size); - -- if (grub_disk_read (array->device[q], sector, 0, size, buf)) -+ if (grub_disk_read (array->members[q].device, sector, 0, size, buf)) - goto quit; - - grub_raid_block_xor (qbuf, buf, size); - ---- a/include/grub/raid.h -+++ b/include/grub/raid.h -@@ -22,8 +22,6 @@ - - #include - --#define GRUB_RAID_MAX_DEVICES 32 -- - #define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC 0 - #define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC 1 - #define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC 2 -@@ -32,6 +30,13 @@ - #define GRUB_RAID_LAYOUT_RIGHT_MASK 1 - #define GRUB_RAID_LAYOUT_SYMMETRIC_MASK 2 - -+struct grub_raid_member -+{ -+ grub_disk_t device; /* Array of total_devs devices. */ -+ grub_disk_addr_t start_sector; -+ /* Start of each device, in 512 byte sectors. */ -+}; -+ - struct grub_raid_array - { - int number; /* The device number, taken from md_minor so we -@@ -43,16 +48,15 @@ struct grub_raid_array - grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */ - grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte - sectors. */ -- int index; /* Index of current device. */ -+ unsigned int index; /* Index of current device. */ - int uuid_len; /* The length of uuid. */ - char *uuid; /* The UUID of the device. */ - - /* The following field is setup by the caller. */ - char *name; /* That will be "md". */ - unsigned int nr_devs; /* The number of devices we've found so far. */ -- grub_disk_t device[GRUB_RAID_MAX_DEVICES]; /* Array of total_devs devices. */ -- grub_disk_addr_t start_sector[GRUB_RAID_MAX_DEVICES]; -- /* Start of each device, in 512 byte sectors. */ -+ unsigned int allocated_devs; -+ struct grub_raid_member *members; - struct grub_raid_array *next; - }; - diff --git a/debian/patches/mkrescue_diet.patch b/debian/patches/mkrescue_diet.patch index e90e59a71..62284ebce 100644 --- a/debian/patches/mkrescue_diet.patch +++ b/debian/patches/mkrescue_diet.patch @@ -26,7 +26,7 @@ Index: b/util/grub-mkrescue.in $self generates a bootable rescue image with specified source files, source directories, or mkisofs options listed by: xorriso -as mkisofs -help -@@ -132,6 +134,9 @@ +@@ -133,6 +135,9 @@ --xorriso=*) xorriso=`echo "${option}/" | sed 's/--xorriso=//'` ;; @@ -36,7 +36,7 @@ Index: b/util/grub-mkrescue.in *) source="${source} ${option} $@"; break ;; esac -@@ -310,7 +315,14 @@ +@@ -303,7 +308,14 @@ fi # build iso image diff --git a/debian/patches/olpc_prefix_hack.patch b/debian/patches/olpc_prefix_hack.patch index 4fd058876..79c2a5b60 100644 --- a/debian/patches/olpc_prefix_hack.patch +++ b/debian/patches/olpc_prefix_hack.patch @@ -1,11 +1,11 @@ This sucks, but it's better than what OFW was giving us. -Index: b/kern/ieee1275/init.c +Index: b/grub-core/kern/ieee1275/init.c =================================================================== ---- a/kern/ieee1275/init.c -+++ b/kern/ieee1275/init.c -@@ -52,6 +52,7 @@ +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -53,6 +53,7 @@ grub_ieee1275_exit (); } @@ -13,7 +13,7 @@ Index: b/kern/ieee1275/init.c /* Translate an OF filesystem path (separated by backslashes), into a GRUB path (separated by forward slashes). */ static void -@@ -66,13 +67,16 @@ +@@ -67,13 +68,16 @@ backslash = grub_strchr (filepath, '\\'); } } @@ -30,7 +30,7 @@ Index: b/kern/ieee1275/init.c if (grub_prefix[0]) { -@@ -81,6 +85,9 @@ +@@ -82,6 +86,9 @@ return; } @@ -40,7 +40,7 @@ Index: b/kern/ieee1275/init.c if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, sizeof (bootpath), 0)) { -@@ -119,6 +126,7 @@ +@@ -120,6 +127,7 @@ grub_free (filename); grub_free (prefix); diff --git a/debian/patches/refuse_embedingless_cross_disk.patch b/debian/patches/refuse_embedingless_cross_disk.patch deleted file mode 100644 index cb8bcae93..000000000 --- a/debian/patches/refuse_embedingless_cross_disk.patch +++ /dev/null @@ -1,21 +0,0 @@ -Description: Refuse to do a cross-disk embeddingless install - rather than creating a broken install. -Author: Vladimir 'phcoder' Serbinenko -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-11-13 - ---- a/util/i386/pc/grub-setup.c -+++ b/util/i386/pc/grub-setup.c -@@ -482,6 +482,12 @@ - grub_util_error (_("embedding is not possible, but this is required when " - "the root device is on a RAID array or LVM volume")); - -+#ifdef GRUB_MACHINE_PCBIOS -+ if (dest_dev->disk->id != root_dev->disk->id) -+ grub_util_error (_("embedding is not possible, but this is required for " -+ "cross-disk install")); -+#endif -+ - grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this " - "setup by using blocklists. However, blocklists are UNRELIABLE and " - "their use is discouraged.")); diff --git a/debian/patches/series b/debian/patches/series index a7891f6b8..7cf88e252 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -9,19 +9,3 @@ gfxpayload_keep_default.patch mkrescue_diet.patch mkconfig_skip_dmcrypt.patch install_stage2_confusion.patch -enable_zfs.patch -zfs_fix_chroot.patch -zfs_fix_segfault.patch -zfs_fix_pathname.patch -zfs_fix_label_arg.patch -zfs_v23.patch -kfreebsd_ext2.patch -dmraid_mapper_paths.patch -dmraid_pool_leak.patch -fix_usb_boot.patch -zfs_fix_mkrelpath.patch -increase_disk_limit.patch -linux_mdraid_1x.patch -yeeloong_boot_info.patch -refuse_embedingless_cross_disk.patch -fix_grub_install_error_msg.patch diff --git a/debian/patches/yeeloong_boot_info.patch b/debian/patches/yeeloong_boot_info.patch deleted file mode 100644 index 00eb2a193..000000000 --- a/debian/patches/yeeloong_boot_info.patch +++ /dev/null @@ -1,62 +0,0 @@ -Description: On Yeeloong, pass machine type information to Linux. -Author: Robert Millan -Forwarded: not-needed, patch from upstream -Last-Update: 2010-11-05 - ---- a/loader/mips/linux.c -+++ b/loader/mips/linux.c -@@ -36,6 +36,14 @@ - #define ELF32_LOADMASK (0x00000000UL) - #define ELF64_LOADMASK (0x0000000000000000ULL) - -+#ifdef GRUB_MACHINE_MIPS_YEELOONG -+/* This can be detected on runtime from PMON, but: -+ a) it wouldn't work when GRUB is the firmware -+ and -+ b) for now we only support Yeeloong anyway. */ -+#define LOONGSON_MACHTYPE "machtype=lemote-yeeloong-2f-8.9inches" -+#endif -+ - static grub_dl_t my_mod; - - static int loaded; -@@ -205,6 +213,9 @@ grub_cmd_linux (grub_command_t cmd __att - - /* For arguments. */ - linux_argc = argc; -+#ifdef LOONGSON_MACHTYPE -+ linux_argc++; -+#endif - /* Main arguments. */ - size = (linux_argc) * sizeof (grub_uint32_t); - /* Initrd address and size. */ -@@ -217,7 +228,10 @@ grub_cmd_linux (grub_command_t cmd __att - /* Normal arguments. */ - for (i = 1; i < argc; i++) - size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -- -+#ifdef LOONGSON_MACHTYPE -+ size += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4); -+#endif -+ - /* rd arguments. */ - size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); - size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -@@ -254,6 +268,16 @@ grub_cmd_linux (grub_command_t cmd __att - linux_argv++; - linux_args += ALIGN_UP (sizeof ("a0"), 4); - -+#ifdef LOONGSON_MACHTYPE -+ /* In Loongson platform, it is the responsibility of the bootloader/firmware -+ to supply the OS kernel with machine type information. */ -+ grub_memcpy (linux_args, LOONGSON_MACHTYPE, sizeof (LOONGSON_MACHTYPE)); -+ *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground -+ + target_addr; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4); -+#endif -+ - for (i = 1; i < argc; i++) - { - grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); - diff --git a/debian/patches/zfs_fix_chroot.patch b/debian/patches/zfs_fix_chroot.patch deleted file mode 100644 index e1ae3d99b..000000000 --- a/debian/patches/zfs_fix_chroot.patch +++ /dev/null @@ -1,26 +0,0 @@ -Description: Fix breakage when running grub-probe inside chroot -Author: Robert Millan -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-08-16 - ---- a/kern/emu/misc.c 2010-08-03 22:15:29 +0000 -+++ b/kern/emu/misc.c 2010-08-16 13:07:46 +0000 -@@ -344,7 +345,17 @@ grub_find_zpool_from_mount_point (const - - *poolname = *poolfs = NULL; - --#if defined(HAVE_GETFSSTAT) /* FreeBSD and GNU/kFreeBSD */ -+#if 1 -+ { -+ struct statfs mnt; -+ -+ if (statfs (mnt_point, &mnt) != 0) -+ error (1, errno, "statfs"); -+ -+ if (!strcmp (mnt.f_fstypename, "zfs")) -+ *poolname = xstrdup (mnt.f_mntfromname); -+ } -+#elif defined(HAVE_GETFSSTAT) /* FreeBSD and GNU/kFreeBSD */ - { - int mnt_count = getfsstat (NULL, 0, MNT_WAIT); - if (mnt_count == -1) diff --git a/debian/patches/zfs_fix_label_arg.patch b/debian/patches/zfs_fix_label_arg.patch deleted file mode 100644 index 04996161c..000000000 --- a/debian/patches/zfs_fix_label_arg.patch +++ /dev/null @@ -1,17 +0,0 @@ -Description: Fix kfreebsd_device initialization on ZFS -Author: Robert Millan -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-09-10 - ---- a/util/grub.d/10_kfreebsd.in 2010-08-01 21:21:09 +0000 -+++ b/util/grub.d/10_kfreebsd.in 2010-08-16 13:07:46 +0000 -@@ -125,7 +125,7 @@ while [ "x$list" != "x" ] ; do - esac - - case ${GRUB_FS} in -- zfs) kfreebsd_device=$(grub-probe -t label --device ${GRUB_DEVICE}) ;; -+ zfs) kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE})$(grub-mkrelpath / | sed -e "s,/*@$,,") ;; - *) kfreebsd_device=${GRUB_DEVICE} ;; - esac - - diff --git a/debian/patches/zfs_fix_mkrelpath.patch b/debian/patches/zfs_fix_mkrelpath.patch deleted file mode 100644 index 0c25b1805..000000000 --- a/debian/patches/zfs_fix_mkrelpath.patch +++ /dev/null @@ -1,19 +0,0 @@ -Description: Fix grub-mkrelpath for non-root ZFS -Author: Vladimir 'phcoder' Serbinenko -Forwarded: not needed, patch from upstream Bazaar (r2905) -Last-Update: 2010-10-24 - ---- a/kern/emu/misc.c 2010-10-23 18:34:50 +0000 -+++ b/kern/emu/misc.c 2010-10-23 18:39:08 +0000 -@@ -416,6 +416,10 @@ grub_make_system_path_relative_to_its_ro - { - free (buf); - free (buf2); -+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) -+ if (poolfs) -+ return xasprintf ("/%s/@", poolfs); -+#endif - return xstrdup (""); - } - else - diff --git a/debian/patches/zfs_fix_pathname.patch b/debian/patches/zfs_fix_pathname.patch deleted file mode 100644 index f25208232..000000000 --- a/debian/patches/zfs_fix_pathname.patch +++ /dev/null @@ -1,18 +0,0 @@ -Description: Fix pathname for non-root ZFS filesystems -Author: Robert Millan -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-08-16 - -Index: b/kern/emu/misc.c -=================================================================== ---- a/kern/emu/misc.c -+++ b/kern/emu/misc.c -@@ -519,7 +519,7 @@ - - if (poolfs) - { -- ret = xasprintf ("/%s@%s", poolfs, buf3); -+ ret = xasprintf ("/%s/@%s", poolfs, buf3); - free (buf3); - } - else diff --git a/debian/patches/zfs_fix_segfault.patch b/debian/patches/zfs_fix_segfault.patch deleted file mode 100644 index 9185d085b..000000000 --- a/debian/patches/zfs_fix_segfault.patch +++ /dev/null @@ -1,38 +0,0 @@ -Description: Fix segfault when /dev is not mounted -Author: Robert Millan -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-08-16 - ---- a/kern/emu/getroot.c 2010-08-01 21:12:24 +0000 -+++ b/kern/emu/getroot.c 2010-08-16 13:07:46 +0000 -@@ -193,11 +193,16 @@ find_root_device_from_libzfs (const char - - { - zpool_handle_t *zpool; -+ libzfs_handle_t *libzfs; - nvlist_t *nvlist; - nvlist_t **nvlist_array; - unsigned int nvlist_count; - -- zpool = zpool_open (grub_get_libzfs_handle (), poolname); -+ libzfs = grub_get_libzfs_handle (); -+ if (! libzfs) -+ return NULL; -+ -+ zpool = zpool_open (libzfs, poolname); - nvlist = zpool_get_config (zpool, NULL); - - if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0) - ---- a/kern/emu/misc.c 2010-08-03 22:15:29 +0000 -+++ b/kern/emu/misc.c 2010-08-16 13:07:46 +0000 -@@ -268,7 +268,8 @@ grub_get_libzfs_handle (void) - if (! __libzfs_handle) - { - __libzfs_handle = libzfs_init (); -- atexit (fini_libzfs); -+ if (__libzfs_handle) -+ atexit (fini_libzfs); - } - - return __libzfs_handle; diff --git a/debian/patches/zfs_v23.patch b/debian/patches/zfs_v23.patch deleted file mode 100644 index 55fe64bb7..000000000 --- a/debian/patches/zfs_v23.patch +++ /dev/null @@ -1,17 +0,0 @@ -Description: Accept ZFS up to v23 (no changes required) -Author: Robert Millan -Forwarded: not needed, patch from upstream Bazaar -Last-Update: 2010-09-22 - ---- a/debian/grub-extras/zfs/include/grub/zfs/zfs.h 2009-10-26 20:15:26 +0000 -+++ b/debian/grub-extras/zfs/include/grub/zfs/zfs.h 2010-09-22 15:43:24 +0000 -@@ -31,7 +31,7 @@ - /* - * On-disk version number. - */ --#define SPA_VERSION 14ULL -+#define SPA_VERSION 23ULL - - /* - * The following are configuration names used in the nvlist describing a pool's - diff --git a/debian/rules b/debian/rules index b7d570786..26acdf2ed 100755 --- a/debian/rules +++ b/debian/rules @@ -27,7 +27,7 @@ CC := gcc-4.4 # Enable external modules from grub-extras. export GRUB_CONTRIB := $(CURDIR)/debian/grub-extras -confflags = CC=$(CC) TARGET_CC=$(CC) --enable-grub-mkfont --disable-grub-fstest +confflags = CC=$(CC) TARGET_CC=$(CC) --enable-grub-mkfont # autogen.sh runs util/import_gcry.py after autoconf et al, so # conf/gcry.rmk's timestamp will be later and we need to disregard it. @@ -108,7 +108,7 @@ build/stamps/build-grub-firmware-qemu: build/stamps/configure-grub-firmware-qemu tar -cf - -C $${grub_dir} boot > $${grub_memdisk} ; \ $(CURDIR)/build/$(package)/grub-mkimage \ -O i386-qemu \ - -d $(CURDIR)/build/$(package) \ + -d $(CURDIR)/build/$(package)/grub-core \ $(CURDIR)/build/$(package)/*.mod \ -m $${grub_memdisk} \ -o $(CURDIR)/build/$(package)/grub.bin @@ -123,7 +123,7 @@ build/stamps/build-grub-rescue-pc: build/stamps/build-grub-pc build/grub-rescue-pc/grub-mkrescue mkdir -p build/grub-rescue-pc/lib/grub rm -rf build/grub-rescue-pc/lib/grub/i386-pc - cp -a build/grub-pc build/grub-rescue-pc/lib/grub/i386-pc + cp -a build/grub-pc/grub-core build/grub-rescue-pc/lib/grub/i386-pc $(CURDIR)/build/grub-rescue-pc/grub-mkrescue \ --grub-mkimage=$(CURDIR)/build/grub-pc/grub-mkimage \ --output=$(CURDIR)/build/grub-rescue-pc/grub-rescue-cdrom.iso \ @@ -142,8 +142,9 @@ install/grub-pc install/grub-efi-ia32 install/grub-efi-amd64 install/grub-ieee12 # shipped with grub-common rm -rf $(CURDIR)/debian/$(package)/etc/grub.d + rm -rf $(CURDIR)/debian/$(package)/etc/bash_completion.d rm -f $(CURDIR)/debian/$(package)/usr/{sbin,share/man/man8}/{grub-dumpbios,grub-probe,grub-mkconfig,grub-mkdevicemap,grub-ofpathname}{,.8} - rm -f $(CURDIR)/debian/$(package)/usr/{bin,share/man/man1}/{grub-bin2h,grub-mkelfimage,grub-mkfont,grub-mkimage,grub-editenv,grub-mkrescue,grub-mkrelpath,grub-script-check,grub-mkpasswd-pbkdf2}{,.1} + rm -f $(CURDIR)/debian/$(package)/usr/{bin,share/man/man1}/{grub-bin2h,grub-mkelfimage,grub-mkfont,grub-mkimage,grub-editenv,grub-mkrescue,grub-mkrelpath,grub-script-check,grub-mkpasswd-pbkdf2,grub-menulst2cfg,grub-mklayout,grub-kbdcomp}{,.1} rm -f $(CURDIR)/debian/$(package)/usr/lib/grub/{grub-mkconfig_lib,update-grub_lib} rm -rf $(CURDIR)/debian/$(package)/usr/share/{grub,info,locale}/ rm -rf $(CURDIR)/debian/$(package)/usr/include diff --git a/disk/mdraid_linux.c b/disk/mdraid_linux.c deleted file mode 100644 index d5a0aad47..000000000 --- a/disk/mdraid_linux.c +++ /dev/null @@ -1,424 +0,0 @@ -/* mdraid_linux.c - module to handle Linux Software RAID. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 - -/* Linux RAID on disk structures and constants, - copied from include/linux/raid/md_p.h. */ - -#define RESERVED_BYTES (64 * 1024) -#define RESERVED_SECTORS (RESERVED_BYTES / 512) - -#define NEW_SIZE_SECTORS(x) ((x & ~(RESERVED_SECTORS - 1)) \ - - RESERVED_SECTORS) - -#define SB_BYTES 4096 -#define SB_WORDS (SB_BYTES / 4) -#define SB_SECTORS (SB_BYTES / 512) - -/* - * The following are counted in 32-bit words - */ -#define SB_GENERIC_OFFSET 0 - -#define SB_PERSONALITY_OFFSET 64 -#define SB_DISKS_OFFSET 128 -#define SB_DESCRIPTOR_OFFSET 992 - -#define SB_GENERIC_CONSTANT_WORDS 32 -#define SB_GENERIC_STATE_WORDS 32 -#define SB_GENERIC_WORDS (SB_GENERIC_CONSTANT_WORDS + \ - SB_GENERIC_STATE_WORDS) - -#define SB_PERSONALITY_WORDS 64 -#define SB_DESCRIPTOR_WORDS 32 -#define SB_DISKS 27 -#define SB_DISKS_WORDS (SB_DISKS * SB_DESCRIPTOR_WORDS) - -#define SB_RESERVED_WORDS (1024 \ - - SB_GENERIC_WORDS \ - - SB_PERSONALITY_WORDS \ - - SB_DISKS_WORDS \ - - SB_DESCRIPTOR_WORDS) - -#define SB_EQUAL_WORDS (SB_GENERIC_WORDS \ - + SB_PERSONALITY_WORDS \ - + SB_DISKS_WORDS) - -/* - * Device "operational" state bits - */ -#define DISK_FAULTY 0 -#define DISK_ACTIVE 1 -#define DISK_SYNC 2 -#define DISK_REMOVED 3 - -#define DISK_WRITEMOSTLY 9 - -#define SB_MAGIC 0xa92b4efc - -/* - * Superblock state bits - */ -#define SB_CLEAN 0 -#define SB_ERRORS 1 - -#define SB_BITMAP_PRESENT 8 - -struct grub_raid_disk_09 -{ - grub_uint32_t number; /* Device number in the entire set. */ - grub_uint32_t major; /* Device major number. */ - grub_uint32_t minor; /* Device minor number. */ - grub_uint32_t raid_disk; /* The role of the device in the raid set. */ - grub_uint32_t state; /* Operational state. */ - grub_uint32_t reserved[SB_DESCRIPTOR_WORDS - 5]; -}; - -struct grub_raid_super_09 -{ - /* - * Constant generic information - */ - grub_uint32_t md_magic; /* MD identifier. */ - grub_uint32_t major_version; /* Major version. */ - grub_uint32_t minor_version; /* Minor version. */ - grub_uint32_t patch_version; /* Patchlevel version. */ - grub_uint32_t gvalid_words; /* Number of used words in this section. */ - grub_uint32_t set_uuid0; /* Raid set identifier. */ - grub_uint32_t ctime; /* Creation time. */ - grub_uint32_t level; /* Raid personality. */ - grub_uint32_t size; /* Apparent size of each individual disk. */ - grub_uint32_t nr_disks; /* Total disks in the raid set. */ - grub_uint32_t raid_disks; /* Disks in a fully functional raid set. */ - grub_uint32_t md_minor; /* Preferred MD minor device number. */ - grub_uint32_t not_persistent; /* Does it have a persistent superblock. */ - grub_uint32_t set_uuid1; /* Raid set identifier #2. */ - grub_uint32_t set_uuid2; /* Raid set identifier #3. */ - grub_uint32_t set_uuid3; /* Raid set identifier #4. */ - grub_uint32_t gstate_creserved[SB_GENERIC_CONSTANT_WORDS - 16]; - - /* - * Generic state information - */ - grub_uint32_t utime; /* Superblock update time. */ - grub_uint32_t state; /* State bits (clean, ...). */ - grub_uint32_t active_disks; /* Number of currently active disks. */ - grub_uint32_t working_disks; /* Number of working disks. */ - grub_uint32_t failed_disks; /* Number of failed disks. */ - grub_uint32_t spare_disks; /* Number of spare disks. */ - grub_uint32_t sb_csum; /* Checksum of the whole superblock. */ - grub_uint64_t events; /* Superblock update count. */ - grub_uint64_t cp_events; /* Checkpoint update count. */ - grub_uint32_t recovery_cp; /* Recovery checkpoint sector count. */ - grub_uint32_t gstate_sreserved[SB_GENERIC_STATE_WORDS - 12]; - - /* - * Personality information - */ - grub_uint32_t layout; /* The array's physical layout. */ - grub_uint32_t chunk_size; /* Chunk size in bytes. */ - grub_uint32_t root_pv; /* LV root PV. */ - grub_uint32_t root_block; /* LV root block. */ - grub_uint32_t pstate_reserved[SB_PERSONALITY_WORDS - 4]; - - /* - * Disks information - */ - struct grub_raid_disk_09 disks[SB_DISKS]; - - /* - * Reserved - */ - grub_uint32_t reserved[SB_RESERVED_WORDS]; - - /* - * Active descriptor - */ - struct grub_raid_disk_09 this_disk; -} __attribute__ ((packed)); - -/* - * The version-1 superblock : - * All numeric fields are little-endian. - * - * Total size: 256 bytes plus 2 per device. - * 1K allows 384 devices. - */ - -struct grub_raid_super_1x -{ - /* Constant array information - 128 bytes. */ - grub_uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */ - grub_uint32_t major_version; /* 1. */ - grub_uint32_t feature_map; /* Bit 0 set if 'bitmap_offset' is meaningful. */ - grub_uint32_t pad0; /* Always set to 0 when writing. */ - - grub_uint8_t set_uuid[16]; /* User-space generated. */ - char set_name[32]; /* Set and interpreted by user-space. */ - - grub_uint64_t ctime; /* Lo 40 bits are seconds, top 24 are microseconds or 0. */ - grub_uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5. */ - grub_uint32_t layout; /* only for raid5 and raid10 currently. */ - grub_uint64_t size; /* Used size of component devices, in 512byte sectors. */ - - grub_uint32_t chunksize; /* In 512byte sectors. */ - grub_uint32_t raid_disks; - grub_uint32_t bitmap_offset; /* Sectors after start of superblock that bitmap starts - * NOTE: signed, so bitmap can be before superblock - * only meaningful of feature_map[0] is set. - */ - - /* These are only valid with feature bit '4'. */ - grub_uint32_t new_level; /* New level we are reshaping to. */ - grub_uint64_t reshape_position; /* Next address in array-space for reshape. */ - grub_uint32_t delta_disks; /* Change in number of raid_disks. */ - grub_uint32_t new_layout; /* New layout. */ - grub_uint32_t new_chunk; /* New chunk size (512byte sectors). */ - grub_uint8_t pad1[128 - 124]; /* Set to 0 when written. */ - - /* Constant this-device information - 64 bytes. */ - grub_uint64_t data_offset; /* Sector start of data, often 0. */ - grub_uint64_t data_size; /* Sectors in this device that can be used for data. */ - grub_uint64_t super_offset; /* Sector start of this superblock. */ - grub_uint64_t recovery_offset; /* Sectors before this offset (from data_offset) have been recovered. */ - grub_uint32_t dev_number; /* Permanent identifier of this device - not role in raid. */ - grub_uint32_t cnt_corrected_read; /* Number of read errors that were corrected by re-writing. */ - grub_uint8_t device_uuid[16]; /* User-space setable, ignored by kernel. */ - grub_uint8_t devflags; /* Per-device flags. Only one defined... */ - grub_uint8_t pad2[64 - 57]; /* Set to 0 when writing. */ - - /* Array state information - 64 bytes. */ - grub_uint64_t utime; /* 40 bits second, 24 btes microseconds. */ - grub_uint64_t events; /* Incremented when superblock updated. */ - grub_uint64_t resync_offset; /* Data before this offset (from data_offset) known to be in sync. */ - grub_uint32_t sb_csum; /* Checksum upto devs[max_dev]. */ - grub_uint32_t max_dev; /* Size of devs[] array to consider. */ - grub_uint8_t pad3[64 - 32]; /* Set to 0 when writing. */ - - /* Device state information. Indexed by dev_number. - * 2 bytes per device. - * Note there are no per-device state flags. State information is rolled - * into the 'roles' value. If a device is spare or faulty, then it doesn't - * have a meaningful role. - */ - grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */ -}; -/* Could be __attribute__ ((packed)), but since all members in this struct - are already appropriately aligned, we can omit this and avoid suboptimal - assembly in some cases. */ - -#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */ - -static grub_err_t -grub_mdraid_detect_09 (grub_disk_addr_t sector, - struct grub_raid_super_09 *sb, - struct grub_raid_array *array, - grub_disk_addr_t *start_sector) -{ - grub_uint32_t *uuid; - - if (sb->major_version != 0 || sb->minor_version != 90) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported RAID version: %d.%d", - sb->major_version, sb->minor_version); - - /* FIXME: Check the checksum. */ - - /* Multipath. */ - if ((int) sb->level == -4) - sb->level = 1; - - if (sb->level != 0 && sb->level != 1 && sb->level != 4 && - sb->level != 5 && sb->level != 6 && sb->level != 10) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported RAID level: %d", sb->level); - - array->name = NULL; - array->number = sb->md_minor; - array->level = sb->level; - array->layout = sb->layout; - array->total_devs = sb->raid_disks; - array->disk_size = (sb->size) ? sb->size * 2 : sector; - array->chunk_size = sb->chunk_size >> 9; - array->index = sb->this_disk.number; - array->uuid_len = 16; - array->uuid = grub_malloc (16); - if (!array->uuid) - return grub_errno; - - uuid = (grub_uint32_t *) array->uuid; - uuid[0] = sb->set_uuid0; - uuid[1] = sb->set_uuid1; - uuid[2] = sb->set_uuid2; - uuid[3] = sb->set_uuid3; - - *start_sector = 0; - - return 0; -} - -static grub_err_t -grub_mdraid_detect_1x (grub_disk_t disk, grub_disk_addr_t sector, - struct grub_raid_super_1x *sb, - struct grub_raid_array *array, - grub_disk_addr_t *start_sector) -{ - grub_uint64_t sb_size; - struct grub_raid_super_1x *real_sb; - - if (sb->major_version != 1) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Unsupported RAID version: %d", - sb->major_version); - - /* Multipath. */ - if ((int) sb->level == -4) - sb->level = 1; - - if (sb->level != 0 && sb->level != 1 && sb->level != 4 && - sb->level != 5 && sb->level != 6 && sb->level != 10) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Unsupported RAID level: %d", sb->level); - - /* 1.x superblocks don't have a fixed size on disk. So we have to - read it again now that we now the max device count. */ - sb_size = sizeof (struct grub_raid_super_1x) + 2 * grub_le_to_cpu32 (sb->max_dev); - real_sb = grub_malloc (sb_size); - if (! real_sb) - return grub_errno; - - if (grub_disk_read (disk, sector, 0, sb_size, real_sb)) - { - grub_free (real_sb); - return grub_errno; - } - - array->name = grub_strdup (real_sb->set_name); - if (! array->name) - { - grub_free (real_sb); - return grub_errno; - } - - array->number = 0; - array->level = grub_le_to_cpu32 (real_sb->level); - array->layout = grub_le_to_cpu32 (real_sb->layout); - array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); - array->disk_size = grub_le_to_cpu64 (real_sb->size); - array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); - if (grub_le_to_cpu32 (real_sb->dev_number) < - grub_le_to_cpu32 (real_sb->max_dev)) - array->index = grub_le_to_cpu16 - (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); - else - array->index = 0xffff; /* disk will be later not used! */ - array->uuid_len = 16; - array->uuid = grub_malloc (16); - if (!array->uuid) - { - grub_free (real_sb); - return grub_errno; - } - - grub_memcpy (array->uuid, real_sb->set_uuid, 16); - - *start_sector = real_sb->data_offset; - - grub_free (real_sb); - return 0; -} - -static grub_err_t -grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, - grub_disk_addr_t *start_sector) -{ - grub_disk_addr_t sector; - grub_uint64_t size; - struct grub_raid_super_09 sb_09; - struct grub_raid_super_1x sb_1x; - grub_uint8_t minor_version; - - /* The sector where the mdraid 0.90 superblock is stored, if available. */ - size = grub_disk_get_size (disk); - sector = NEW_SIZE_SECTORS (size); - - if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb_09)) - return grub_errno; - - /* Look whether there is a mdraid 0.90 superblock. */ - if (sb_09.md_magic == SB_MAGIC) - return grub_mdraid_detect_09 (sector, &sb_09, array, start_sector); - - /* Check for an 1.x superblock. - * It's always aligned to a 4K boundary - * and depending on the minor version it can be: - * 0: At least 8K, but less than 12K, from end of device - * 1: At start of device - * 2: 4K from start of device. - */ - - for (minor_version = 0; minor_version < 3; ++minor_version) - { - switch (minor_version) - { - case 0: - sector = (size - 8 * 2) & ~(4 * 2 - 1); - break; - case 1: - sector = 0; - break; - case 2: - sector = 4 * 2; - break; - } - - if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x), - &sb_1x)) - return grub_errno; - - if (sb_1x.magic == SB_MAGIC) - return grub_mdraid_detect_1x (disk, sector, &sb_1x, array, - start_sector); - } - - /* Neither 0.90 nor 1.x. */ - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid"); -} - -static struct grub_raid grub_mdraid_dev = { - .name = "mdraid", - .detect = grub_mdraid_detect, - .next = 0 -}; - -GRUB_MOD_INIT (mdraid) -{ - grub_raid_register (&grub_mdraid_dev); -} - -GRUB_MOD_FINI (mdraid) -{ - grub_raid_unregister (&grub_mdraid_dev); -} diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 000000000..8d9fb8445 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,7 @@ +AUTOMAKE_OPTIONS = subdir-objects + +# AM_MAKEINFOFLAGS = --no-split --no-validate +info_TEXINFOS = grub.texi +grub_TEXINFOS = fdl.texi + + diff --git a/docs/grub.texi b/docs/grub.texi index 583cf98cb..54a2d8791 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -46,6 +46,8 @@ Invariant Sections. @subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}. @author Gordon Matzigkeit @author Yoshinori K. Okuji +@author Colin Watson +@author Colin D. Bennett @c The following two commands start the copyright page. @page @vskip 0pt plus 1filll @@ -77,6 +79,7 @@ This edition documents version @value{VERSION}. * Installation:: Installing GRUB on your drive * Booting:: How to boot different operating systems * Configuration:: Writing your own configuration file +* Theme file format:: Format of GRUB theme files * Network:: Downloading OS images from a network * Serial terminal:: Using GRUB via a serial line * Vendor power-on keys:: Changing GRUB behaviour on vendor power-on keys @@ -85,6 +88,7 @@ This edition documents version @value{VERSION}. * Interface:: The menu and the command-line * Commands:: The list of available builtin commands * Security:: Authentication and authorisation +* Supported kernels:: The list of supported kernels * Troubleshooting:: Error messages produced by GRUB * Invoking grub-install:: How to use the GRUB installer * Invoking grub-mkconfig:: Generate a GRUB configuration file @@ -105,8 +109,8 @@ This edition documents version @value{VERSION}. @menu * Overview:: What exactly GRUB is and how to use it * History:: From maggot to house fly -* Features:: GRUB features * Changes from GRUB Legacy:: Differences from previous versions +* Features:: GRUB features * Role of a boot loader:: The role of a boot loader @end menu @@ -223,7 +227,9 @@ scripting language: variables, conditionals, and loops are available. @item A small amount of persistent storage is available across reboots, using the @command{save_env} and @command{load_env} commands in GRUB and the -@command{grub-editenv} utility. +@command{grub-editenv} utility. For safety reasons this storage is only +available when installed on plain disk (no LVM or RAID), using non-checksumming +filesystem (no ZFS) and using BIOS or EFI functions (no ATA, USB or IEEE1275) @item GRUB 2 has more reliable ways to find its own files and those of target @@ -555,6 +561,14 @@ always. Therefore, GRUB provides you with a map file called the @dfn{device map}, which you must fix if it is wrong. @xref{Device map}, for more details. +On BIOS platforms GRUB has to use a so-called embedding zone. On msdos +partition tables, this is the space between the MBR and the first partition +(called the MBR gap or the boot track), while on GPT partition tables it +uses a BIOS Boot Partition (a partition with GUID +21686148-6449-6e6f-744e656564454649). If you use GRUB on a BIOS system, make +sure that the embedding zone is at least 31 KiB (512KiB or more +recommended). + If you still do want to install GRUB under a UNIX-like OS (such as @sc{gnu}), invoke the program @command{grub-install} (@pxref{Invoking grub-install}) as the superuser (@dfn{root}). @@ -575,18 +589,6 @@ Likewise, under GNU/Hurd, this has the same effect: # @kbd{grub-install /dev/hd0} @end example -If it is the first BIOS drive, this is the same as well: - -@example -# @kbd{grub-install '(hd0)'} -@end example - -Or you can omit the parentheses: - -@example -# @kbd{grub-install hd0} -@end example - But all the above examples assume that GRUB should use images under the root directory. If you want GRUB to use images under a directory other than the root directory, you need to specify the option @@ -618,6 +620,19 @@ installation. The format is defined in @ref{Device map}. Please be quite careful. If the output is wrong, it is unlikely that your computer will be able to boot with no problem. +Some BIOSes have a bug of exposing the first partition of a USB drive as a +floppy instead of exposing the USB drive as a hard disk (they call it +``USB-FDD'' boot). In such cases, you need to install like this: + +@example +# @kbd{losetup /dev/loop0 /dev/sdb1} +# @kbd{mount /dev/loop0 /mnt/usb} +# @kbd{grub-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0} +@end example + +This install doesn't conflict with standard install as long as they are in +separate directories. + Note that @command{grub-install} is actually just a shell script and the real task is done by @command{grub-mkimage} and @command{grub-setup}. Therefore, you may run those commands directly to install GRUB, without @@ -625,7 +640,6 @@ 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 @@ -828,11 +842,30 @@ Since GNU/Hurd is Multiboot-compliant, it is easy to boot it; there is nothing special about it. But do not forget that you have to specify a root partition to the kernel. -FIXME: this section is incomplete. - @enumerate @item -Run the command @command{boot} (@pxref{boot}). +Set GRUB's root device to the same drive as GNU/Hurd's. The command +@code{search --file --set /boot/gnumach.gz} or similar may help you +(@pxref{search}). + +@item +Load the kernel and the modules, like this: + +@example +@group +grub> @kbd{multiboot /boot/gnumach.gz root=device:hd0s1} +grub> @kbd{module /hurd/ext2fs.static ext2fs --readonly \ + --multiboot-command-line='$@{kernel-command-line@}' \ + --host-priv-port='$@{host-port@}' \ + --device-master-port='$@{device-port@}' \ + --exec-server-task='$@{exec-task@}' -T typed '$@{root@}' \ + '$(task-create)' '$(task-resume)'} +grub> @kbd{module /lib/ld.so.1 exec /hurd/exec '$(exec-task=task-create)'} +@end group +@end example + +@item +Finally, run the command @command{boot} (@pxref{boot}). @end enumerate @@ -865,6 +898,14 @@ grub> @kbd{linux /vmlinuz root=/dev/sda1 acpi=off} See the documentation in the Linux source tree for complete information on the available options. +With @command{linux} GRUB uses 32-bit protocol. Some BIOS services like APM +or EDD aren't available with this protocol. In this case you need to use +@command{linux16} + +@example +grub> @kbd{linux16 /vmlinuz root=/dev/sda1 acpi=off} +@end example + @item If you use an initrd, execute the command @command{initrd} (@pxref{initrd}) after @command{linux}: @@ -873,6 +914,12 @@ after @command{linux}: grub> @kbd{initrd /initrd} @end example +If you used @command{linux16} you need to use @command{initrd16}: + +@example +grub> @kbd{initrd16 /initrd} +@end example + @item Finally, run the command @command{boot} (@pxref{boot}). @end enumerate @@ -944,7 +991,6 @@ need to write the whole thing by hand. * Simple configuration:: Recommended for most users * Shell-like scripting:: For power users and developers * Embedded configuration:: Embedding a configuration file into GRUB -* Themes:: Graphical menu themes @end menu @@ -988,6 +1034,8 @@ it as a new default entry for use by future runs of GRUB. This is only useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because @samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with @command{grub-set-default} or @command{grub-reboot}. Unset by default. +The remarks of @pxref{Changes from GRUB Legacy} on the availability +of @samp{save_env} apply. @item GRUB_TIMEOUT Boot the default entry this many seconds after the menu is displayed, unless @@ -1051,7 +1099,7 @@ A command to configure the serial port when using the serial console. Command-line arguments to add to menu entries for the Linux kernel. @item GRUB_CMDLINE_LINUX_DEFAULT -Unless @samp{GRUB_DISABLE_LINUX_RECOVERY} is set to @samp{true}, two menu +Unless @samp{GRUB_DISABLE_RECOVERY} is set to @samp{true}, two menu entries will be generated for each Linux kernel: one default entry and one entry for recovery mode. This option lists command-line arguments to add only to the default menu entry, after those listed in @@ -1074,13 +1122,9 @@ 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_RECOVERY +@item GRUB_DISABLE_RECOVERY If this option is set to @samp{true}, disable the generation of recovery -mode menu entries for Linux. - -@item GRUB_DISABLE_NETBSD_RECOVERY -If this option is set to @samp{true}, disable the generation of recovery -mode menu entries for NetBSD. +mode menu entries. @item GRUB_VIDEO_BACKEND If graphical video support is required, either because the @samp{gfxterm} @@ -1106,7 +1150,6 @@ The image will be scaled if necessary to fit the screen. @item GRUB_THEME Set a theme for use with the @samp{gfxterm} graphical terminal. -@xref{Themes}. @item GRUB_GFXPAYLOAD_LINUX Set to @samp{text} to force the Linux kernel to boot in normal text mode, @@ -1206,8 +1249,10 @@ The @samp{$} character retains its special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: @samp{$}, @samp{"}, @samp{\}, or newline. A backslash-newline pair is treated as a line continuation (that is, it is -removed from the input stream and effectively ignored). A double quote may -be quoted within double quotes by preceding it with a backslash. +removed from the input stream and effectively ignored@footnote{Currently a +backslash-newline pair within a variable name is not handled properly, so +use this feature with some care.}). A double quote may be quoted within +double quotes by preceding it with a backslash. @heading Variable expansion @@ -1219,11 +1264,15 @@ which could be interpreted as part of the name. Normal variable names begin with an alphabetic character, followed by zero or more alphanumeric characters. -Positional variable names consist of one or more digits. These are reserved -for future expansion. +Positional variable names consist of one or more digits. They represent +parameters passed to function calls, with @samp{$1} representing the first +parameter, and so on. The special variable name @samp{?} expands to the exit status of the most -recently executed command. +recently executed command. When positional variable names are active, other +special variable names @samp{@@}, @samp{*} and @samp{#} are defined and they +expand to all positional parameters with necessary quoting, positional +parameters without any quoting, and positional parameter count respectively. @heading Comments @@ -1237,7 +1286,9 @@ and terminated by a semicolon or a newline. The first word specifies the command to be executed. The remaining words are passed as arguments to the invoked command. -The return value of a simple command is its exit status. +The return value of a simple command is its exit status. If the reserved +word @code{!} precedes the command, then the return value is instead the +logical negation of the command's exit status. @heading Compound commands @@ -1284,6 +1335,45 @@ the body. @xref{menuentry}. @end table +@heading Built-in Commands + +Some built-in commands are also provided by GRUB script to help script +writers perform actions that are otherwise not possible. For example, these +include commands to jump out of a loop without fully completing it, etc. + +@table @asis +@item break [@code{n}] +Exit from within a @code{for}, @code{while}, or @code{until} loop. If +@code{n} is specified, break @code{n} levels. @code{n} must be greater than +or equal to 1. If @code{n} is greater than the number of enclosing loops, +all enclosing loops are exited. The return value is 0 unless @code{n} is +not greater than or equal to 1. + +@item continue [@code{n}] +Resume the next iteration of the enclosing @code{for}, @code{while} or +@code{until} loop. If @code{n} is specified, resume at the @code{n}th +enclosing loop. @code{n} must be greater than or equal to 1. If @code{n} +is greater than the number of enclosing loops, the last enclosing loop (the +@dfn{top-level} loop) is resumed. The return value is 0 unless @code{n} is +not greater than or equal to 1. + +@item return [@code{n}] +Causes a function to exit with the return value specified by @code{n}. If +@code{n} is omitted, the return status is that of the last command executed +in the function body. If used outside a function the return status is +false. + +@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 +@code{$#}-@code{n}+1 are unset. @code{n} must be a non-negative number less +than or equal to @code{$#}. If @code{n} is 0, no parameters are changed. +If @code{n} is not given, it is assumed to be 1. If @code{n} is greater +than @code{$#}, the positional parameters are not changed. The return +status is greater than zero if @code{n} is greater than @code{$#} or less +than zero; otherwise 0. + +@end table @node Embedded configuration @section Embedding a configuration file into GRUB @@ -1352,9 +1442,372 @@ fi The embedded configuration file may not contain menu entries directly, but may only read them from elsewhere using @command{configfile}. +@node Theme file format +@chapter Theme file format +@section Introduction +The GRUB graphical menu supports themes that can customize the layout and +appearance of the GRUB boot menu. The theme is configured through a plain +text file that specifies the layout of the various GUI components (including +the boot menu, timeout progress bar, and text messages) as well as the +appearance using colors, fonts, and images. Example is available in docs/example_theme.txt + +@section Theme Elements +@subsection Colors + +Colors can be specified in several ways: + +@itemize +@item HTML-style ``#RRGGBB'' or ``#RGB'' format, where *R*, *G*, and *B* are hexadecimal digits (e.g., ``#8899FF'') +@item as comma-separated decimal RGB values (e.g., ``128, 128, 255'') +@item with ``SVG 1.0 color names'' (e.g., ``cornflowerblue'') which must be specified in lowercase. +@end itemize +@subsection Fonts +The fonts GRUB uses ``PFF2 font format'' bitmap fonts. Fonts are specified +with full font names. Currently there is no +provision for a preference list of fonts, or deriving one font from another. +Fonts are loaded with the ``loadfont'' command in GRUB. To see the list of +loaded fonts, execute the ``lsfonts'' command. If there are too many fonts to +fit on screen, do ``set pager=1'' before executing ``lsfonts''. + + +@subsection Progress Bar + +@float Figure, Pixmap-styled progress bar +@c @image{Theme_progress_bar,,,,.png} +@end float + +@float Figure, Plain progress bar, drawn with solid color. +@c @image{Theme_progress_bar_filled,,,,.png} +@end float + +Progress bars are used to display the remaining time before GRUB boots the +default menu entry. To create a progress bar that will display the remaining +time before automatic boot, simply create a ``progress_bar'' component with +the id ``__timeout__''. This indicates to GRUB that the progress bar should +be updated as time passes, and it should be made invisible if the countdown to +automatic boot is interrupted by the user. + +Progress bars may optionally have text displayed on them. This is controlled +through the ``show_text'' property, which can be set to either ``true'' or +``false'' to control whether text is displayed. When GRUB is counting down to +automatic boot, the text informs the user of the number of seconds remaining. + + +@subsection Circular Progress Indicator + +@c @image{Theme_circular_progress,,,,.png} + +The circular progress indicator functions similarly to the progress bar. When +given an id of ``__timeout__'', GRUB updates the circular progress indicator's +value to indicate the time remaining. For the circular progress indicator, +there are two images used to render it: the *center* image, and the *tick* +image. The center image is rendered in the center of the component, while the +tick image is used to render each mark along the circumference of the +indicator. + + +@subsection Labels + +Text labels can be placed on the boot screen. The font, color, and horizontal +alignment can be specified for labels. If a label is given the id +``__timeout__'', then the ``text'' property for that label is also updated +with a message informing the user of the number of seconds remaining until +automatic boot. This is useful in case you want the text displayed somewhere +else instead of directly on the progress bar. + + +@subsection Boot Menu + +@c @image{Theme_boot_menu,,,,.png} + +The boot menu where GRUB displays the menu entries from the ``grub.cfg'' file. +It is a list of items, where each item has a title and an optional icon. The +icon is selected based on the *classes* specified for the menu entry. If +there is a PNG file named ``myclass.png'' in the ``grub/themes/icons'' +directory, it will be displayed for items which have the class *myclass*. The +boot menu can be customized in several ways, such as the font and color used +for the menu entry title, and by specifying styled boxes for the menu itself +and for the selected item highlight. + + +@subsection Styled Boxes + +One of the most important features for customizing the layout is the use of + *styled boxes*. A styled box is composed of 9 rectangular (and potentially +empty) regions, which are used to seamlessly draw the styled box on screen: + +@multitable @columnfractions 0.3 0.3 0.3 +@item Northwest (nw) @tab North (n) @tab Northeast (ne) +@item West (w) @tab Center (c) @tab East (e) +@item Southwest (sw) @tab South (s) @tab Southeast (se) +@end multitable + +To support any size of box on screen, the center slice and the slices for the +top, bottom, and sides are all scaled to the correct size for the component on +screen, using the following rules: + +@enumerate +@item The edge slices (north, south, east, and west) are scaled in the direction of the edge they are adjacent to. For instance, the west slice is scaled vertically. +@item The corner slices (northwest, northeast, southeast, and southwest) are not scaled. +@item The center slice is scaled to fill the remaining space in the middle. +@end enumerate + +As an example of how an image might be sliced up, consider the styled box +used for a terminal view. + +@float Figure, An example of the slices (in red) used for a terminal window. This drawing was created and sliced in Inkscape_, as the next section explains. +@c @image{Box_slice_example_terminal,,,,.png} +@end float + +@subsection Creating Styled Box Images + +The Inkscape_ scalable vector graphics editor is a very useful tool for +creating styled box images. One process that works well for slicing a drawing +into the necessary image slices is: + +@enumerate +@item Create or open the drawing you'd like use. +@item Create a new layer on the top of the layer stack. Make it visible. Select this layer as the current layer. +@item Draw 9 rectangles on your drawing where you'd like the slices to be. Clear the fill option, and set the stroke to 1 pixel wide solid stroke. The corners of the slices must meet precisely; if it is off by a single pixel, it will probably be evident when the styled box is rendered in the GRUB menu. You should probably go to File | Document Properties | Grids and enable a grid or create a guide (click on one of the rulers next to the drawing and drag over the drawing; release the mouse button to place the guide) to help place the rectangles precisely. +@item Right click on the center slice rectangle and choose Object Properties. Change the "Id" to ``slice_c`` and click Set. Repeat this for the remaining 8 rectangles, giving them Id values of ``slice_n``, ``slice_ne``, ``slice_e``, and so on according to the location. +@item Save the drawing. +@item Select all the slice rectangles. With the slice layer selected, you can simply press Ctrl+A to select all rectangles. The status bar should indicate that 9 rectangles are selected. +@item Click the layer hide icon for the slice layer in the layer palette. The rectangles will remain selected, even though they are hidden. +@item Choose File | Export Bitmap and check the *Batch export 9 selected objects* box. Make sure that *Hide all except selected* is unchecked. click *Export*. This will create PNG files in the same directory as the drawing, named after the slices. These can now be used for a styled box in a GRUB theme. +@end enumerate + +@section Theme File Manual + +The theme file is a plain text file. Lines that begin with ``#`` are ignored +and considered comments. (Note: This may not be the case if the previous line +ended where a value was expected.) + +The theme file contains two types of statements: +@enumerate +@item Global properties. +@item Component construction. +@end enumerate + +@subsection Global Properties + +@subsection Format + +Global properties are specified with the simple format: +@itemize +@item name1: value1 +@item name2: "value which may contain spaces" +@item name3: #88F +@end itemize + +In this example, name3 is assigned a color value. + + +@subsection Global Property List + +@multitable @columnfractions 0.3 0.6 +@item title-text @tab Specifies the text to display at the top center of the screen as a title. +@item title-font @tab Defines the font used for the title message at the top of the screen. +@item title-color @tab Defines the color of the title message. +@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry. +@item message-color @tab Defines the color of the message text. +@item message-bg-color @tab Defines the background color of the message text area. +@item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size. +@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified. +@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty. +@end multitable + + +@subsection Component Construction + +Greater customizability comes is provided by components. A tree of components +forms the user interface. *Containers* are components that can contain other +components, and there is always a single root component which is an instance +of a *canvas* container. + +Components are created in the theme file by prefixing the type of component +with a '+' sign: + +@code{ + label @{ text="GRUB" font="aqui 11" color="#8FF" @} } + +properties of a component are specified as "name = value" (whitespace +surrounding tokens is optional and is ignored) where *value* may be: +@itemize +@item a single word (e.g., ``align = center``, ``color = #FF8080``), +@item a quoted string (e.g., ``text = "Hello, World!"``), or +@item a tuple (e.g., ``preferred_size = (120, 80)``). +@end itemize + +@subsection Component List + +The following is a list of the components and the properties they support. + +@itemize +@item label + A label displays a line of text. + + Properties: + @multitable @columnfractions 0.2 0.7 + @item text @tab The text to display. + @item font @tab The font to use for text display. + @item color @tab The color of the text. + @item align @tab The horizontal alignment of the text within the component. Options are ``left``, ``center``, and ``right``. + @end multitable + +@item image + A component that displays an image. The image is scaled to fit the + component, although the preferred size defaults to the image's original + size unless the ``preferred_size`` property is explicitly set. + + Properties: + + @multitable @columnfractions 0.2 0.7 + @item file @tab The full path to the image file to load. + @end multitable + +@item progress_bar + Displays a horizontally oriented progress bar. It can be rendered using + simple solid filled rectangles, or using a pair of pixmap styled boxes. + + Properties: + + @multitable @columnfractions 0.2 0.7 + @item fg_color @tab The foreground color for plain solid color rendering. + @item bg_color @tab The background color for plain solid color rendering. + @item border_color @tab The border color for plain solid color rendering. + @item text_color @tab The text color. + @item show_text @tab Boolean value indicating whether or not text should be displayed on the progress bar. If set to *false*, then no text will be displayed on the bar. If set to any other value, text will be displayed on the bar. + @item bar_style @tab The styled box specification for the frame of the progress bar. Example: ``progress_frame_*.png`` + @item highlight_style @tab The styled box specification for the highlighted region of the progress bar. This box will be used to paint just the highlighted region of the bar, and will be increased in size as the bar nears completion. Example: ``progress_hl_*.png``. + @item text @tab The text to display on the progress bar. If the progress bar's ID is set to ``__timeout__``, then GRUB will updated this property with an informative message as the timeout approaches. + @item value @tab The progress bar current value. Normally not set manually. + @item start @tab The progress bar start value. Normally not set manually. + @item end @tab The progress bar end value. Normally not set manually. + @end multitable + +@item circular_progress + Displays a circular progress indicator. The appearance of this component + is determined by two images: the *center* image and the *tick* image. The + center image is generally larger and will be drawn in the center of the + component. Around the circumference of a circle within the component, the + tick image will be drawn a certain number of times, depending on the + properties of the component. + + Properties: + + @multitable @columnfractions 0.3 0.6 + @item center_bitmap + @tab The file name of the image to draw in the center of the component. + @item tick_bitmap + @tab The file name of the image to draw for the tick marks. + @item num_ticks + @tab The number of ticks that make up a full circle. + @item ticks_disappear + @tab Boolean value indicating whether tick marks should progressively appear, + or progressively disappear as *value* approaches *end*. Specify + ``true`` or ``false``. + @item value + @tab The progress indicator current value. Normally not set manually. + @item start + @tab The progress indicator start value. Normally not set manually. + @item end + @tab The progress indicator end value. Normally not set manually. + @end multitable +@item boot_menu + Displays the GRUB boot menu. It allows selecting items and executing them. + + Properties: + + @multitable @columnfractions 0.4 0.5 + @item item_font + @tab The font to use for the menu item titles. + @item selected_item_font + @tab The font to use for the selected menu item, or ``inherit`` (the default) + to use ``item_font`` for the selected menu item as well. + @item item_color + @tab The color to use for the menu item titles. + @item selected_item_color + @tab The color to use for the selected menu item, or ``inherit`` (the default) + to use ``item_color`` for the selected menu item as well. + @item icon_width + @tab The width of menu item icons. Icons are scaled to the specified size. + @item icon_height + @tab The height of menu item icons. + @item item_height + @tab The height of each menu item in pixels. + @item item_padding + @tab The amount of space in pixels to leave on each side of the menu item + contents. + @item item_icon_space + @tab The space between an item's icon and the title text, in pixels. + @item item_spacing + @tab The amount of space to leave between menu items, in pixels. + @item menu_pixmap_style + @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 selected_item_pixmap_style + @tab The image file pattern for the selected item highlight styled box. + @item scrollbar + @tab Boolean value indicating whether the scroll bar should be drawn if the + frame and thumb styled boxes are configured. + @item scrollbar_frame + @tab The image file pattern for the entire scroll bar. + Example: ``scrollbar_*.png`` + @item scrollbar_thumb + @tab The image file pattern for the scroll bar thumb (the part of the scroll + bar that moves as scrolling occurs). + Example: ``scrollbar_thumb_*.png`` + @item max_items_shown + @tab The maximum number of items to show on the menu. If there are more than + *max_items_shown* items in the menu, the list will scroll to make all + items accessible. + @end multitable + +@item canvas + Canvas is a container that allows manual placement of components within it. + It does not alter the positions of its child components. It assigns all + child components their preferred sizes. + +@item hbox + The *hbox* container lays out its children from left to right, giving each + one its preferred width. The height of each child is set to the maximum of + the preferred heights of all children. + +@item vbox + The *vbox* container lays out its children from top to bottom, giving each + one its preferred height. The width of each child is set to the maximum of + the preferred widths of all children. +@end itemize + + +@subsection Common properties + +The following properties are supported by all components: +@table @samp +@item left + The distance from the left border of container to left border of the object in either of three formats: + @multitable @columnfractions 0.2 0.7 + @item x @tab Value in pixels + @item p% @tab Percentage + @item p%+x @tab mixture of both + @end multitable +@item top + The distance from the left border of container to left border of the object in same format. +@item width + The width of object in same format. +@item height + The height of object in same format. +@item id + The identifier for the component. This can be any arbitrary string. + The ID can be used by scripts to refer to various components in the GUI + component tree. Currently, there is one special ID value that GRUB + recognizes: + + @multitable @columnfractions 0.2 0.7 + @item ``__timeout__`` @tab Any component with this ID will have its *text*, *start*, *end*, *value*, and *visible* properties set by GRUB when it is counting down to an automatic boot of the default menu entry. + @end multitable +@end table -@node Themes -@section Graphical menu themes @node Network @@ -1367,8 +1820,7 @@ To generate a PXE boot image, run: @example @group -grub-mkimage --format=i386-pc --output=core.img --prefix='(pxe)/boot/grub' pxe pxecmd -cat /boot/grub/pxeboot.img core.img >grub.pxe +grub-mkimage --format=i386-pc-pxe --output=grub.pxe --prefix='(pxe)/boot/grub' pxe pxecmd @end group @end example @@ -1378,6 +1830,9 @@ 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). +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{(pxe)} device. @@ -1416,7 +1871,7 @@ The boot file name provided by DHCP. Read-only. The name of the DHCP server responsible for these boot parameters. Read-only. -@item net_pxe_blksize +@item pxe_blksize The PXE transfer block size. Read-write, defaults to 512. @item pxe_default_server @@ -1986,8 +2441,7 @@ The serial port is not used as a communication channel unless the @command{terminal_input} or @command{terminal_output} command is used (@pxref{terminal_input}, @pxref{terminal_output}). -This command is only available if GRUB is compiled with serial -support. See also @ref{Serial terminal}. +See also @ref{Serial terminal}. @end deffn @@ -2094,6 +2548,7 @@ you forget a command, you can run the command @command{help} * pxe_unload:: Unload the PXE environment * reboot:: Reboot your computer * search:: Search devices by file, label, or UUID +* sendkey:: Emulate keystrokes * set:: Set an environment variable * unset:: Unset an environment variable * uppermem:: Set the upper memory size @@ -2477,7 +2932,7 @@ This command is only available on x86 systems. @node ls @subsection ls -@deffn Command ls [arg] +@deffn Command ls [arg @dots{}] List devices or files. With no arguments, print all devices known to GRUB. @@ -2604,6 +3059,154 @@ commands are aliases for @samp{search --file}, @samp{search --label}, and @end deffn +@node sendkey +@subsection sendkey + +@deffn Command sendkey @ + [@option{--num}|@option{--caps}|@option{--scroll}|@option{--insert}|@ +@option{--pause}|@option{--left-shift}|@option{--right-shift}|@ +@option{--sysrq}|@option{--numkey}|@option{--capskey}|@option{--scrollkey}|@ +@option{--insertkey}|@option{--left-alt}|@option{--right-alt}|@ +@option{--left-ctrl}|@option{--right-ctrl} @ + @samp{on}|@samp{off}]@dots{} @ + [@option{no-led}] @ + keystroke +Insert keystrokes into the keyboard buffer when booting. Sometimes an +operating system or chainloaded boot loader requires particular keys to be +pressed: for example, one might need to press a particular key to enter +"safe mode", or when chainloading another boot loader one might send +keystrokes to it to navigate its menu. + +You may provide up to 16 keystrokes (the length of the BIOS keyboard +buffer). Keystroke names may be upper-case or lower-case letters, digits, +or taken from the following table: + +@c Please keep this table in the same order as in +@c commands/i386/pc/sendkey.c, for ease of maintenance. +@c Exception: The function and numeric keys are sorted, for aesthetics. + +@multitable @columnfractions .4 .5 +@headitem Name @tab Key +@item escape @tab Escape +@item exclam @tab ! +@item at @tab @@ +@item numbersign @tab # +@item dollar @tab $ +@item percent @tab % +@item caret @tab ^ +@item ampersand @tab & +@item asterisk @tab * +@item parenleft @tab ( +@item parenright @tab ) +@item minus @tab - +@item underscore @tab _ +@item equal @tab = +@item plus @tab + +@item backspace @tab Backspace +@item tab @tab Tab +@item bracketleft @tab [ +@item braceleft @tab @{ +@item bracketright @tab ] +@item braceright @tab @} +@item enter @tab Enter +@item control @tab press and release Control +@item semicolon @tab ; +@item colon @tab : +@item quote @tab ' +@item doublequote @tab " +@item backquote @tab ` +@item tilde @tab ~ +@item shift @tab press and release left Shift +@item backslash @tab \ +@item bar @tab | +@item comma @tab , +@item less @tab < +@item period @tab . +@item greater @tab > +@item slash @tab / +@item question @tab ? +@item rshift @tab press and release right Shift +@item alt @tab press and release Alt +@item space @tab space bar +@item capslock @tab Caps Lock +@item F1 @tab F1 +@item F2 @tab F2 +@item F3 @tab F3 +@item F4 @tab F4 +@item F5 @tab F5 +@item F6 @tab F6 +@item F7 @tab F7 +@item F8 @tab F8 +@item F9 @tab F9 +@item F10 @tab F10 +@item F11 @tab F11 +@item F12 @tab F12 +@item num1 @tab 1 (numeric keypad) +@item num2 @tab 2 (numeric keypad) +@item num3 @tab 3 (numeric keypad) +@item num4 @tab 4 (numeric keypad) +@item num5 @tab 5 (numeric keypad) +@item num6 @tab 6 (numeric keypad) +@item num7 @tab 7 (numeric keypad) +@item num8 @tab 8 (numeric keypad) +@item num9 @tab 9 (numeric keypad) +@item num0 @tab 0 (numeric keypad) +@item numperiod @tab . (numeric keypad) +@item numend @tab End (numeric keypad) +@item numdown @tab Down (numeric keypad) +@item numpgdown @tab Page Down (numeric keypad) +@item numleft @tab Left (numeric keypad) +@item numcenter @tab 5 with Num Lock inactive (numeric keypad) +@item numright @tab Right (numeric keypad) +@item numhome @tab Home (numeric keypad) +@item numup @tab Up (numeric keypad) +@item numpgup @tab Page Up (numeric keypad) +@item numinsert @tab Insert (numeric keypad) +@item numdelete @tab Delete (numeric keypad) +@item numasterisk @tab * (numeric keypad) +@item numminus @tab - (numeric keypad) +@item numplus @tab + (numeric keypad) +@item numslash @tab / (numeric keypad) +@item numenter @tab Enter (numeric keypad) +@item delete @tab Delete +@item insert @tab Insert +@item home @tab Home +@item end @tab End +@item pgdown @tab Page Down +@item pgup @tab Page Up +@item down @tab Down +@item up @tab Up +@item left @tab Left +@item right @tab Right +@end multitable + +As well as keystrokes, the @command{sendkey} command takes various options +that affect the BIOS keyboard status flags. These options take an @samp{on} +or @samp{off} parameter, specifying that the corresponding status flag be +set or unset; omitting the option for a given status flag will leave that +flag at its initial state at boot. The @option{--num}, @option{--caps}, +@option{--scroll}, and @option{--insert} options emulate setting the +corresponding mode, while the @option{--numkey}, @option{--capskey}, +@option{--scrollkey}, and @option{--insertkey} options emulate pressing and +holding the corresponding key. The other status flag options are +self-explanatory. + +If the @option{--no-led} option is given, the status flag options will have +no effect on keyboard LEDs. + +If the @command{sendkey} command is given multiple times, then only the last +invocation has any effect. + +Since @command{sendkey} manipulates the BIOS keyboard buffer, it may cause +hangs, reboots, or other misbehaviour on some systems. If the operating +system or boot loader that runs after GRUB uses its own keyboard driver +rather than the BIOS keyboard functions, then @command{sendkey} will have no +effect. + +This command is only available on PC BIOS systems. +@end deffn + + @node set @subsection set @@ -2694,6 +3297,145 @@ adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} commands. +@node Supported kernels +@chapter Supported boot targets + +X86 support is summarised in the following table. ``Yes'' means that the kernel works on the given platform, ``crashes'' means an early kernel crash which we hope will be fixed by concerned kernel developers. ``no'' means GRUB doesn't load the given kernel on a given platform. ``headless'' means that the kernel works but lacks console drivers (you can still use serial or network console). In case of ``no'' and ``crashes'' the reason is given in footnote. +@multitable @columnfractions .50 .22 .22 +@item @tab BIOS @tab Coreboot +@item BIOS chainloading @tab yes @tab no (1) +@item NTLDR @tab yes @tab no (1) +@item FreeBSD bootloader @tab yes @tab crashes (1) +@item 32-bit kFreeBSD @tab yes @tab crashes (2,6) +@item 64-bit kFreeBSD @tab yes @tab crashes (2,6) +@item 32-bit kNetBSD @tab yes @tab crashes (1) +@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 +@item Multiboot2 @tab yes @tab yes +@item 32-bit Linux (legacy protocol) @tab yes @tab no (1) +@item 64-bit Linux (legacy protocol) @tab yes @tab no (1) +@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 ? +@item 64-bit XNU @tab yes @tab ? +@item 32-bit EFI chainloader @tab no (3) @tab no (3) +@item 64-bit EFI chainloader @tab no (3) @tab no (3) +@item Appleloader @tab no (3) @tab no (3) +@end multitable + +@multitable @columnfractions .50 .22 .22 +@item @tab Multiboot @tab Qemu +@item BIOS chainloading @tab no (1) @tab no (1) +@item NTLDR @tab no (1) @tab no (1) +@item FreeBSD bootloader @tab crashes (1) @tab crashes (1) +@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) +@item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6) +@item 32-bit kNetBSD @tab crashes (1) @tab crashes (1) +@item 64-bit kNetBSD @tab yes @tab yes +@item 32-bit kOpenBSD @tab yes @tab yes +@item 64-bit kOpenBSD @tab yes @tab yes +@item Multiboot @tab yes @tab yes +@item Multiboot2 @tab yes @tab yes +@item 32-bit Linux (legacy protocol) @tab no (1) @tab no (1) +@item 64-bit Linux (legacy protocol) @tab no (1) @tab no (1) +@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 ? @tab ? +@item 64-bit XNU @tab ? @tab ? +@item 32-bit EFI chainloader @tab no (3) @tab no (3) +@item 64-bit EFI chainloader @tab no (3) @tab no (3) +@item Appleloader @tab no (3) @tab no (3) +@end multitable + +@multitable @columnfractions .50 .22 .22 +@item @tab 32-bit EFI @tab 64-bit EFI +@item BIOS chainloading @tab no (1) @tab no (1) +@item NTLDR @tab no (1) @tab no (1) +@item FreeBSD bootloader @tab crashes (1) @tab crashes (1) +@item 32-bit kFreeBSD @tab headless @tab headless +@item 64-bit kFreeBSD @tab headless @tab headless +@item 32-bit kNetBSD @tab crashes (1) @tab crashes (1) +@item 64-bit kNetBSD @tab yes @tab yes +@item 32-bit kOpenBSD @tab headless @tab headless +@item 64-bit kOpenBSD @tab headless @tab headless +@item Multiboot @tab yes @tab yes +@item Multiboot2 @tab yes @tab yes +@item 32-bit Linux (legacy protocol) @tab no (1) @tab no (1) +@item 64-bit Linux (legacy protocol) @tab no (1) @tab no (1) +@item 32-bit Linux (modern protocol) @tab yes @tab yes +@item 64-bit Linux (modern protocol) @tab yes @tab yes +@item 32-bit XNU @tab yes @tab yes +@item 64-bit XNU @tab yes (5) @tab yes +@item 32-bit EFI chainloader @tab yes @tab no (4) +@item 64-bit EFI chainloader @tab no (4) @tab yes +@item Appleloader @tab yes @tab yes +@end multitable + +@multitable @columnfractions .50 .22 .22 +@item @tab IEEE1275 +@item BIOS chainloading @tab no (1) +@item NTLDR @tab no (1) +@item FreeBSD bootloader @tab crashes (1) +@item 32-bit kFreeBSD @tab crashes (6) +@item 64-bit kFreeBSD @tab crashes (6) +@item 32-bit kNetBSD @tab crashes (1) +@item 64-bit kNetBSD @tab ? +@item 32-bit kOpenBSD @tab ? +@item 64-bit kOpenBSD @tab ? +@item Multiboot @tab ? +@item Multiboot2 @tab ? +@item 32-bit Linux (legacy protocol) @tab no (1) +@item 64-bit Linux (legacy protocol) @tab no (1) +@item 32-bit Linux (modern protocol) @tab ? +@item 64-bit Linux (modern protocol) @tab ? +@item 32-bit XNU @tab ? +@item 64-bit XNU @tab ? +@item 32-bit EFI chainloader @tab no (3) +@item 64-bit EFI chainloader @tab no (3) +@item Appleloader @tab no (3) +@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 +@item Requires ACPI +@end enumerate + +PowerPC and Sparc ports support only Linux. MIPS port supports Linux and multiboot2. + +@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. + +Following variables must be defined: + +@multitable @columnfractions .30 .65 +@item GRUB_PAYLOADS_DIR @tab directory containing the required kernels +@item GRUB_CBFSTOOL @tab cbfstoll from Coreboot package (for coreboot platform only) +@item GRUB_COREBOOT_ROM @tab empty Coreboot ROM +@item GRUB_QEMU_OPTS @tab additional options to be supplied to QEMU +@end multitable + +Required files are: + +@multitable @columnfractions .40 .55 +@item kfreebsd_env.i386 @tab 32-bit kFreeBSD device hints +@item kfreebsd.i386 @tab 32-bit FreeBSD kernel image +@item kfreebsd.x86_64, kfreebsd_env.x86_64 @tab same from 64-bit kFreeBSD +@item knetbsd.i386 @tab 32-bit NetBSD kernel image +@item knetbsd.miniroot.i386 @tab 32-bit kNetBSD miniroot.kmod. +@item knetbsd.x86_64, knetbsd.miniroot.x86_64 @tab same from 64-bit kNetBSD +@item kopenbsd.i386 @tab 32-bit OpenBSD kernel bsd.rd image +@item kopenbsd.x86_64 @tab same from 64-bit kOpenBSD +@item linux.i386 @tab 32-bit Linux +@item linux.x86_64 @tab 64-bit Linux +@end multitable + @node Troubleshooting @chapter Error messages produced by GRUB diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m new file mode 100644 index 000000000..0c0570f27 --- /dev/null +++ b/docs/man/grub-menulst2cfg.h2m @@ -0,0 +1,3 @@ +[NAME] +grub-menulst2cfg \- transform legacy menu.lst into grub.cfg + diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m new file mode 100644 index 000000000..e0ae9dedb --- /dev/null +++ b/docs/man/grub-mklayout.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mklayout \- generate a GRUB keyboard layout file diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m new file mode 100644 index 000000000..26defe876 --- /dev/null +++ b/docs/man/grub-mknetdir.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mknetdir \- prepare a GRUB netboot directory. diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m index 3ac13d7ed..dd0793cfd 100644 --- a/docs/man/grub-set-default.h2m +++ b/docs/man/grub-set-default.h2m @@ -1,2 +1,2 @@ [NAME] -grub-set-default \- set the default boot entry for GRUB +grub-set-default \- set the saved default boot entry for GRUB diff --git a/efiemu/runtime/efiemu.sh b/efiemu/runtime/efiemu.sh deleted file mode 100644 index 5a492dc2f..000000000 --- a/efiemu/runtime/efiemu.sh +++ /dev/null @@ -1,4 +0,0 @@ -gcc -c -m32 -DELF32 -o efiemu32.o ./efiemu.c -Wall -Werror -nostdlib -O2 -I. -I../../include -gcc -c -m64 -DELF64 -o efiemu64_c.o ./efiemu.c -Wall -Werror -mcmodel=large -O2 -I. -I../../include -gcc -c -m64 -DELF64 -o efiemu64_s.o ./efiemu.S -Wall -Werror -mcmodel=large -O2 -I. -I../../include -ld -o efiemu64.o -r efiemu64_s.o efiemu64_c.o -nostdlib diff --git a/gencmdlist.sh b/gencmdlist.sh deleted file mode 100644 index ed5965f07..000000000 --- a/gencmdlist.sh +++ /dev/null @@ -1,22 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2005,2009 Free Software Foundation, Inc. -# -# This gensymlist.sh is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect command names. - -module=$1 - -grep -v "^#" | sed -n \ - -e "/grub_register_command *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $module/;p;}" \ - -e "/grub_register_extcmd *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $module/;p;}" \ - -e "/grub_register_command_p1 *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $module/;p;}" - diff --git a/gendistlist.sh b/gendistlist.sh deleted file mode 100755 index 102c0c11c..000000000 --- a/gendistlist.sh +++ /dev/null @@ -1,46 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc. -# -# This gendistlist.sh is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Generate a list of distributed files. - -EXTRA_DISTFILES="AUTHORS COPYING ChangeLog DISTLIST INSTALL NEWS README \ - THANKS TODO Makefile.in aclocal.m4 autogen.sh config.guess \ - config.h.in config.sub configure configure.ac gencmdlist.sh \ - gendistlist.sh genfslist.sh genhandlerlist.sh geninit.sh \ - geninitheader.sh genkernsyms.sh.in genmk.rb genmoddep.awk \ - genmodsrc.sh genpartmaplist.sh genparttoollist.sh \ - genvideolist.sh \ - gensymlist.sh.in install-sh mkinstalldirs stamp-h.in" - -DISTDIRS="boot bus commands conf disk docs efiemu font fs hello hook include io \ - kern lib loader mmap normal partmap parttool script term util video" - -LC_COLLATE=C -export LC_COLLATE - -for f in $EXTRA_DISTFILES; do - echo $f -done - -dir=`dirname $0` -cd $dir - -for dir in $DISTDIRS; do - for d in `find $dir -type d ! -name .svn ! -name .bzr | sort`; do - find $d -maxdepth 1 -name '*.[chSy]' -o -name '*.mk' -o -name '*.rmk' \ - -o -name '*.rb' -o -name '*.in' -o -name '*.tex' -o -name '*.texi' \ - -o -name '*.info' -o -name 'grub.cfg' -o -name 'README' \ - -o -name '*.sc' -o -name 'mdate-sh' -o -name '*.sh' \ - -o -name 'grub-dumpdevtree' -o -name '*.lua' | sort - done -done diff --git a/genfslist.sh b/genfslist.sh deleted file mode 100644 index 6fa7e927d..000000000 --- a/genfslist.sh +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2005,2008 Free Software Foundation, Inc. -# -# This gensymlist.sh is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect fs names. - -module=$1 - -# Ignore kernel.mod. -if test $module = kernel; then - exit -fi - -# For now, this emits only a module name, if the module registers a filesystem. -if grep -v "^#" | grep '^ *grub_fs_register' >/dev/null 2>&1; then - echo $module -fi diff --git a/genhandlerlist.sh b/genhandlerlist.sh deleted file mode 100644 index e4cb0d9de..000000000 --- a/genhandlerlist.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2009 Free Software Foundation, Inc. -# -# This script is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect command names. - -module=$1 - -grep -v "^#" | sed -n \ - -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}" diff --git a/geninit.sh b/geninit.sh index 43d2d1640..f0810120f 100644 --- a/geninit.sh +++ b/geninit.sh @@ -11,11 +11,6 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. -lst="$1" -shift - -header=`echo "${lst}" | sed -e "s/\.lst$/.h/g"` - cat <. */ -#include <$header> +#include EOF +for mod in "$@"; do + echo "extern void grub_${mod}_init (void);" + echo "extern void grub_${mod}_fini (void);" +done + cat </dev/null; then - echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/ grub_\1_init ();/' - fi -done < ${lst} +for mod in "$@"; do + echo "grub_${mod}_init ();" +done cat </dev/null; then - echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/ grub_\1_fini ();/' - fi -done < ${lst} +for mod in "$@"; do + echo "grub_${mod}_fini ();" +done cat <. - */ - -EOF - -cat </dev/null 2>&1 && u="_" - -$CC @TARGET_CFLAGS@ -DGRUB_SYMBOL_GENERATOR=1 -E -I. -Iinclude -I"$srcdir/include" $* \ - | grep -v '^#' \ - | sed -n \ - -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/'"$u"'\1 kernel/;p;}' \ - -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/'"$u"'\1 kernel/;p;}' \ - | sort -u diff --git a/genmk.rb b/genmk.rb deleted file mode 100644 index 01b969ecf..000000000 --- a/genmk.rb +++ /dev/null @@ -1,475 +0,0 @@ -#! /usr/bin/ruby -w -# -# Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. -# -# This genmk.rb is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -module Enumerable - def collect_with_index - ret = [] - self.each_with_index do |item, index| - ret.push(yield(item, index)) - end - ret - end -end - -class String - def to_var - self.gsub(/[^a-zA-Z0-9_@]/, '_') - end - - def suffix(str) - self.sub(/\.[^\.]*$/, '') + '.' + str - end - - def to_obj - self.sub(/\.[^\.]*$/, '').to_var + '.o' - end -end - -class Image - def initialize(dir, name) - @dir = dir - @name = name - @rule_count = 0 - end - attr_reader :dir, :name - - def rule(sources) - prefix = @name.to_var - @rule_count += 1 - exe = @name.suffix('exec') - objs = sources.collect do |src| - raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src - prefix + '-' + src.to_obj - end - objs_str = objs.join(' ') - deps = objs.collect {|obj| obj.suffix('d')} - deps_str = deps.join(' ') - -" -clean-image-#{@name}.#{@rule_count}: - rm -f #{@name} #{exe} #{objs_str} - -CLEAN_IMAGE_TARGETS += clean-image-#{@name}.#{@rule_count} - -mostlyclean-image-#{@name}.#{@rule_count}: - rm -f #{deps_str} - -MOSTLYCLEAN_IMAGE_TARGETS += mostlyclean-image-#{@name}.#{@rule_count} - -ifneq ($(TARGET_APPLE_CC),1) -#{@name}: #{exe} - $(OBJCOPY) -O $(#{prefix}_FORMAT) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@ -else -ifneq (#{exe},kernel.exec) -#{@name}: #{exe} ./grub-macho2img - ./grub-macho2img $< $@ -else -#{@name}: #{exe} ./grub-macho2img - ./grub-macho2img --bss $< $@ -endif -endif - -#{exe}: #{objs_str} - $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS) - -" + objs.collect_with_index do |obj, i| - src = sources[i] - fake_obj = File.basename(src).suffix('o') - dep = deps[i] - flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end - extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end - dir = File.dirname(src) - - "#{obj}: #{src} $(#{src}_DEPENDENCIES) - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $< --include #{dep} - -" - end.join('') - end -end - -# Use PModule instead Module, to avoid name conflicting. -class PModule - def initialize(dir, name) - @dir = dir - @name = name - @rule_count = 0 - end - attr_reader :dir, :name - - def rule(sources) - prefix = @name.to_var - @rule_count += 1 - objs = sources.collect do |src| - raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src - prefix + '-' + src.to_obj - end - objs_str = objs.join(' ') - deps = objs.collect {|obj| obj.suffix('d')} - deps_str = deps.join(' ') - pre_obj = 'pre-' + @name.suffix('o') - mod_src = 'mod-' + @name.suffix('c') - mod_obj = mod_src.suffix('o') - defsym = 'def-' + @name.suffix('lst') - undsym = 'und-' + @name.suffix('lst') - mod_name = File.basename(@name, '.mod') - symbolic_name = mod_name.sub(/\.[^\.]*$/, '') - -" -clean-module-#{@name}.#{@rule_count}: - rm -f #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{undsym} - -CLEAN_MODULE_TARGETS += clean-module-#{@name}.#{@rule_count} - -clean-module-#{@name}-symbol.#{@rule_count}: - rm -f #{defsym} - -CLEAN_MODULE_TARGETS += clean-module-#{@name}-symbol.#{@rule_count} -DEFSYMFILES += #{defsym} -mostlyclean-module-#{@name}.#{@rule_count}: - rm -f #{deps_str} - -MOSTLYCLEAN_MODULE_TARGETS += mostlyclean-module-#{@name}.#{@rule_count} -UNDSYMFILES += #{undsym} - -ifeq ($(TARGET_NO_MODULES), yes) -#{@name}: #{pre_obj} $(TARGET_OBJ2ELF) - -rm -f $@ - $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{pre_obj} - if test ! -z \"$(TARGET_OBJ2ELF)\"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi - if test x$(TARGET_NO_STRIP) != xyes ; then $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@; fi -else -ifneq ($(TARGET_APPLE_CC),1) -#{@name}: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF) - -rm -f $@ - $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{pre_obj} #{mod_obj} - if test ! -z \"$(TARGET_OBJ2ELF)\"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi - if test x$(TARGET_NO_STRIP) != xyes ; then $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@; fi -else -#{@name}: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF) - -rm -f $@ - -rm -f $@.bin - $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin #{pre_obj} #{mod_obj} - $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -ew2030 -ew2050 -nu -nd $@.bin $@ - -rm -f $@.bin -endif -endif - -#{pre_obj}: $(#{prefix}_DEPENDENCIES) #{objs_str} - -rm -f $@ - $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{objs_str} - -#{mod_obj}: #{mod_src} - $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -DGRUB_FILE=\\\"#{mod_src}\\\" -c -o $@ $< - -#{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh - sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1) - -ifneq ($(TARGET_APPLE_CC),1) -#{defsym}: #{pre_obj} - $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@ -else -#{defsym}: #{pre_obj} - $(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]' | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@ -endif - -#{undsym}: #{pre_obj} - echo '#{mod_name}' > $@ - $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ - -" + objs.collect_with_index do |obj, i| - src = sources[i] - fake_obj = File.basename(src).suffix('o') - extra_target = obj.sub(/\.[^\.]*$/, '') + '-extra' - command = 'cmd-' + obj.suffix('lst') - fs = 'fs-' + obj.suffix('lst') - partmap = 'partmap-' + obj.suffix('lst') - handler = 'handler-' + obj.suffix('lst') - terminal = 'terminal-' + obj.suffix('lst') - parttool = 'parttool-' + obj.suffix('lst') - video = 'video-' + obj.suffix('lst') - dep = deps[i] - flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end - extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end - dir = File.dirname(src) - - "#{obj}: #{src} $(#{src}_DEPENDENCIES) - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $< --include #{dep} - -clean-module-#{extra_target}.#{@rule_count}: - rm -f #{command} #{fs} #{partmap} #{handler} #{parttool} #{video} #{terminal} - -CLEAN_MODULE_TARGETS += clean-module-#{extra_target}.#{@rule_count} - -COMMANDFILES += #{command} -FSFILES += #{fs} -PARTTOOLFILES += #{parttool} -PARTMAPFILES += #{partmap} -HANDLERFILES += #{handler} -TERMINALFILES += #{terminal} -VIDEOFILES += #{video} - -#{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/gencmdlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -#{fs}: #{src} $(#{src}_DEPENDENCIES) genfslist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} -DGRUB_LST_GENERATOR $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/genfslist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -#{parttool}: #{src} $(#{src}_DEPENDENCIES) genparttoollist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/genparttoollist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -#{partmap}: #{src} $(#{src}_DEPENDENCIES) genpartmaplist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} -DGRUB_LST_GENERATOR $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/genpartmaplist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -#{handler}: #{src} $(#{src}_DEPENDENCIES) genhandlerlist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -#{terminal}: #{src} $(#{src}_DEPENDENCIES) genterminallist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/genterminallist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -#{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh - set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} -DGRUB_LST_GENERATOR $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ - | sh $(srcdir)/genvideolist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) - -" - end.join('') - end -end - -class Utility - def initialize(dir, name) - @dir = dir - @name = name - @rule_count = 0 - end - def print_tail() - prefix = @name.to_var - print "#{@name}: $(#{prefix}_DEPENDENCIES) $(#{prefix}_OBJECTS) - $(CC) -o $@ $(#{prefix}_OBJECTS) $(LDFLAGS) $(#{prefix}_LDFLAGS) - -" - end - attr_reader :dir, :name - - def rule(sources) - prefix = @name.to_var - @rule_count += 1 - objs = sources.collect do |src| - raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src - prefix + '-' + src.to_obj - end - objs_str = objs.join(' '); - deps = objs.collect {|obj| obj.suffix('d')} - deps_str = deps.join(' '); - - " -clean-utility-#{@name}.#{@rule_count}: - rm -f #{@name}$(EXEEXT) #{objs_str} - -CLEAN_UTILITY_TARGETS += clean-utility-#{@name}.#{@rule_count} - -mostlyclean-utility-#{@name}.#{@rule_count}: - rm -f #{deps_str} - -MOSTLYCLEAN_UTILITY_TARGETS += mostlyclean-utility-#{@name}.#{@rule_count} - -#{prefix}_OBJECTS += #{objs_str} - -" + objs.collect_with_index do |obj, i| - src = sources[i] - fake_obj = File.basename(src).suffix('o') - dep = deps[i] - dir = File.dirname(src) - - "#{obj}: #{src} $(#{src}_DEPENDENCIES) - $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(#{prefix}_CFLAGS) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $< --include #{dep} - -" - end.join('') - end -end - -class Program - def initialize(dir, name) - @dir = dir - @name = name - end - attr_reader :dir, :name - - def print_tail() - prefix = @name.to_var - print "CLEANFILES += #{@name} $(#{prefix}_OBJECTS) -ifeq ($(#{prefix}_RELOCATABLE),yes) -#{@name}: $(#{prefix}_DEPENDENCIES) $(#{prefix}_OBJECTS) - $(TARGET_CC) -Wl,-r,-d -o $@ $(#{prefix}_OBJECTS) $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS) - if test x$(TARGET_NO_STRIP) != xyes ; then $(STRIP) --strip-unneeded -K start -R .note -R .comment $@; fi -else -#{@name}: $(#{prefix}_DEPENDENCIES) $(#{prefix}_OBJECTS) - $(TARGET_CC) -o $@ $(#{prefix}_OBJECTS) $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS) - if test x$(TARGET_NO_STRIP) != xyes ; then $(STRIP) -R .rel.dyn -R .reginfo -R .note -R .comment $@; fi -endif - -" - end - - def rule(sources) - prefix = @name.to_var - objs = sources.collect do |src| - raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src - prefix + '-' + src.to_obj - end - deps = objs.collect {|obj| obj.suffix('d')} - deps_str = deps.join(' '); - - "MOSTLYCLEANFILES += #{deps_str} - -" + objs.collect_with_index do |obj, i| - src = sources[i] - fake_obj = File.basename(src).suffix('o') - dep = deps[i] - flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end - extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end - dir = File.dirname(src) - - "#{obj}: #{src} $(#{src}_DEPENDENCIES) - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $< - --include #{dep} - -#{prefix}_OBJECTS += #{obj} -" - end.join('') - end -end - -class Script - def initialize(dir, name) - @dir = dir - @name = name - end - attr_reader :dir, :name - - def rule(sources) - if sources.length != 1 - raise "only a single source file must be specified for a script" - end - src = sources[0] - if /\.in$/ !~ src - raise "unknown source file `#{src}'" - end - - "CLEANFILES += #{@name} - -#{@name}: #{src} $(#{src}_DEPENDENCIES) config.status - ./config.status --file=-:#{src} | sed -e 's,@pkglib_DATA@,$(pkglib_DATA),g' > $@ - chmod +x $@ - -" - end -end - -images = [] -utils = [] -pmodules = [] -programs = [] -scripts = [] - -l = gets -print l -print "# Generated by genmk.rb, please don't edit!\n" - -cont = false -str = nil -while l = gets - if cont - str += l - else - str = l - end - - print l - cont = (/\\$/ =~ l) - unless cont - str.gsub!(/\\\n/, ' ') - - if /^([a-zA-Z0-9_]+)\s*\+?=\s*(.*?)\s*$/ =~ str - var, args = $1, $2 - - if var =~ /^([a-zA-Z0-9_]+)_([A-Z]+)$/ - prefix, type = $1, $2 - - case type - when 'IMAGES' - images += args.split(/\s+/).collect do |img| - Image.new(prefix, img) - end - - when 'MODULES' - pmodules += args.split(/\s+/).collect do |pmod| - PModule.new(prefix, pmod) - end - - when 'UTILITIES' - utils += args.split(/\s+/).collect do |util| - Utility.new(prefix, util) - end - - when 'PROGRAMS' - programs += args.split(/\s+/).collect do |prog| - Program.new(prefix, prog) - end - - when 'SCRIPTS' - scripts += args.split(/\s+/).collect do |script| - Script.new(prefix, script) - end - - when 'SOURCES' - if img = images.detect() {|i| i.name.to_var == prefix} - print img.rule(args.split(/\s+/)) - elsif pmod = pmodules.detect() {|m| m.name.to_var == prefix} - print pmod.rule(args.split(/\s+/)) - elsif util = utils.detect() {|u| u.name.to_var == prefix} - print util.rule(args.split(/\s+/)) - elsif program = programs.detect() {|u| u.name.to_var == prefix} - print program.rule(args.split(/\s+/)) - elsif script = scripts.detect() {|s| s.name.to_var == prefix} - print script.rule(args.split(/\s+/)) - end - end - end - - end - - end - -end -utils.each {|util| util.print_tail()} -programs.each {|program| program.print_tail()} - diff --git a/genmodsrc.sh b/genmodsrc.sh deleted file mode 100644 index 2d420550a..000000000 --- a/genmodsrc.sh +++ /dev/null @@ -1,47 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2002,2007 Free Software Foundation, Inc. -# -# This genmodsrc.sh is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -set -e - -mod_name="$1" -deps="$2" - -cat <. - */ - -#include - -EOF - -echo "GRUB_MOD_NAME(${mod_name});" - -for mod in `grep "^${mod_name}:" ${deps} | sed 's/^[^:]*://'`; do - echo "GRUB_MOD_DEP(${mod});" -done diff --git a/genpartmaplist.sh b/genpartmaplist.sh deleted file mode 100644 index fceb0f869..000000000 --- a/genpartmaplist.sh +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2005, 2008 Free Software Foundation, Inc. -# -# This script is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect partmap names. - -module=$1 - -# Ignore kernel.mod. -if test $module = kernel; then - exit -fi - -# For now, this emits only a module name, if the module registers a partition map. -if grep -v "^#" | grep '^ *grub_partition_map_register' >/dev/null 2>&1; then - echo $module -fi diff --git a/genparttoollist.sh b/genparttoollist.sh deleted file mode 100644 index 48a0efe55..000000000 --- a/genparttoollist.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2009 Free Software Foundation, Inc. -# -# This gensymlist.sh is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect parttool names. - -module=$1 - -grep -v "^#" | sed -n \ - -e "/grub_parttool_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $module/;p;}" diff --git a/genterminallist.sh b/genterminallist.sh deleted file mode 100644 index 60f5b9105..000000000 --- a/genterminallist.sh +++ /dev/null @@ -1,20 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2009,2010 Free Software Foundation, Inc. -# -# This script is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect command names. - -module=$1 - -grep -v "^#" | sed -n \ - -e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $module/;p;}" \ - -e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $module/;p;}" \ diff --git a/gentpl.py b/gentpl.py new file mode 100644 index 000000000..a42a60667 --- /dev/null +++ b/gentpl.py @@ -0,0 +1,506 @@ +#! /usr/bin/python + +# +# 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", + "mips_yeeloong", "sparc64_ieee1275", + "powerpc_ieee1275" ] + +GROUPS = {} + +GROUPS["common"] = GRUB_PLATFORMS[:] + +# Groups based on CPU +GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ] +GROUPS["x86_64"] = [ "x86_64_efi" ] +GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] +GROUPS["mips"] = [ "mips_yeeloong" ] +GROUPS["sparc64"] = [ "sparc64_ieee1275" ] +GROUPS["powerpc"] = [ "powerpc_ieee1275" ] + +# Groups based on firmware +GROUPS["x86_efi"] = [ "i386_efi", "x86_64_efi" ] +GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] + +# emu is a special case so many core functionality isn't needed on this platform +GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") + +# Groups based on hardware features +GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"] +GROUPS["usb"] = GROUPS["pci"] + +# If gfxterm is main output console integrate it into kernel +GROUPS["videoinkernel"] = ["mips_yeeloong"] +GROUPS["videomodules"] = GRUB_PLATFORMS[:]; +for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) + +# Similar for terminfo +GROUPS["terminfoinkernel"] = ["mips_yeeloong"] + GROUPS["ieee1275"]; +GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; +for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) + +# Miscelaneous groups schedulded to disappear in future +GROUPS["nosparc64"] = GRUB_PLATFORMS[:]; GROUPS["nosparc64"].remove("sparc64_ieee1275") +GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] +GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") + +# +# Create platform => groups reverse map, where groups covering that +# platform are ordered by their sizes +# +RMAP = {} +for platform in GRUB_PLATFORMS: + # initialize with platform itself as a group + RMAP[platform] = [ platform ] + + for k in GROUPS.keys(): + v = GROUPS[k] + # skip groups that don't cover this platform + if platform not in v: continue + + bigger = [] + smaller = [] + # partition currently known groups based on their size + for group in RMAP[platform]: + if group in GRUB_PLATFORMS: smaller.append(group) + elif len(GROUPS[group]) < len(v): smaller.append(group) + else: bigger.append(group) + # insert in the middle + RMAP[platform] = smaller + [ k ] + bigger + +# +# Global variables +# +GVARS = set() + +def gvar_add(var, value): + GVARS.add(var) + return var + " += " + value + "\n" + +def global_variable_initializers(): + r = "" + for var in sorted(GVARS): + r += var + " ?= \n" + return r + +# +# Per PROGRAM/SCRIPT variables +# + +def vars_init(*var_list): + r = "[+ IF (if (not (assoc-ref seen-vars (get \".name\"))) \"seen\") +]" + r += "[+ (out-suspend \"v\") +]" + for var in var_list: + r += var + " = \n" + r += "[+ (out-resume \"v\") +]" + r += "[+ (set! seen-vars (assoc-set! seen-vars (get \".name\") 0)) +]" + r += "[+ ENDIF +]" + return first_time(r) + +def var_set(var, value): + return var + " = " + value + "\n" + +def var_add(var, value): + return var + " += " + value + "\n" + +# +# Autogen constructs +# + +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": + return "\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n" + else: + return "\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n" + +# +# Template for keys with platform names as values, for example: +# +# kernel = { +# nostrip = emu; +# ... +# } +# +def if_platform_tagged(platform, tag, snippet_if, snippet_else=None): + r = "" + r += "[+ IF " + tag + " defined +]" + r += "[+ FOR " + tag + " +][+ CASE " + tag + " +]" + for group in RMAP[platform]: + r += "[+ = \"" + group + "\" +]" + snippet_if + + 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 + +# +# Template for tagged values +# +# module = { +# extra_dist = ... +# extra_dist = ... +# ... +# }; +# +def foreach_value(tag, closure): + return "[+ FOR " + tag + " +]" + closure("[+ ." + tag + " +]") + "[+ ENDFOR +]" + +# +# Template for handling best matched values for a platform, for example: +# +# module = { +# cflags = '-Wall'; +# emu_cflags = '-Wall -DGRUB_EMU=1'; +# ... +# } +# +def foreach_platform_specific_value(platform, suffix, nonetag, closure): + r = "" + for group in RMAP[platform]: + gtag = group + suffix + + if group == RMAP[platform][0]: + r += "[+ IF " + gtag + " +]" + else: + r += "[+ ELIF " + gtag + " +]" + + r += "[+ FOR " + gtag + " +]" + closure("[+ ." + gtag + " +]") + "[+ ENDFOR +]" + r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]" + return r + +# +# Template for handling values from sum of all groups for a platform, +# for example: +# +# module = { +# common = kern/misc.c; +# emu = kern/emu/misc.c; +# ... +# } +# +def foreach_platform_value (platform, suffix, closure): + r = "" + for group in RMAP[platform]: + gtag = group + suffix + + r += "[+ IF " + gtag + " +]" + r += "[+ FOR " + gtag + " +]" + closure("[+ ." + gtag + " +]") + "[+ ENDFOR +]" + r += "[+ ENDIF +]" + return r + +# +# Template for gaurding with platform specific "enable" keys, for example: +# +# module = { +# name = pci; +# noemu = bus/pci.c; +# emu = bus/emu/pci.c; +# emu = commands/lspci.c; +# +# enable = emu; +# enable = i386_pc; +# enable = x86_efi; +# enable = i386_ieee1275; +# enable = i386_coreboot; +# }; +# +def foreach_enabled_platform(closure): + r = "[+ IF - enable undefined +]" + for platform in GRUB_PLATFORMS: + r += "\nif COND_" + platform + "\n" + closure(platform) + "endif\n" + r += "[+ ELSE +]" + for platform in GRUB_PLATFORMS: + x = "\nif COND_" + platform + "\n" + closure(platform) + "endif\n" + r += if_platform_tagged(platform, "enable", x) + r += "[+ ENDIF +]" + return r + +# +# Template for gaurding with platform specific automake conditionals, +# for example: +# +# module = { +# name = usb; +# common = bus/usb/usb.c; +# noemu = bus/usb/usbtrans.c; +# noemu = bus/usb/usbhub.c; +# enable = emu; +# enable = i386; +# enable = mips_yeeloong; +# emu_condition = COND_GRUB_EMU_USB; +# }; +# +def under_platform_specific_conditionals(platform, snippet): + r = foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n") + r += snippet + r += foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n") + return r + +def platform_specific_values(platform, suffix, nonetag): + return foreach_platform_specific_value(platform, suffix, nonetag, + lambda value: value + " ") + +def platform_values(platform, suffix): + return foreach_platform_value(platform, suffix, lambda value: value + " ") + +def extra_dist(): + return foreach_value("extra_dist", lambda value: value + " ") + +def platform_sources(p): return platform_values(p, "") +def platform_nodist_sources(p): return platform_values(p, "_nodist") +def platform_dependencies(p): return platform_values(p, "dependencies", "_dependencies") + +def platform_startup(p): return platform_specific_values(p, "_startup", "startup") +def platform_ldadd(p): return platform_specific_values(p, "_ldadd", "ldadd") +def platform_cflags(p): return platform_specific_values(p, "_cflags", "cflags") +def platform_ldflags(p): return platform_specific_values(p, "_ldflags", "ldflags") +def platform_cppflags(p): return platform_specific_values(p, "_cppflags", "cppflags") +def platform_ccasflags(p): return platform_specific_values(p, "_ccasflags", "ccasflags") +def platform_stripflags(p): return platform_specific_values(p, "_stripflags", "stripflags") +def platform_objcopyflags(p): return platform_specific_values(p, "_objcopyflags", "objcopyflags") + +# +# Emit snippet only the first time through for the current name. +# +def first_time(snippet): + r = "[+ IF (if (not (assoc-ref seen-target (get \".name\"))) \"seen\") +]" + r += snippet + r += "[+ ENDIF +]" + return r + +def module(platform): + r = set_canonical_name_suffix(".module") + + r += gvar_add("noinst_PROGRAMS", "[+ name +].module") + r += gvar_add("MODULE_FILES", "[+ name +].module$(EXEEXT)") + + 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)) + + r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + + 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(platform): + r = set_canonical_name_suffix(".exec") + r += gvar_add("noinst_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)) + + r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + + 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", "cp $< $@", + "$(STRIP) $(" + cname() + "_STRIPFLAGS) -o $@ $<")) + return r + +def image(platform): + r = set_canonical_name_suffix(".image") + r += gvar_add("noinst_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)) + + r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") + r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + + r += gvar_add("platform_DATA", "[+ name +].img") + r += gvar_add("CLEANFILES", "[+ name +].img") + r += rule("[+ name +].img", "[+ name +].image$(EXEEXT)", """ +if test x$(USE_APPLE_CC_FIXES) = xyes; then \ + $(MACHO2IMG) $< $@; \ +else \ + $(OBJCOPY) $(""" + cname() + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@; \ +fi +""") + return r + +def library(platform): + r = set_canonical_name_suffix("") + + r += vars_init(cname() + "_SOURCES", + "nodist_" + cname() + "_SOURCES", + cname() + "_CFLAGS", + cname() + "_CPPFLAGS", + cname() + "_CCASFLAGS") + # cname() + "_DEPENDENCIES") + + r += first_time(gvar_add("noinst_LIBRARIES", "[+ name +]")) + r += var_add(cname() + "_SOURCES", platform_sources(platform)) + r += var_add("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform)) + r += var_add(cname() + "_CFLAGS", first_time("$(AM_CFLAGS) $(CFLAGS_LIBRARY) ") + platform_cflags(platform)) + r += var_add(cname() + "_CPPFLAGS", first_time("$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) ") + platform_cppflags(platform)) + r += var_add(cname() + "_CCASFLAGS", first_time("$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) ") + platform_ccasflags(platform)) + # r += var_add(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform)) + + 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(default="bin"): + return "[+ IF installdir +][+ installdir +][+ ELSE +]" + default + "[+ ENDIF +]" + +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 $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +] +""") + r += gvar_add("CLEANFILES", "[+ name +].[+ mansection +]") + r += "endif\n" + return r + +def program(platform, test=False): + r = set_canonical_name_suffix("") + + r += "[+ IF testcase defined +]" + r += gvar_add("check_PROGRAMS", "[+ name +]") + r += gvar_add("TESTS", "[+ name +]") + r += "[+ ELSE +]" + r += var_add(installdir() + "_PROGRAMS", "[+ name +]") + r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" + r += "[+ ENDIF +]" + + 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)) + + 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(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 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 +]" + + r += rule("[+ name +]", platform_sources(platform) + " $(top_builddir)/config.status", """ +$(top_builddir)/config.status --file=-:$< | sed -e 's,@pkglib_DATA@,$(pkglib_DATA),g' > $@ +chmod a+x [+ name +] +""") + + r += gvar_add("CLEANFILES", "[+ name +]") + r += gvar_add("dist_noinst_DATA", platform_sources(platform)) + return r + +def rules(target, closure): + # Create association lists for the benefit of first_time and vars_init. + r = "[+ (define seen-target '()) +]" + r += "[+ (define seen-vars '()) +]" + # Most output goes to a diversion. This allows us to emit variable + # initializations before everything else. + r += "[+ (out-push-new) +]" + + 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 + +def module_rules(): + return rules("module", module) + +def kernel_rules(): + return rules("kernel", kernel) + +def image_rules(): + return rules("image", image) + +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) + +print "[+ AutoGen5 template +]\n" +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 z # initializer for all vars +print a +print b +print c +print d +print e +print f +print g diff --git a/genvideolist.sh b/genvideolist.sh deleted file mode 100644 index b208fa25c..000000000 --- a/genvideolist.sh +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 2005,2008,2009 Free Software Foundation, Inc. -# -# This script is free software; the author -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. -# -# This program 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. - -# Read source code from stdin and detect partmap names. - -module=$1 - -# Ignore video.mod. -if test $module = video; then - exit -fi - -# For now, this emits only a module name, if the module registers a partition map. -if grep -v "^#" | grep '^ *grub_video_register' >/dev/null 2>&1; then - echo $module -fi diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am new file mode 100644 index 000000000..9792dd974 --- /dev/null +++ b/grub-core/Makefile.am @@ -0,0 +1,351 @@ +AUTOMAKE_OPTIONS = subdir-objects + +DEPDIR=.deps-core + +include $(top_srcdir)/conf/Makefile.common + +CC=$(TARGET_CC) +CPP=$(TARGET_CC) +CCAS=$(TARGET_CC) + +if COND_GRUB_MKFONT +if COND_HAVE_FONT_SOURCE +TARGET_CFLAGS += -DUSE_ASCII_FAILBACK=1 -DHAVE_UNIFONT_WIDTHSPEC=1 +endif +endif + +AM_CFLAGS = $(TARGET_CFLAGS) +AM_LDFLAGS = $(TARGET_LDFLAGS) +AM_CPPFLAGS = $(TARGET_CPPFLAGS) $(CPPFLAGS_DEFAULT) +AM_CCASFLAGS = $(TARGET_CCASFLAGS) $(CCASFLAGS_DEFAULT) + +CFLAGS_PROGRAM += $(CFLAGS_PLATFORM) +LDFLAGS_PROGRAM += $(LDFLAGS_PLATFORM) +CPPFLAGS_PROGRAM += $(CPPFLAGS_PLATFORM) +CCASFLAGS_PROGRAM += $(CCASFLAGS_PLATFORM) + +CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin +CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM) +CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM) + +# gentrigtables +gentrigtables: gentrigtables.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) -lm $< +CLEANFILES += gentrigtables + +# trigtables.c +trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac + $(builddir)/gentrigtables > $@ +CLEANFILES += trigtables.c + +# XXX Use Automake's LEX & YACC support +grub_script.tab.h: script/parser.y + $(YACC) -d -p grub_script_yy -b grub_script $< +grub_script.tab.c: grub_script.tab.h +CLEANFILES += grub_script.tab.c grub_script.tab.h + +# For the lexer. +grub_script.yy.h: script/yylex.l + $(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $< +grub_script.yy.c: grub_script.yy.h + +rs_decoder.S: $(srcdir)/lib/reed_solomon.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 + +kern/i386/pc/startup.S: $(builddir)/rs_decoder.S + +CLEANFILES += grub_script.yy.c grub_script.yy.h + +include $(srcdir)/Makefile.core.am + +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/file.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/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/boot.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/loader.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +endif + +if COND_i386_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +endif + +if COND_i386_coreboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +endif + +if COND_i386_multiboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +endif + +if COND_i386_qemu +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +endif + +if COND_i386_ieee1275 +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/pit.h +endif + +if COND_x86_64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +endif + +if COND_mips_yeeloong +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/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.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 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + +if COND_powerpc_ieee1275 +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 +endif + +if COND_sparc64_ieee1275 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/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 +endif + +if COND_emu +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.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 +endif + +symlist.h: $(top_builddir)/config.h $(KERNEL_HEADER_FILES) + @list='$^'; \ + for p in $$list; do \ + echo "#include <$$p>" >> $@ || (rm -f $@; exit 1); \ + done +CLEANFILES += symlist.h +BUILT_SOURCES += symlist.h + +symlist.c: symlist.h gensymlist.sh + $(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1) + cat symlist.p | /bin/sh $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1) + rm -f symlist.p +CLEANFILES += symlist.c +BUILT_SOURCES += symlist.c + +if COND_HAVE_ASM_USCORE +ASM_PREFIX=_ +else +ASM_PREFIX= +endif + +noinst_DATA += kernel_syms.lst + +kernel_syms.lst: $(KERNEL_HEADER_FILES) $(top_builddir)/config.h + $(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) $(CFLAGS) -DGRUB_SYMBOL_GENERATOR=1 $^ >kernel_syms.input + cat kernel_syms.input | grep -v '^#' | sed -n \ + -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \ + -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \ + | sort -u >$@ + rm -f kernel_syms.input +CLEANFILES += kernel_syms.lst + +if COND_emu +kern/emu/grub_emu-main.$(OBJEXT):grub_emu_init.h +grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h +kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h +grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h + +grub_emu_init.h: genemuinitheader.sh $(MOD_FILES) + rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(NM) > $@ +CLEANFILES += grub_emu_init.h + +grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES) + rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(NM) > $@ +CLEANFILES += grub_emu_init.c +endif + +# List files + +fs.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + if grep 'FS_LIST_MARKER' $$pp >/dev/null 2>&1; then \ + echo $$b; \ + fi; \ + done) | sort -u > $@ +platform_DATA += fs.lst +CLEANFILES += fs.lst + +command.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \ + -e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \ + -e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += command.lst +CLEANFILES += command.lst + +partmap.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + if grep 'PARTMAP_LIST_MARKER' $$pp >/dev/null 2>&1; then \ + echo $$b; \ + fi; \ + done) | sort -u > $@ +platform_DATA += partmap.lst +CLEANFILES += partmap.lst + +terminal.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/INPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \ + -e "/OUTPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += terminal.lst +CLEANFILES += terminal.lst + +parttool.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/PARTTOOL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += parttool.lst +CLEANFILES += parttool.lst + +video.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + if grep 'VIDEO_LIST_MARKER' $$pp >/dev/null 2>&1; then \ + echo $$b; \ + fi; \ + done) | sort -u > $@ +platform_DATA += video.lst +CLEANFILES += video.lst + +# but, crypto.lst is simply copied +crypto.lst: $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst + cp $^ $@ +platform_DATA += crypto.lst +CLEANFILES += crypto.lst + +syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES) + cat kernel_syms.lst > $@.new + for m in $(MODULE_FILES); do \ + sh $< $$m >> $@.new || exit 1; \ + done + mv $@.new $@ + +# generate global module dependencies list +moddep.lst: syminfo.lst genmoddep.awk + 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) + sh $^ $@ +platform_DATA += $(MOD_FILES) +CLEANFILES += $(MOD_FILES) + +if COND_ENABLE_EFIEMU +efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) + -rm -f $@; \ + if test "x$(TARGET_APPLE_CC)" = x1; then \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF32 -DAPPLE_CC -m32 -Wall -Werror -nostdlib -O2 -c -o $@.bin $< || exit 1; \ + $(OBJCONV) -felf32 -nu -nd $@.bin $@ || exit 1; \ + rm -f $@.bin; \ + else \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF32 -m32 -Wall -Werror -nostdlib -O2 -c -o $@ $< || exit 1; \ + if test ! -z "$(TARGET_OBJ2ELF)"; then $(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi; \ + 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 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def new file mode 100644 index 000000000..46c65adac --- /dev/null +++ b/grub-core/Makefile.core.def @@ -0,0 +1,1502 @@ +AutoGen definitions Makefile.tpl; + +script = { + installdir = noinst; + name = gensyminfo.sh; + common = gensyminfo.sh.in; +}; + +script = { + installdir = noinst; + name = genmod.sh; + common = genmod.sh.in; +}; + +kernel = { + name = kernel; + + nostrip = emu; + + emu_ldflags = '-Wl,-r,-d'; + x86_efi_ldflags = '-Wl,-r,-d'; + x86_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; + + 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_yeeloong_ldflags = '-Wl,-Ttext,0x80200000'; + powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + + mips_yeeloong_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)'; + + 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_qemu_startup = kern/i386/qemu/startup.S; + i386_ieee1275_startup = kern/i386/ieee1275/startup.S; + i386_coreboot_startup = kern/i386/coreboot/startup.S; + i386_multiboot_startup = kern/i386/coreboot/startup.S; + mips_yeeloong_startup = kern/mips/startup.S; + sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; + powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; + + common = kern/command.c; + common = kern/corecmd.c; + common = kern/device.c; + common = kern/disk.c; + common = kern/dl.c; + common = kern/env.c; + common = kern/err.c; + common = kern/file.c; + common = kern/fs.c; + common = kern/list.c; + common = kern/main.c; + common = kern/misc.c; + common = kern/parser.c; + common = kern/partition.c; + common = kern/rescue_parser.c; + common = kern/rescue_reader.c; + common = kern/term.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; + x86_efi = kern/generic/rtc_get_time_ms.c; + i386_qemu = kern/generic/rtc_get_time_ms.c; + i386_coreboot = kern/generic/rtc_get_time_ms.c; + i386_multiboot = kern/generic/rtc_get_time_ms.c; + mips_yeeloong = kern/generic/rtc_get_time_ms.c; + + ieee1275 = disk/ieee1275/ofdisk.c; + ieee1275 = kern/ieee1275/cmain.c; + ieee1275 = kern/ieee1275/ieee1275.c; + ieee1275 = kern/ieee1275/mmap.c; + ieee1275 = kern/ieee1275/openfw.c; + ieee1275 = term/ieee1275/ofconsole.c; + + terminfoinkernel = term/terminfo.c; + terminfoinkernel = term/tparm.c; + terminfoinkernel = commands/extcmd.c; + terminfoinkernel = lib/arg.c; + + i386 = kern/i386/dl.c; + + i386_coreboot_multiboot_qemu = kern/i386/coreboot/init.c; + i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; + + i386_coreboot_multiboot_qemu = term/i386/vga_common.c; + i386_pc = term/i386/vga_common.c; + + x86 = kern/i386/pit.c; + + x86_efi = disk/efi/efidisk.c; + x86_efi = kern/efi/efi.c; + x86_efi = kern/efi/init.c; + x86_efi = kern/efi/mm.c; + x86_efi = kern/i386/efi/init.c; + x86_efi = term/efi/console.c; + + i386_efi = kern/i386/tsc.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; + + 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/i386/qemu/init.c; + i386_qemu = kern/i386/qemu/mmap.c; + i386_qemu = kern/i386/tsc.c; + + i386_coreboot = kern/i386/coreboot/mmap.c; + i386_coreboot = kern/i386/tsc.c; + + i386_multiboot = kern/i386/multiboot_mmap.c; + i386_multiboot = kern/i386/tsc.c; + + i386_ieee1275 = kern/ieee1275/init.c; + + mips_yeeloong = term/ns8250.c; + mips_yeeloong = bus/bonito.c; + mips_yeeloong = bus/cs5536.c; + mips_yeeloong = bus/pci.c; + mips_yeeloong = kern/mips/cache.S; + mips_yeeloong = kern/mips/dl.c; + mips_yeeloong = kern/mips/init.c; + mips_yeeloong = kern/mips/yeeloong/init.c; + mips_yeeloong = term/at_keyboard.c; + mips_yeeloong = term/serial.c; + mips_yeeloong = video/sm712.c; + extra_dist = video/sm712_init.c; + mips_yeeloong = commands/keylayouts.c; + + powerpc_ieee1275 = kern/ieee1275/init.c; + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; + + sparc64_ieee1275 = kern/sparc64/cache.S; + sparc64_ieee1275 = kern/sparc64/dl.c; + sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; + sparc64_ieee1275 = kern/sparc64/ieee1275/init.c; + + emu = disk/host.c; + emu = gnulib/progname.c; + emu = gnulib/error.c; + emu = kern/emu/console.c; + emu = kern/emu/getroot.c; + emu = kern/emu/hostdisk.c; + emu = kern/emu/hostfs.c; + emu = kern/emu/main.c; + emu = kern/emu/misc.c; + emu = kern/emu/mm.c; + emu = kern/emu/time.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/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/realmode.S; + extra_dist = kern/i386/pc/lzma_decode.S; + extra_dist = kern/mips/cache_flush.S; +}; + +program = { + name = grub-emu; + mansection = 1; + + emu = kern/emu/full.c; + emu_nodist = grub_emu_init.c; + + ldadd = 'kernel.img$(EXEEXT)'; + ldadd = '$(MODULE_FILES)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; + + enable = emu; +}; + +program = { + name = grub-emu-lite; + + emu = kern/emu/lite.c; + emu = kern/emu/cache.S; + emu_nodist = symlist.c; + + ldadd = 'kernel.img$(EXEEXT)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; + + enable = emu; +}; + +image = { + name = boot; + i386_pc = boot/i386/pc/boot.S; + i386_qemu = boot/i386/qemu/boot.S; + sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_BOOT_MACHINE_LINK_ADDR)'; + i386_qemu_ccasflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; + + sparc64_ieee1275_objcopyflags = '-O a.out-sunos-big'; + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x4000'; + + objcopyflags = '-O binary'; + enable = i386_pc; + enable = i386_qemu; + enable = sparc64_ieee1275; +}; + +image = { + name = cdboot; + i386_pc = boot/i386/pc/cdboot.S; + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + objcopyflags = '-O binary'; + enable = i386_pc; +}; + +image = { + name = pxeboot; + i386_pc = boot/i386/pc/pxeboot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + +image = { + name = diskboot; + i386_pc = boot/i386/pc/diskboot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8000'; + + sparc64_ieee1275 = boot/sparc64/ieee1275/diskboot.S; + sparc64_ieee1275_ldflags = '-Wl,-Ttext=0x4200'; + + objcopyflags = '-O binary'; + + enable = i386_pc; + enable = sparc64_ieee1275; +}; + +image = { + name = lnxboot; + i386_pc = boot/i386/pc/lnxboot.S; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x6000'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + +image = { + name = xz_decompress; + mips = boot/mips/startup_raw.S; + common = boot/decompressor/minilib.c; + common = boot/decompressor/xz.c; + common = lib/xzembed/xz_dec_bcj.c; + common = lib/xzembed/xz_dec_lzma2.c; + common = lib/xzembed/xz_dec_stream.c; + + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; + + mips_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; + + objcopyflags = '-O binary'; + ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000'; + cflags = '-static-libgcc'; + enable = mips; +}; + +image = { + name = none_decompress; + mips = boot/mips/startup_raw.S; + common = boot/decompressor/none.c; + + mips_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; + + objcopyflags = '-O binary'; + ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000'; + cflags = '-static-libgcc'; + enable = mips; +}; + +image = { + name = fwstart; + mips_yeeloong = boot/mips/yeeloong/fwstart.S; + objcopyflags = '-O binary'; + enable = mips_yeeloong; +}; + +module = { + name = trig; + common_nodist = trigtables.c; + extra_dist = gentrigtables.c; +}; + +module = { + name = cs5536; + x86 = bus/cs5536.c; + enable = x86; +}; + +module = { + name = libusb; + emu = bus/usb/emu/usb.c; + enable = emu; + condition = COND_GRUB_EMU_USB; +}; + +module = { + name = lsspd; + mips_yeeloong = commands/mips/yeeloong/lsspd.c; + enable = mips_yeeloong; +}; + +module = { + name = usb; + common = bus/usb/usb.c; + noemu = bus/usb/usbtrans.c; + noemu = bus/usb/usbhub.c; + enable = emu; + enable = usb; + emu_condition = COND_GRUB_EMU_USB; +}; + +module = { + name = usbserial_common; + common = bus/usb/serial/common.c; + enable = usb; +}; + +module = { + name = usbserial_pl2303; + common = bus/usb/serial/pl2303.c; + enable = usb; +}; + +module = { + name = usbserial_ftdi; + common = bus/usb/serial/ftdi.c; + enable = usb; +}; + +module = { + name = uhci; + common = bus/usb/uhci.c; + enable = x86; +}; + +module = { + name = ohci; + common = bus/usb/ohci.c; + enable = pci; +}; + +module = { + name = pci; + noemu = bus/pci.c; + emu = bus/emu/pci.c; + emu = commands/lspci.c; + + enable = emu; + enable = i386_pc; + enable = x86_efi; + enable = i386_ieee1275; + enable = i386_coreboot; + enable = i386_multiboot; + emu_condition = COND_GRUB_EMU_PCI; +}; + +library = { + name = libgnulib.a; + common = gnulib/regex.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; +}; + +module = { + name = cmostest; + common = commands/i386/cmostest.c; + enable = cmos; +}; + +module = { + name = iorw; + common = commands/iorw.c; + enable = x86; +}; + +module = { + name = regexp; + common = commands/regexp.c; + common = commands/wildcard.c; + ldadd = libgnulib.a; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; +}; + +module = { + name = acpi; + + common = commands/acpi.c; + x86_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 = x86_efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = lsacpi; + + common = commands/lsacpi.c; + + enable = x86_efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = lsefisystab; + + common = commands/efi/lsefisystab.c; + + enable = x86_efi; +}; + +module = { + name = lssal; + + common = commands/efi/lssal.c; + + enable = x86_efi; +}; + +module = { + name = lsefimmap; + + common = commands/efi/lsefimmap.c; + + enable = x86_efi; +}; + +module = { + name = blocklist; + common = commands/blocklist.c; +}; + +module = { + name = boot; + common = commands/boot.c; + i386_pc = lib/i386/pc/biosnum.c; + enable = videomodules; +}; + +module = { + name = cat; + common = commands/cat.c; +}; + +module = { + name = cmp; + common = commands/cmp.c; +}; + +module = { + name = configfile; + common = commands/configfile.c; +}; + +module = { + name = cpuid; + x86 = commands/i386/cpuid.c; + enable = x86; +}; + +module = { + name = date; + common = commands/date.c; +}; + +module = { + name = drivemap; + + i386_pc = commands/i386/pc/drivemap.c; + i386_pc = commands/i386/pc/drivemap_int13h.S; + enable = i386_pc; +}; + +module = { + name = echo; + common = commands/echo.c; +}; + +module = { + name = extcmd; + common = commands/extcmd.c; + common = lib/arg.c; + enable = terminfomodule; +}; + +module = { + name = fixvideo; + x86_efi = commands/efi/fixvideo.c; + enable = x86_efi; +}; + +module = { + name = gptsync; + common = commands/gptsync.c; +}; + +module = { + name = halt; + nopc = commands/halt.c; + i386_pc = commands/i386/pc/halt.c; + i386_pc = commands/acpihalt.c; + i386_coreboot = commands/acpihalt.c; + i386_multiboot = commands/acpihalt.c; + x86_efi = commands/acpihalt.c; + i386_multiboot = lib/i386/halt.c; + i386_coreboot = lib/i386/halt.c; + i386_qemu = lib/i386/halt.c; + x86_efi = lib/efi/halt.c; + ieee1275 = lib/ieee1275/halt.c; + emu = lib/emu/halt.c; +}; + +module = { + name = hashsum; + common = commands/hashsum.c; +}; + +module = { + name = hdparm; + common = commands/hdparm.c; + common = lib/hexdump.c; + enable = pci; +}; + +module = { + name = help; + common = commands/help.c; +}; + +module = { + name = hexdump; + common = commands/hexdump.c; + common = lib/hexdump.c; +}; + +module = { + name = keystatus; + common = commands/keystatus.c; +}; + +module = { + name = loadbios; + x86_efi = commands/efi/loadbios.c; + enable = x86_efi; +}; + +module = { + name = loadenv; + common = commands/loadenv.c; + common = lib/envblk.c; +}; + +module = { + name = ls; + common = commands/ls.c; +}; + +module = { + name = lsmmap; + common = commands/lsmmap.c; +}; + +module = { + name = lspci; + common = commands/lspci.c; + + enable = pci; +}; + +module = { + name = memrw; + common = commands/memrw.c; +}; + +module = { + name = minicmd; + common = commands/minicmd.c; +}; + +module = { + name = parttool; + common = commands/parttool.c; +}; + +module = { + name = password; + common = commands/password.c; +}; + +module = { + name = password_pbkdf2; + common = commands/password_pbkdf2.c; +}; + +module = { + name = play; + x86 = commands/i386/pc/play.c; + enable = x86; +}; + +module = { + name = probe; + common = commands/probe.c; +}; + +module = { + name = pxecmd; + i386_pc = commands/i386/pc/pxecmd.c; + enable = i386_pc; +}; + +module = { + name = read; + common = commands/read.c; +}; + +module = { + name = reboot; + common = commands/reboot.c; +}; + +module = { + name = search; + common = commands/search_wrap.c; + extra_dist = commands/search.c; +}; + +module = { + name = search_fs_file; + common = commands/search_file.c; +}; + +module = { + name = search_fs_uuid; + common = commands/search_uuid.c; +}; + +module = { + name = search_label; + common = commands/search_label.c; +}; + +module = { + name = setpci; + common = commands/setpci.c; + enable = x86; +}; + +module = { + name = sleep; + common = commands/sleep.c; +}; + +module = { + name = suspend; + ieee1275 = commands/ieee1275/suspend.c; + enable = i386_ieee1275; + enable = powerpc_ieee1275; +}; + +module = { + name = terminal; + common = commands/terminal.c; +}; + +module = { + name = test; + common = commands/test.c; +}; + +module = { + name = true; + common = commands/true.c; +}; + +module = { + name = usbtest; + common = commands/usbtest.c; + enable = usb; + enable = emu; + emu_condition = COND_GRUB_EMU_USB; +}; + +module = { + name = videoinfo; + common = commands/videoinfo.c; +}; + +module = { + name = videotest; + common = commands/videotest.c; +}; + +module = { + name = xnu_uuid; + common = commands/xnu_uuid.c; +}; + +module = { + name = dm_nv; + common = disk/dmraid_nvidia.c; +}; + +module = { + name = loopback; + common = disk/loopback.c; +}; + +module = { + name = lvm; + common = disk/lvm.c; +}; + +module = { + name = mdraid09; + common = disk/mdraid_linux.c; +}; + +module = { + name = mdraid1x; + common = disk/mdraid1x_linux.c; +}; + +module = { + name = raid; + common = disk/raid.c; +}; + +module = { + name = raid5rec; + common = disk/raid5_recover.c; +}; + +module = { + name = raid6rec; + common = disk/raid6_recover.c; +}; + +module = { + name = scsi; + common = disk/scsi.c; +}; + +module = { + name = memdisk; + common = disk/memdisk.c; +}; + +module = { + name = ata; + common = disk/ata.c; + enable = pci; +}; + +module = { + name = ata_pthru; + common = disk/ata_pthru.c; + enable = pci; +}; + +module = { + name = biosdisk; + i386_pc = disk/i386/pc/biosdisk.c; + enable = i386_pc; +}; + +module = { + name = usbms; + common = disk/usbms.c; + enable = usb; + enable = emu; + emu_condition = COND_GRUB_EMU_USB; +}; + +module = { + name = nand; + ieee1275 = disk/ieee1275/nand.c; + enable = i386_ieee1275; +}; + +module = { + name = efiemu; + common = efiemu/main.c; + common = efiemu/i386/loadcore32.c; + common = efiemu/i386/loadcore64.c; + i386_pc = efiemu/i386/pc/cfgtables.c; + i386_coreboot = efiemu/i386/pc/cfgtables.c; + i386_multiboot = efiemu/i386/pc/cfgtables.c; + i386_ieee1275 = efiemu/i386/nocfgtables.c; + i386_qemu = efiemu/i386/nocfgtables.c; + common = efiemu/mm.c; + common = efiemu/loadcore_common.c; + common = efiemu/symbols.c; + common = efiemu/loadcore32.c; + common = efiemu/loadcore64.c; + common = efiemu/prepare32.c; + common = efiemu/prepare64.c; + common = efiemu/pnvram.c; + common = efiemu/i386/coredetect.c; + + extra_dist = efiemu/prepare.c; + extra_dist = efiemu/loadcore.c; + extra_dist = efiemu/runtime/efiemu.S; + extra_dist = efiemu/runtime/efiemu.c; + + enable = i386_pc; + enable = i386_coreboot; + enable = i386_ieee1275; + enable = i386_multiboot; + enable = i386_qemu; +}; + +module = { + name = font; + common = font/font.c; + common = font/font_cmd.c; + enable = videomodules; +}; + +module = { + name = affs; + common = fs/affs.c; +}; + +module = { + name = afs; + common = fs/afs.c; +}; + +module = { + name = afs_be; + common = fs/afs_be.c; +}; + +module = { + name = befs; + common = fs/befs.c; +}; + +module = { + name = befs_be; + common = fs/befs_be.c; +}; + +module = { + name = btrfs; + common = fs/btrfs.c; +}; + +module = { + name = cpio; + common = fs/cpio.c; +}; + +module = { + name = ext2; + common = fs/ext2.c; +}; + +module = { + name = fat; + common = fs/fat.c; +}; + +module = { + name = fshelp; + common = fs/fshelp.c; +}; + +module = { + name = hfs; + common = fs/hfs.c; +}; + +module = { + name = hfsplus; + common = fs/hfsplus.c; +}; + +module = { + name = iso9660; + common = fs/iso9660.c; +}; + +module = { + name = jfs; + common = fs/jfs.c; +}; + +module = { + name = minix; + common = fs/minix.c; +}; + +module = { + name = minix2; + common = fs/minix2.c; +}; + +module = { + name = nilfs2; + common = fs/nilfs2.c; +}; + +module = { + name = ntfs; + common = fs/ntfs.c; +}; + +module = { + name = ntfscomp; + common = fs/ntfscomp.c; +}; + +module = { + name = reiserfs; + common = fs/reiserfs.c; +}; + +module = { + name = sfs; + common = fs/sfs.c; +}; + +module = { + name = tar; + common = fs/tar.c; +}; + +module = { + name = udf; + common = fs/udf.c; +}; + +module = { + name = ufs1; + common = fs/ufs.c; +}; + +module = { + name = ufs2; + common = fs/ufs2.c; +}; + +module = { + name = xfs; + common = fs/xfs.c; +}; + +module = { + name = pxe; + i386_pc = fs/i386/pc/pxe.c; + enable = i386_pc; +}; + +module = { + name = gettext; + common = gettext/gettext.c; +}; + +module = { + name = gfxmenu; + common = gfxmenu/gfxmenu.c; + common = gfxmenu/model.c; + common = gfxmenu/view.c; + common = gfxmenu/font.c; + common = gfxmenu/icon_manager.c; + common = gfxmenu/theme_loader.c; + common = gfxmenu/widget-box.c; + common = gfxmenu/gui_canvas.c; + common = gfxmenu/gui_circular_progress.c; + common = gfxmenu/gui_box.c; + common = gfxmenu/gui_label.c; + common = gfxmenu/gui_list.c; + common = gfxmenu/gui_image.c; + common = gfxmenu/gui_progress_bar.c; + common = gfxmenu/gui_util.c; + common = gfxmenu/gui_string_util.c; + common = gfxmenu/named_colors.c; +}; + +module = { + name = hello; + common = hello/hello.c; +}; + +module = { + name = gzio; + common = io/gzio.c; +}; + +module = { + name = bufio; + common = io/bufio.c; + enable = videomodules; +}; + +module = { + name = elf; + common = kern/elf.c; +}; + +module = { + name = crypto; + common = lib/crypto.c; + + extra_dist = lib/libgcrypt-grub/cipher/crypto.lst; +}; + +module = { + name = pbkdf2; + common = lib/pbkdf2.c; +}; + +module = { + name = relocator; + common = lib/relocator.c; + x86 = lib/i386/relocator16.S; + x86 = lib/i386/relocator32.S; + x86 = lib/i386/relocator64.S; + i386 = lib/i386/relocator_asm.S; + x86_64 = lib/x86_64/relocator_asm.S; + x86 = lib/i386/relocator.c; + ieee1275 = lib/ieee1275/relocator.c; + x86_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; + + extra_dist = lib/i386/relocator_common.S; + extra_dist = kern/powerpc/cache_flush.S; + + enable = mips; + enable = powerpc; + enable = x86; +}; + +module = { + name = datetime; + cmos = lib/cmos_datetime.c; + x86_efi = lib/efi/datetime.c; + sparc64_ieee1275 = lib/ieee1275/datetime.c; + powerpc_ieee1275 = lib/ieee1275/datetime.c; + enable = noemu; +}; + +module = { + name = setjmp; + common = lib/setjmp.S; + extra_dist = lib/i386/setjmp.S; + extra_dist = lib/mips/setjmp.S; + extra_dist = lib/x86_64/setjmp.S; + extra_dist = lib/sparc64/setjmp.S; + extra_dist = lib/powerpc/setjmp.S; +}; + +module = { + name = aout; + common = loader/aout.c; + enable = x86; +}; + +module = { + name = bsd; + x86 = loader/i386/bsd.c; + x86 = loader/i386/bsd32.c; + x86 = loader/i386/bsd64.c; + + extra_dist = loader/i386/bsdXX.c; + extra_dist = loader/i386/bsd_pagetable.c; + + enable = x86; +}; + +module = { + name = linux16; + i386_pc = loader/i386/pc/linux.c; + enable = i386_pc; +}; + +module = { + name = ntldr; + i386_pc = loader/i386/pc/ntldr.c; + enable = i386_pc; +}; + +module = { + name = multiboot2; + cppflags = "-DGRUB_USE_MULTIBOOT2"; + + common = loader/multiboot.c; + common = loader/multiboot_mbi2.c; + enable = x86; + enable = mips; +}; + +module = { + name = multiboot; + common = loader/multiboot.c; + x86 = loader/i386/multiboot_mbi.c; + extra_dist = loader/multiboot_elfxx.c; + enable = x86; +}; + +module = { + name = linux; + x86 = loader/i386/linux.c; + i386_pc = 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; + enable = noemu; +}; + +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; + + extra_dist = loader/machoXX.c; + enable = x86; +}; + +module = { + name = appleldr; + x86_efi = loader/efi/appleloader.c; + enable = x86_efi; +}; + +module = { + name = chain; + x86_efi = loader/efi/chainloader.c; + i386_pc = loader/i386/pc/chainloader.c; + enable = i386_pc; + enable = x86_efi; +}; + +module = { + name = mmap; + common = mmap/mmap.c; + x86 = mmap/i386/uppermem.c; + x86 = mmap/i386/mmap.c; + + i386_pc = mmap/i386/pc/mmap.c; + i386_pc = mmap/i386/pc/mmap_helper.S; + + x86_efi = mmap/efi/mmap.c; + + mips_yeeloong = mmap/mips/yeeloong/uppermem.c; + + enable = x86; + enable = mips_yeeloong; +}; + +module = { + name = normal; + common = normal/main.c; + common = normal/cmdline.c; + common = normal/dyncmd.c; + common = normal/auth.c; + 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; + common = normal/misc.c; + common = normal/crypto.c; + common = normal/term.c; + common = normal/context.c; + common = normal/charset.c; + + common = script/main.c; + common = script/script.c; + common = script/execute.c; + common = script/function.c; + common = script/lexer.c; + common = script/argv.c; + + common = commands/menuentry.c; + + common = unidata.c; + common_nodist = grub_script.tab.c; + common_nodist = grub_script.yy.c; + common_nodist = grub_script.tab.h; + common_nodist = grub_script.yy.h; + + extra_dist = script/yylex.l; + extra_dist = script/parser.y; + + cflags = '$(CFLAGS_POSIX) -Wno-error'; + cppflags = '$(CPPFLAGS_POSIX)'; +}; + +module = { + name = part_acorn; + common = partmap/acorn.c; +}; + +module = { + name = part_amiga; + common = partmap/amiga.c; +}; + +module = { + name = part_apple; + common = partmap/apple.c; +}; + +module = { + name = part_gpt; + common = partmap/gpt.c; +}; + +module = { + name = part_msdos; + common = partmap/msdos.c; +}; + +module = { + name = part_sun; + common = partmap/sun.c; +}; + +module = { + name = part_bsd; + common = partmap/bsdlabel.c; +}; + +module = { + name = part_sunpc; + common = partmap/sunpc.c; +}; + +module = { + name = msdospart; + common = parttool/msdospart.c; +}; + +module = { + name = at_keyboard; + common = term/at_keyboard.c; + enable = x86; +}; + +module = { + name = gfxterm; + common = term/gfxterm.c; + enable = videomodules; +}; + +module = { + name = serial; + common = term/serial.c; + x86 = term/ns8250.c; + + enable = emu; + enable = i386; + enable = x86_64_efi; + emu_condition = COND_GRUB_EMU_USB; +}; + +module = { + name = sendkey; + i386_pc = commands/i386/pc/sendkey.c; + enable = i386_pc; +}; + +module = { + name = terminfo; + common = term/terminfo.c; + common = term/tparm.c; + enable = terminfomodule; +}; + +module = { + name = usb_keyboard; + common = term/usb_keyboard.c; + enable = usb; +}; + +module = { + name = vga; + i386_pc = video/i386/pc/vga.c; + enable = i386_pc; +}; + +module = { + name = vga_text; + common = term/i386/pc/vga_text.c; + common = term/i386/vga_common.c; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = video_cirrus; + x86 = video/cirrus.c; + enable = x86; +}; + +module = { + name = video_bochs; + x86 = video/bochs.c; + enable = x86; +}; + +module = { + name = functional_test; + common = tests/lib/functional_test.c; + common = tests/lib/test.c; +}; + +module = { + name = example_functional_test; + common = tests/example_functional_test.c; + cflags = -Wno-format; +}; + +module = { + name = bitmap; + common = video/bitmap.c; + enable = videomodules; +}; + +module = { + name = bitmap_scale; + common = video/bitmap_scale.c; + enable = videomodules; +}; + +module = { + name = efi_gop; + x86_efi = video/efi_gop.c; + enable = x86_efi; +}; + +module = { + name = efi_uga; + x86_efi = video/efi_uga.c; + enable = x86_efi; +}; + +module = { + name = jpeg; + common = video/readers/jpeg.c; +}; + +module = { + name = png; + common = video/readers/png.c; +}; + +module = { + name = tga; + common = video/readers/tga.c; +}; + +module = { + name = vbe; + i386_pc = video/i386/pc/vbe.c; + enable = i386_pc; +}; + +module = { + name = video_fb; + common = video/fb/video_fb.c; + common = video/fb/fbblit.c; + common = video/fb/fbfill.c; + common = video/fb/fbutil.c; + enable = videomodules; +}; + +module = { + name = video; + common = video/video.c; + enable = videomodules; +}; + +module = { + name = ieee1275_fb; + ieee1275 = video/ieee1275.c; + enable = powerpc; + enable = sparc64; +}; + +module = { + name = sdl; + emu = video/emu/sdl.c; + enable = emu; + condition = COND_GRUB_EMU_SDL; +}; + +module = { + name = datehook; + common = hook/datehook.c; +}; + +module = { + name = legacycfg; + common = commands/legacycfg.c; + common = lib/legacy_parse.c; + emu = lib/i386/pc/vesa_modes_table.c; + enable = i386_pc; + enable = emu; +}; + +module = { + name = test_blockarg; + common = tests/test_blockarg.c; +}; + +module = { + name = xzio; + common = io/xzio.c; + common = lib/xzembed/xz_dec_bcj.c; + common = lib/xzembed/xz_dec_lzma2.c; + common = lib/xzembed/xz_dec_stream.c; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; +}; + +module = { + name = testload; + common = commands/testload.c; +}; + +module = { + name = lsapm; + common = commands/i386/pc/lsapm.c; + enable = i386_pc; +}; + +module = { + name = keylayouts; + common = commands/keylayouts.c; + enable = videomodules; +}; diff --git a/grub-core/boot/decompressor/minilib.c b/grub-core/boot/decompressor/minilib.c new file mode 100644 index 000000000..f2a2ef7e5 --- /dev/null +++ b/grub-core/boot/decompressor/minilib.c @@ -0,0 +1,102 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include + +void * +memset (void *s, int c, grub_size_t len) +{ + grub_uint8_t *ptr; + for (ptr = s; len; ptr++, len--) + *ptr = c; + return s; +} + +void * +grub_memmove (void *dest, const void *src, grub_size_t n) +{ + char *d = (char *) dest; + const char *s = (const char *) src; + + if (d < s) + while (n--) + *d++ = *s++; + else + { + d += n; + s += n; + + while (n--) + *--d = *--s; + } + + return dest; +} + +int +grub_memcmp (const void *s1, const void *s2, grub_size_t n) +{ + const char *t1 = s1; + const char *t2 = s2; + + while (n--) + { + if (*t1 != *t2) + return (int) *t1 - (int) *t2; + + t1++; + t2++; + } + + 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 +find_scratch (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize) +{ +#ifdef _mips + /* Decoding from ROM. */ + if (((grub_addr_t) src & 0x10000000)) + { + grub_decompressor_scratch = (void *) ALIGN_UP((grub_addr_t) dst + dstsize, + 256); + return; + } +#endif + if ((char *) src + srcsize > (char *) dst + dstsize) + grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize, + 256); + else + grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize, + 256); + return; +} diff --git a/kern/i386/ieee1275/init.c b/grub-core/boot/decompressor/none.c similarity index 63% rename from kern/i386/ieee1275/init.c rename to grub-core/boot/decompressor/none.c index 9fb98739b..44f56ce90 100644 --- a/kern/i386/ieee1275/init.c +++ b/grub-core/boot/decompressor/none.c @@ -1,7 +1,6 @@ -/* init.c -- Initialize GRUB on Open Firmware. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2004,2005,2007,2008 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,12 +16,24 @@ * along with GRUB. If not, see . */ -#include -#include - -void grub_stop_floppy (void); +#include void -grub_stop_floppy (void) +grub_decompress_core (void *src, void *dest, unsigned long n, + unsigned long dstsize __attribute__ ((unused))) { + char *d = (char *) dest; + const char *s = (const char *) src; + + if (d < s) + while (n--) + *d++ = *s++; + else + { + d += n; + s += n; + + while (n--) + *--d = *--s; + } } diff --git a/grub-core/boot/decompressor/xz.c b/grub-core/boot/decompressor/xz.c new file mode 100644 index 000000000..2279118e1 --- /dev/null +++ b/grub-core/boot/decompressor/xz.c @@ -0,0 +1,60 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include + +#include "xz.h" +#include "xz_stream.h" + +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize) +{ + struct xz_dec *dec; + struct xz_buf buf; + + find_scratch (src, dst, srcsize, dstsize); + + dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE); + + buf.in = src; + buf.in_pos = 0; + buf.in_size = srcsize; + buf.out = dst; + buf.out_pos = 0; + buf.out_size = dstsize; + + while (buf.in_pos != buf.in_size) + { + enum xz_ret xzret; + xzret = xz_dec_run (dec, &buf); + switch (xzret) + { + case XZ_MEMLIMIT_ERROR: + case XZ_FORMAT_ERROR: + case XZ_OPTIONS_ERROR: + case XZ_DATA_ERROR: + case XZ_BUF_ERROR: + return; + default: + break; + } + } +} diff --git a/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S similarity index 98% rename from boot/i386/pc/boot.S rename to grub-core/boot/i386/pc/boot.S index 4afc57349..320918566 100644 --- a/boot/i386/pc/boot.S +++ b/grub-core/boot/i386/pc/boot.S @@ -112,12 +112,16 @@ LOCAL(after_BPB): */ . = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK boot_drive_check: - jmp 1f /* grub-setup may overwrite this jump */ + jmp 3f /* grub-setup may overwrite this jump */ testb $0x80, %dl - jnz 1f + jz 2f +3: + /* Ignore %dl different from 0-0x0f and 0x80-0x8f. */ + testb $0x70, %dl + jz 1f +2: movb $0x80, %dl 1: - /* * ljmp to the next instruction because some bogus BIOSes * jump to 07C0:0000 instead of 0000:7C00. @@ -153,10 +157,6 @@ real_start: /* set %si to the disk address packet */ movw $disk_address_packet, %si - /* do not probe LBA if the drive is a floppy */ - testb $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl - jz LOCAL(chs_mode) - /* check if LBA is supported */ movb $0x41, %ah movw $0x55aa, %bx diff --git a/boot/i386/pc/cdboot.S b/grub-core/boot/i386/pc/cdboot.S similarity index 100% rename from boot/i386/pc/cdboot.S rename to grub-core/boot/i386/pc/cdboot.S diff --git a/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S similarity index 100% rename from boot/i386/pc/diskboot.S rename to grub-core/boot/i386/pc/diskboot.S diff --git a/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S similarity index 98% rename from boot/i386/pc/lnxboot.S rename to grub-core/boot/i386/pc/lnxboot.S index b4f0030b8..9a599c261 100644 --- a/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -185,7 +185,7 @@ real_code_2: call LOCAL(move_memory) /* Check for multiboot signature. */ - cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_DATA_END) + cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART) jz 1f movl (ramdisk_image - start), %esi diff --git a/boot/i386/pc/pxeboot.S b/grub-core/boot/i386/pc/pxeboot.S similarity index 100% rename from boot/i386/pc/pxeboot.S rename to grub-core/boot/i386/pc/pxeboot.S diff --git a/boot/i386/qemu/boot.S b/grub-core/boot/i386/qemu/boot.S similarity index 98% rename from boot/i386/qemu/boot.S rename to grub-core/boot/i386/qemu/boot.S index fe14f0f06..97aeab9e6 100644 --- a/boot/i386/qemu/boot.S +++ b/grub-core/boot/i386/qemu/boot.S @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/kern/mips/startup.S b/grub-core/boot/mips/startup_raw.S similarity index 54% rename from kern/mips/startup.S rename to grub-core/boot/mips/startup_raw.S index c67bb9742..c41ce8257 100644 --- a/kern/mips/startup.S +++ b/grub-core/boot/mips/startup_raw.S @@ -23,25 +23,26 @@ #include #define BASE_ADDR 8 - + .extern __bss_start .extern _end - + .globl __start, _start, start + .set noreorder + .set nomacro __start: _start: -start: +start: + bal codestart + nop base: . = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE compressed_size: .long 0 - . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE -total_module_size: + . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE +uncompressed_size: .long 0 - . = _start + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE -kernel_image_size: - .long 0 codestart: /* Save our base. */ move $s0, $ra @@ -57,24 +58,28 @@ codestart: /* $a2 has the environment. */ addiu $t0, $a2, 1 beq $t0, $zero, argdone + nop move $t0, $a2 argcont: lw $t1, 0($t0) beq $t1, $zero, argdone + nop #define DO_PARSE(str, reg) \ addiu $t2, $s0, (str-base);\ bal parsestr;\ + nop ;\ beq $v0, $zero, 1f;\ - move reg, $v0;\ + nop ;\ b 2f;\ + move reg, $v0; \ 1: DO_PARSE (busclockstr, $s2) DO_PARSE (cpuclockstr, $s3) DO_PARSE (memsizestr, $s4) DO_PARSE (highmemsizestr, $s5) 2: - addiu $t0, $t0, 4 b argcont + addiu $t0, $t0, 4 parsestr: move $v0, $zero move $t3, $t1 @@ -84,8 +89,11 @@ parsestr: addiu $t2, $t2, 1 addiu $t3, $t3, 1 beq $t5, $zero, 1f + nop beq $t5, $t4, 3b + nop bne $t4, $zero, 1f + nop addiu $t3, $t3, 0xffff digcont: @@ -93,8 +101,10 @@ digcont: /* Substract '0' from digit. */ addiu $t5, $t5, 0xffd0 bltz $t5, 1f + nop addiu $t4, $t5, 0xfff7 bgtz $t4, 1f + nop /* Multiply $v0 by 10 with bitshifts. */ sll $v0, $v0, 1 sll $t4, $v0, 2 @@ -102,8 +112,10 @@ digcont: addu $v0, $v0, $t5 addiu $t3, $t3, 1 b digcont + nop 1: jr $ra + nop busclockstr: .asciiz "busclock=" cpuclockstr: .asciiz "cpuclock=" memsizestr: .asciiz "memsize=" @@ -111,116 +123,65 @@ highmemsizestr: .asciiz "highmemsize=" .p2align 2 argdone: #endif + /* Copy the decompressor. */ + lui $t1, %hi(base) + addiu $t1, $t1, %lo(base) + lui $t3, %hi(__bss_start) + addiu $t3, $t3, %lo(__bss_start) + move $t2, $s0 + +1: + beq $t1, $t3, 2f + lb $t4, 0($t2) + sb $t4, 0($t1) + addiu $t1, $t1, 1 + b 1b + addiu $t2, $t2, 1 +2: + /* Clean out its BSS. */ + lui $t1, %hi(__bss_start) + addiu $t1, $t1, %lo(__bss_start) + lui $t2, %hi(_end) + addiu $t2, $t2, %lo(_end) +1: + beq $t1, $t2, 2f + nop + sb $zero, 0($t1) + b 1b + addiu $t1, $t1, 1 +2: /* Decompress the payload. */ - addiu $a0, $s0, GRUB_KERNEL_MACHINE_RAW_SIZE - BASE_ADDR - lui $a1, %hi(compressed) - addiu $a1, %lo(compressed) + lui $a0, %hi(__bss_start) + addiu $a0, $a0, %lo(__bss_start) + lui $t0, %hi(base) + addiu $t0, $t0, %lo(base) + subu $a0, $a0, $t0 + addu $a0, $a0, $s0 + + lui $a1, %hi(GRUB_MACHINE_LINK_ADDR) + addiu $a1, %lo(GRUB_MACHINE_LINK_ADDR) lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) + lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0) move $s1, $a1 /* $a0 contains source compressed address, $a1 is destination, - $a2 is compressed size. FIXME: put LZMA here. Don't clober $s0, - $s1, $s2, $s3, $s4 and $s5. - On return $v0 contains uncompressed size. + $a2 is compressed size, $a3 is uncompressed size. */ - move $v0, $a2 -reloccont: - lb $t4, 0($a0) - sb $t4, 0($a1) - addiu $a1,$a1,1 - addiu $a0,$a0,1 - addiu $a2, 0xffff - bne $a2, $0, reloccont + move $s6, $a3 + lui $sp, %hi(_start - 256) + + bal EXT_C(grub_decompress_core) + addiu $sp, $sp, %lo(_start - 256) + move $a0, $s1 - move $a1, $v0 + move $a1, $s6 -#include "cache_flush.S" +#include "../../kern/mips/cache_flush.S" - lui $t1, %hi(cont) - addiu $t1, %lo(cont) + lui $t1, %hi(GRUB_MACHINE_LINK_ADDR) + addiu $t1, %lo(GRUB_MACHINE_LINK_ADDR) jr $t1 - . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE -compressed: - . = _start + GRUB_KERNEL_MACHINE_PREFIX - -VARIABLE(grub_prefix) - - /* to be filled by grub-mkelfimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_DATA_END -#ifdef GRUB_MACHINE_MIPS_YEELOONG -VARIABLE (grub_arch_busclock) - .long 0 -VARIABLE (grub_arch_cpuclock) - .long 0 -VARIABLE (grub_arch_memsize) - .long 0 -VARIABLE (grub_arch_highmemsize) - .long 0 -#endif -cont: - -#ifdef GRUB_MACHINE_MIPS_YEELOONG - lui $t1, %hi(grub_arch_busclock) - addiu $t1, %lo(grub_arch_busclock) - sw $s2, 0($t1) - sw $s3, 4($t1) - sw $s4, 8($t1) - sw $s5, 12($t1) -#endif - - /* Move the modules out of BSS. */ - lui $t1, %hi(_start) - addiu $t1, %lo(_start) - lw $t2, (GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE - BASE_ADDR)($s0) - addu $t2, $t1, $t2 - - lui $t1, %hi(_end) - addiu $t1, %lo(_end) - addiu $t1, (GRUB_KERNEL_MACHINE_MOD_ALIGN-1) - li $t3, (GRUB_KERNEL_MACHINE_MOD_ALIGN-1) - nor $t3, $t3, $0 - and $t1, $t1, $t3 - - lw $t3, (GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE - BASE_ADDR)($s0) - - /* Backward copy. */ - add $t1, $t1, $t3 - add $t2, $t2, $t3 - addiu $t1, $t1, 0xffff - addiu $t2, $t2, 0xffff - - /* $t2 is source. $t1 is destination. $t3 is size. */ -modulesmovcont: - lb $t4, 0($t2) - sb $t4, 0($t1) - addiu $t1,$t1,0xffff - addiu $t2,$t2,0xffff - addiu $t3, 0xffff - bne $t3, $0, modulesmovcont - - /* Clean BSS. */ - - lui $t1, %hi(__bss_start) - addiu $t1, %lo(__bss_start) - lui $t2, %hi(_end) - addiu $t2, %lo(_end) -bsscont: - sb $0,0($t1) - addiu $t1,$t1,1 - sltu $t3,$t1,$t2 - bne $t3, $0, bsscont - - li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH - lui $t1, %hi(grub_main) - addiu $t1, %lo(grub_main) - - jr $t1 - + nop diff --git a/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S similarity index 99% rename from boot/mips/yeeloong/fwstart.S rename to grub-core/boot/mips/yeeloong/fwstart.S index 7fe5d7ac2..425458401 100644 --- a/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -20,7 +20,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/boot/sparc64/ieee1275/boot.S b/grub-core/boot/sparc64/ieee1275/boot.S similarity index 100% rename from boot/sparc64/ieee1275/boot.S rename to grub-core/boot/sparc64/ieee1275/boot.S diff --git a/boot/sparc64/ieee1275/diskboot.S b/grub-core/boot/sparc64/ieee1275/diskboot.S similarity index 100% rename from boot/sparc64/ieee1275/diskboot.S rename to grub-core/boot/sparc64/ieee1275/diskboot.S diff --git a/bus/bonito.c b/grub-core/bus/bonito.c similarity index 100% rename from bus/bonito.c rename to grub-core/bus/bonito.c diff --git a/bus/cs5536.c b/grub-core/bus/cs5536.c similarity index 100% rename from bus/cs5536.c rename to grub-core/bus/cs5536.c diff --git a/bus/emu/pci.c b/grub-core/bus/emu/pci.c similarity index 98% rename from bus/emu/pci.c rename to grub-core/bus/emu/pci.c index 420ae320b..d1beb561d 100644 --- a/bus/emu/pci.c +++ b/grub-core/bus/emu/pci.c @@ -19,6 +19,7 @@ #include #include +#include #include grub_pci_address_t diff --git a/bus/pci.c b/grub-core/bus/pci.c similarity index 100% rename from bus/pci.c rename to grub-core/bus/pci.c diff --git a/bus/usb/emu/usb.c b/grub-core/bus/usb/emu/usb.c similarity index 100% rename from bus/usb/emu/usb.c rename to grub-core/bus/usb/emu/usb.c diff --git a/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c similarity index 70% rename from bus/usb/ohci.c rename to grub-core/bus/usb/ohci.c index 42af11466..8adaee6e0 100644 --- a/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -55,12 +55,12 @@ struct grub_ohci_td grub_uint32_t next_td; /* LittleEndian physical address */ grub_uint32_t buffer_end; /* LittleEndian physical address */ /* next values are not for OHCI HW */ + volatile struct grub_ohci_td *link_td; /* pointer to next free/chained TD + * pointer as uint32 */ grub_uint32_t prev_td_phys; /* we need it to find previous TD * physical address in CPU endian */ - grub_uint32_t link_td; /* pointer to next free/chained TD - * pointer as uint32 */ grub_uint32_t tr_index; /* index of TD in transfer */ - grub_uint8_t pad[4]; /* padding to 32 bytes */ + grub_uint8_t pad[8 - sizeof (volatile struct grub_ohci_td *)]; /* padding to 32 bytes */ } __attribute__((packed)); /* OHCI Endpoint Descriptor. */ @@ -98,7 +98,6 @@ struct grub_ohci struct grub_pci_dma_chunk *td_chunk; struct grub_ohci *next; grub_ohci_td_t td_free; /* Pointer to first free TD */ - int bad_OHCI; }; static struct grub_ohci *ohci; @@ -149,9 +148,9 @@ typedef enum #define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4) #define GRUB_OHCI_RESET_CONNECT_CHANGE (1 << 16) -#define GRUB_OHCI_CTRL_EDS 16 -#define GRUB_OHCI_BULK_EDS 16 -#define GRUB_OHCI_TDS 256 +#define GRUB_OHCI_CTRL_EDS 256 +#define GRUB_OHCI_BULK_EDS 510 +#define GRUB_OHCI_TDS 640 #define GRUB_OHCI_ED_ADDR_MASK 0x7ff @@ -221,7 +220,6 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_address_t addr; struct grub_ohci *o; grub_uint32_t revision; - int cs5536; int j; /* Determine IO base address. */ @@ -231,7 +229,6 @@ grub_ohci_pci_iter (grub_pci_device_t dev, { grub_uint64_t basereg; - cs5536 = 1; basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE); if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE)) { @@ -334,7 +331,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, /* Preset free TDs chain in TDs */ grub_memset ((void*)o->td, 0, sizeof(struct grub_ohci_td) * GRUB_OHCI_TDS); for (j=0; j < (GRUB_OHCI_TDS-1); j++) - o->td[j].link_td = (grub_uint32_t)&o->td[j+1]; + o->td[j].link_td = &o->td[j+1]; grub_dprintf ("ohci", "TDs: chunk=%p, virt=%p, phys=0x%02x\n", o->td_chunk, o->td, o->td_addr); @@ -442,8 +439,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev, (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) & ~GRUB_OHCI_RHUB_PORT_POWER_MASK) | GRUB_OHCI_RHUB_PORT_ALL_POWERED); +#if 0 /* We don't need it at all, handled via hotplugging */ /* Now we have hot-plugging, we need to wait for stable power only */ grub_millisleep (100); +#endif /* Link to ohci now that initialisation is successful. */ o->next = ohci; @@ -561,7 +560,7 @@ static void grub_ohci_free_td (struct grub_ohci *o, grub_ohci_td_t td) { grub_memset ( (void*)td, 0, sizeof(struct grub_ohci_td) ); - td->link_td = (grub_uint32_t) o->td_free; /* Cahin new free TD & rest */ + td->link_td = o->td_free; /* Cahin new free TD & rest */ o->td_free = td; /* Change address of first free TD */ } @@ -604,8 +603,8 @@ grub_ohci_transaction (grub_ohci_td_t td, grub_uint32_t buffer; grub_uint32_t buffer_end; - grub_dprintf ("ohci", "OHCI transaction td=%p type=%d, toggle=%d, size=%d\n", - td, type, toggle, size); + grub_dprintf ("ohci", "OHCI transaction td=%p type=%d, toggle=%d, size=%lu\n", + td, type, toggle, (unsigned long) size); switch (type) { @@ -623,7 +622,8 @@ grub_ohci_transaction (grub_ohci_td_t td, break; } - /* Set the token (Always generate interrupt - bits 21-23 = 0). */ + /* Set the token */ + token |= ( 7 << 21); /* Never generate interrupt */ token |= toggle << 24; token |= 1 << 25; @@ -652,33 +652,31 @@ grub_ohci_transaction (grub_ohci_td_t td, td->next_td = 0; } +struct grub_ohci_transfer_controller_data +{ + grub_uint32_t tderr_phys; + grub_uint32_t td_last_phys; + grub_ohci_ed_t ed_virt; + grub_ohci_td_t td_current_virt; + grub_ohci_td_t td_head_virt; +}; + static grub_usb_err_t -grub_ohci_transfer (grub_usb_controller_t dev, - grub_usb_transfer_t transfer) +grub_ohci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) { struct grub_ohci *o = (struct grub_ohci *) dev->data; - grub_ohci_ed_t ed_virt; int bulk = 0; - grub_ohci_td_t td_head_virt; - grub_ohci_td_t td_current_virt; grub_ohci_td_t td_next_virt; - grub_ohci_td_t tderr_virt = NULL; grub_uint32_t target; grub_uint32_t td_head_phys; grub_uint32_t td_tail_phys; - grub_uint32_t td_last_phys; - grub_uint32_t tderr_phys = 0; - grub_uint32_t status; - grub_uint32_t control; - grub_uint8_t errcode = 0; - grub_usb_err_t err = GRUB_USB_ERR_NONE; int i; - grub_uint64_t maxtime; - grub_uint64_t bad_OHCI_delay = 0; - int err_halt = 0; - int err_timeout = 0; - int err_unrec = 0; - grub_uint32_t intstatus; + struct grub_ohci_transfer_controller_data *cdata; + + cdata = grub_zalloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; /* Pre-set target for ED - we need it to find proper ED */ /* Set the device address. */ @@ -700,21 +698,23 @@ grub_ohci_transfer (grub_usb_controller_t dev, case GRUB_USB_TRANSACTION_TYPE_CONTROL: break; - default : + default: + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Find proper ED or add new ED */ - ed_virt = grub_ohci_find_ed (o, bulk, target); - if (!ed_virt) + cdata->ed_virt = grub_ohci_find_ed (o, bulk, target); + if (!cdata->ed_virt) { grub_dprintf ("ohci","Fatal: No free ED !\n"); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Take pointer to first TD from ED */ - td_head_phys = grub_le_to_cpu32 (ed_virt->td_head) & ~0xf; - td_tail_phys = grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf; + td_head_phys = grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf; + td_tail_phys = grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf; /* Sanity check - td_head should be equal to td_tail */ if (td_head_phys != td_tail_phys) /* Should never happen ! */ @@ -723,6 +723,7 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_dprintf ("ohci", "HEAD = 0x%02x, TAIL = 0x%02x\n", td_head_phys, td_tail_phys); /* XXX: Fix: What to do ? */ + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } @@ -730,65 +731,62 @@ grub_ohci_transfer (grub_usb_controller_t dev, * we must allocate the first TD. */ if (!td_head_phys) { - td_head_virt = grub_ohci_alloc_td (o); - if (!td_head_virt) + cdata->td_head_virt = grub_ohci_alloc_td (o); + if (!cdata->td_head_virt) return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ /* We can set td_head only when ED is not active, i.e. * when it is newly allocated. */ - ed_virt->td_head = grub_cpu_to_le32 ( grub_ohci_td_virt2phys (o, - td_head_virt) ); - ed_virt->td_tail = ed_virt->td_head; + cdata->ed_virt->td_head + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_head_virt)); + cdata->ed_virt->td_tail = cdata->ed_virt->td_head; } else - td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); + cdata->td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); /* Set TDs */ - td_last_phys = td_head_phys; /* initial value to make compiler happy... */ - for (i = 0, td_current_virt = td_head_virt; + cdata->td_last_phys = td_head_phys; /* initial value to make compiler happy... */ + for (i = 0, cdata->td_current_virt = cdata->td_head_virt; i < transfer->transcnt; i++) { grub_usb_transaction_t tr = &transfer->transactions[i]; - grub_ohci_transaction (td_current_virt, tr->pid, tr->toggle, + grub_ohci_transaction (cdata->td_current_virt, tr->pid, tr->toggle, tr->size, tr->data); /* Set index of TD in transfer */ - td_current_virt->tr_index = (grub_uint32_t) i; - - /* No IRQ request in TD if bad_OHCI set */ - if (o->bad_OHCI) - td_current_virt->token |= grub_cpu_to_le32 ( 7 << 21); + cdata->td_current_virt->tr_index = (grub_uint32_t) i; /* Remember last used (processed) TD phys. addr. */ - td_last_phys = grub_ohci_td_virt2phys (o, td_current_virt); + cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt); /* Allocate next TD */ td_next_virt = grub_ohci_alloc_td (o); if (!td_next_virt) /* No free TD, cancel transfer and free TDs except head TD */ { if (i) /* if i==0 we have nothing to free... */ - grub_ohci_free_tds (o, - grub_ohci_td_phys2virt(o, - grub_le_to_cpu32 (td_head_virt->next_td) ) ); + grub_ohci_free_tds (o, grub_ohci_td_phys2virt(o, + grub_le_to_cpu32 (cdata->td_head_virt->next_td))); /* Reset head TD */ - grub_memset ( (void*)td_head_virt, 0, + grub_memset ( (void*)cdata->td_head_virt, 0, sizeof(struct grub_ohci_td) ); grub_dprintf ("ohci", "Fatal: No free TD !"); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Chain TDs */ - td_current_virt->link_td = (grub_uint32_t) td_next_virt; - td_current_virt->next_td = grub_cpu_to_le32 ( + + cdata->td_current_virt->link_td = td_next_virt; + cdata->td_current_virt->next_td = grub_cpu_to_le32 ( grub_ohci_td_virt2phys (o, td_next_virt) ); td_next_virt->prev_td_phys = grub_ohci_td_virt2phys (o, - td_current_virt); - td_current_virt = td_next_virt; + cdata->td_current_virt); + cdata->td_current_virt = td_next_virt; } grub_dprintf ("ohci", "Tail TD (not processed) = %p\n", - td_current_virt); + cdata->td_current_virt); /* Setup the Endpoint Descriptor for transfer. */ /* First set necessary fields in TARGET but keep (or set) skip bit */ @@ -796,12 +794,12 @@ grub_ohci_transfer (grub_usb_controller_t dev, * size never change after first allocation of ED. * But unfortunately max. packet size may change during initial * setup sequence and we must handle it. */ - ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); + cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); /* Set td_tail */ - ed_virt->td_tail - = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, td_current_virt)); + cdata->ed_virt->td_tail + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_current_virt)); /* Now reset skip bit */ - ed_virt->target = grub_cpu_to_le32 (target); + cdata->ed_virt->target = grub_cpu_to_le32 (target); /* ed_virt->td_head = grub_cpu_to_le32 (td_head); Must not be changed, it is maintained by OHCI */ /* ed_virt->next_ed = grub_cpu_to_le32 (0); Handled by grub_ohci_find_ed, do not change ! */ @@ -831,93 +829,21 @@ grub_ohci_transfer (grub_usb_controller_t dev, } } - /* Safety measure to avoid a hang. */ - maxtime = grub_get_time_ms () + 1000; - - /* Wait until the transfer is completed or STALLs. */ - do - { - /* Check transfer status */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - { - /* Remember last successful TD */ - tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - /* Reset DoneHead */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* if TD is last, finish */ - if (tderr_phys == td_last_phys) - { - if (grub_le_to_cpu32 (ed_virt->td_head) & 1) - err_halt = 1; - break; - } - continue; - } + transfer->controller_data = cdata; - if ((intstatus & 0x10) != 0) - { /* Unrecoverable error - only reset can help...! */ - err_unrec = 1; - break; - } + return GRUB_USB_ERR_NONE; +} - /* Detected a HALT. */ - if (err_halt || (grub_le_to_cpu32 (ed_virt->td_head) & 1)) - { - err_halt = 1; - /* ED is halted, but donehead event can happened in the meantime */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - /* Don't break loop now, first do donehead action(s) */ - continue; - break; - } - - /* bad OHCI handling */ - if ( (grub_le_to_cpu32 (ed_virt->td_head) & ~0xf) == - (grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf) ) /* Empty ED */ - { - if (o->bad_OHCI) /* Bad OHCI detected previously */ - { - /* Try get last successful TD. */ - tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - if (tderr_phys)/* Reset DoneHead if we were successful */ - { - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - } - /* Check the HALT bit */ - if (grub_le_to_cpu32 (ed_virt->td_head) & 1) - err_halt = 1; - break; - } - else /* Detection of bad OHCI */ - /* We should wait short time (~2ms) before we say that - * it is bad OHCI to prevent some hazard - - * donehead can react in the meantime. This waiting is done - * only once per OHCI driver "live cycle". */ - if (!bad_OHCI_delay) /* Set delay time */ - bad_OHCI_delay = grub_get_time_ms () + 2; - else if (grub_get_time_ms () >= bad_OHCI_delay) - o->bad_OHCI = 1; - continue; - } - - /* Timeout ? */ - if (grub_get_time_ms () > maxtime) - { - err_timeout = 1; - break; - } - - grub_cpu_idle (); - } - while (1); +static void +pre_finish_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint32_t target; + grub_uint32_t status; + grub_uint32_t control; + grub_uint32_t intstatus; /* There are many ways how the loop above can finish: * - normally without any error via INTSTATUS WDH bit @@ -949,8 +875,8 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Remember target for debug and set skip flag in ED */ /* It should be normaly not necessary but we need it at least * in case of timeout */ - target = grub_le_to_cpu32 ( ed_virt->target ); - ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); + target = grub_le_to_cpu32 ( cdata->ed_virt->target ); + cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); /* Read registers for debug - they should be read now because * debug prints case unwanted delays, so something can happen * in the meantime... */ @@ -960,252 +886,321 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Now print debug values - to have full info what happened */ grub_dprintf ("ohci", "loop finished: control=0x%02x status=0x%02x\n", control, status); - grub_dprintf ("ohci", "intstatus=0x%02x \n\t\t tderr_phys=0x%02x, td_last_phys=0x%02x\n", - intstatus, tderr_phys, td_last_phys); - grub_dprintf ("ohci", "err_unrec=%d, err_timeout=%d \n\t\t err_halt=%d, bad_OHCI=%d\n", - err_unrec, err_timeout, err_halt, o->bad_OHCI); + grub_dprintf ("ohci", "intstatus=0x%02x, td_last_phys=0x%02x\n", + intstatus, cdata->td_last_phys); grub_dprintf ("ohci", "TARGET=0x%02x, HEAD=0x%02x, TAIL=0x%02x\n", target, - grub_le_to_cpu32 (ed_virt->td_head), - grub_le_to_cpu32 (ed_virt->td_tail) ); + grub_le_to_cpu32 (cdata->ed_virt->td_head), + grub_le_to_cpu32 (cdata->ed_virt->td_tail) ); - if (!err_halt && !err_unrec && !err_timeout) /* normal finish */ - { - /* Simple workaround if donehead is not working */ - if (o->bad_OHCI && - ( !tderr_phys || (tderr_phys != td_last_phys) ) ) - { - grub_dprintf ("ohci", "normal finish, but tderr_phys corrected\n"); - tderr_phys = td_last_phys; - /* I hope we can do it as transfer (most probably) finished OK */ - } - /* Prepare pointer to last processed TD */ - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - /* Set index of last processed TD */ - if (tderr_virt) - transfer->last_trans = tderr_virt->tr_index; - else - transfer->last_trans = -1; - } +} - else if (err_halt) /* error, ED is halted by OHCI, i.e. can be modified */ - { - /* First we must get proper tderr_phys value */ - if (o->bad_OHCI) /* In case of bad_OHCI tderr_phys can be wrong */ - { - if ( tderr_phys ) /* check if tderr_phys points to TD with error */ - errcode = grub_le_to_cpu32 ( grub_ohci_td_phys2virt (o, - tderr_phys)->token ) - >> 28; - if ( !tderr_phys || !errcode ) /* tderr_phys not valid or points to wrong TD */ - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - } +static void +finish_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; - /* Even if we have "good" OHCI, in some cases - * tderr_phys can be zero, check it */ - else if ( !tderr_phys ) - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - - /* Prepare pointer to last processed TD and get error code */ - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - /* Set index of last processed TD */ - if (tderr_virt) - { - errcode = grub_le_to_cpu32 ( tderr_virt->token ) >> 28; - transfer->last_trans = tderr_virt->tr_index; - } - else - transfer->last_trans = -1; - - /* Evaluation of error code */ - grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", - tderr_phys, errcode); - switch (errcode) - { - case 0: - /* XXX: Should not happen! */ - grub_error (GRUB_ERR_IO, "OHCI without reporting the reason"); - err = GRUB_USB_ERR_INTERNAL; - break; - - case 1: - /* XXX: CRC error. */ - err = GRUB_USB_ERR_TIMEOUT; - break; - - case 2: - err = GRUB_USB_ERR_BITSTUFF; - break; - - case 3: - /* XXX: Data Toggle error. */ - err = GRUB_USB_ERR_DATA; - break; - - case 4: - err = GRUB_USB_ERR_STALL; - break; - - case 5: - /* XXX: Not responding. */ - err = GRUB_USB_ERR_TIMEOUT; - break; - - case 6: - /* XXX: PID Check bits failed. */ - err = GRUB_USB_ERR_BABBLE; - break; - - case 7: - /* XXX: PID unexpected failed. */ - err = GRUB_USB_ERR_BABBLE; - break; - - case 8: - /* XXX: Data overrun error. */ - err = GRUB_USB_ERR_DATA; - grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", - tderr_virt, tderr_virt->tr_index); - break; - - case 9: - /* XXX: Data underrun error. */ - err = GRUB_USB_ERR_DATA; - grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", - tderr_virt, tderr_virt->tr_index); - grub_dprintf ("ohci", "Underrun, number of not transferred bytes: %d\n", - 1 + grub_le_to_cpu32 (tderr_virt->buffer_end) - - grub_le_to_cpu32 (tderr_virt->buffer)); - break; - - case 10: - /* XXX: Reserved. */ - err = GRUB_USB_ERR_NAK; - break; - - case 11: - /* XXX: Reserved. */ - err = GRUB_USB_ERR_NAK; - break; - - case 12: - /* XXX: Buffer overrun. */ - err = GRUB_USB_ERR_DATA; - break; - - case 13: - /* XXX: Buffer underrun. */ - err = GRUB_USB_ERR_DATA; - break; - - default: - err = GRUB_USB_ERR_NAK; - break; - } - - } - - else if (err_unrec) - { - /* Don't try to get error code and last processed TD for proper - * toggle bit value - anything can be invalid */ - err = GRUB_USB_ERR_UNRECOVERABLE; - grub_dprintf("ohci", "Unrecoverable error!"); - - /* Do OHCI reset in case of unrecoverable error - maybe we will need - * do more - re-enumerate bus etc. (?) */ - - /* Suspend the OHCI by issuing a reset. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); - grub_millisleep (1); - grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); - - /* Misc. resets. */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - - /* Enable the OHCI. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, - (2 << 6) - | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE - | GRUB_OHCI_REG_CONTROL_BULK_ENABLE ); - } - - else if (err_timeout) - { - /* In case of timeout do not detect error from TD */ - err = GRUB_ERR_TIMEOUT; - grub_dprintf("ohci", "Timeout !\n"); - - /* We should wait for next SOF to be sure that ED is unaccessed - * by OHCI */ - /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); - /* Wait for new SOF */ - while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); - - /* Now we must find last processed TD if bad_OHCI == TRUE */ - if (o->bad_OHCI) - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf) - ->prev_td_phys; - } - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - if (tderr_virt) - transfer->last_trans = tderr_virt->tr_index; - else - transfer->last_trans = -1; - - } - - /* Set empty ED - set HEAD = TAIL = last (not processed) TD */ - ed_virt->td_head = grub_cpu_to_le32 ( grub_le_to_cpu32 ( - ed_virt->td_tail) & ~0xf); + /* Set empty ED - set HEAD = TAIL = last (not processed) TD */ + cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf); /* At this point always should be: * ED has skip bit set and halted or empty or after next SOF, * i.e. it is safe to free all TDs except last not processed * ED HEAD == TAIL == phys. addr. of td_current_virt */ - /* Reset DoneHead - sanity cleanup */ + /* Un-chainig of last TD */ + if (cdata->td_current_virt->prev_td_phys) + { + grub_ohci_td_t td_prev_virt + = grub_ohci_td_phys2virt (o, cdata->td_current_virt->prev_td_phys); + + if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td) + td_prev_virt->link_td = 0; + + cdata->td_current_virt->prev_td_phys = 0; + } + + grub_dprintf ("ohci", "OHCI finished, freeing\n"); + grub_ohci_free_tds (o, cdata->td_head_virt); + grub_free (cdata); +} + +static grub_usb_err_t +parse_halt (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint8_t errcode = 0; + grub_usb_err_t err = GRUB_USB_ERR_NAK; + grub_ohci_td_t tderr_virt = NULL; + + *actual = 0; + + pre_finish_transfer (dev, transfer); + + /* First we must get proper tderr_phys value */ + /* Retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys = grub_ohci_td_phys2virt (o, + grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf ) + ->prev_td_phys; + + /* Prepare pointer to last processed TD and get error code */ + tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + /* Set index of last processed TD */ + if (tderr_virt) + { + errcode = grub_le_to_cpu32 (tderr_virt->token) >> 28; + transfer->last_trans = tderr_virt->tr_index; + } + else + transfer->last_trans = -1; + + /* Evaluation of error code */ + grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", + cdata->tderr_phys, errcode); + switch (errcode) + { + case 0: + /* XXX: Should not happen! */ + grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason"); + err = GRUB_USB_ERR_INTERNAL; + break; + + case 1: + /* XXX: CRC error. */ + err = GRUB_USB_ERR_TIMEOUT; + break; + + case 2: + err = GRUB_USB_ERR_BITSTUFF; + break; + + case 3: + /* XXX: Data Toggle error. */ + err = GRUB_USB_ERR_DATA; + break; + + case 4: + err = GRUB_USB_ERR_STALL; + break; + + case 5: + /* XXX: Not responding. */ + err = GRUB_USB_ERR_TIMEOUT; + break; + + case 6: + /* XXX: PID Check bits failed. */ + err = GRUB_USB_ERR_BABBLE; + break; + + case 7: + /* XXX: PID unexpected failed. */ + err = GRUB_USB_ERR_BABBLE; + break; + + case 8: + /* XXX: Data overrun error. */ + err = GRUB_USB_ERR_DATA; + grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", + tderr_virt, tderr_virt->tr_index); + break; + + case 9: + /* XXX: Data underrun error. */ + grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", + tderr_virt, tderr_virt->tr_index); + if (transfer->last_trans == -1) + break; + *actual = transfer->transactions[transfer->last_trans].size + - (grub_le_to_cpu32 (tderr_virt->buffer_end) + - grub_le_to_cpu32 (tderr_virt->buffer)) + + transfer->transactions[transfer->last_trans].preceding; + err = GRUB_USB_ERR_NONE; + break; + + case 10: + /* XXX: Reserved. */ + err = GRUB_USB_ERR_NAK; + break; + + case 11: + /* XXX: Reserved. */ + err = GRUB_USB_ERR_NAK; + break; + + case 12: + /* XXX: Buffer overrun. */ + err = GRUB_USB_ERR_DATA; + break; + + case 13: + /* XXX: Buffer underrun. */ + err = GRUB_USB_ERR_DATA; + break; + + default: + err = GRUB_USB_ERR_NAK; + break; + } + + finish_transfer (dev, transfer); + + return err; +} + +static grub_usb_err_t +parse_success (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_ohci_td_t tderr_virt = NULL; + + pre_finish_transfer (dev, transfer); + + /* I hope we can do it as transfer (most probably) finished OK */ + cdata->tderr_phys = cdata->td_last_phys; + + /* Prepare pointer to last processed TD */ + tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + + /* Set index of last processed TD */ + if (tderr_virt) + transfer->last_trans = tderr_virt->tr_index; + else + transfer->last_trans = -1; + *actual = transfer->size + 1; + + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_NONE; +} + +static grub_usb_err_t +parse_unrec (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + + *actual = 0; + + pre_finish_transfer (dev, transfer); + + /* Don't try to get error code and last processed TD for proper + * toggle bit value - anything can be invalid */ + grub_dprintf("ohci", "Unrecoverable error!"); + + /* Do OHCI reset in case of unrecoverable error - maybe we will need + * do more - re-enumerate bus etc. (?) */ + + /* Suspend the OHCI by issuing a reset. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); + grub_millisleep (1); + grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); + + /* Misc. resets. */ o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); /* Read back of register should ensure it is really written */ grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* Un-chainig of last TD */ - if (td_current_virt->prev_td_phys) - { - grub_ohci_td_t td_prev_virt - = grub_ohci_td_phys2virt (o, td_current_virt->prev_td_phys); + /* Enable the OHCI. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, + (2 << 6) + | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE + | GRUB_OHCI_REG_CONTROL_BULK_ENABLE ); + finish_transfer (dev, transfer); - td_next_virt = (grub_ohci_td_t) td_prev_virt->link_td; - if (td_current_virt == td_next_virt) - td_prev_virt->link_td = 0; + return GRUB_USB_ERR_UNRECOVERABLE; +} + +static grub_usb_err_t +grub_ohci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint32_t intstatus; + + /* Check transfer status */ + intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + + if ((intstatus & 0x10) != 0) + /* Unrecoverable error - only reset can help...! */ + return parse_unrec (dev, transfer, actual); + + /* Detected a HALT. */ + if ((grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1)) + return parse_halt (dev, transfer, actual); + + /* Finished ED detection */ + if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == + (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ + { + /* Check the HALT bit */ + /* It looks like nonsense - it was tested previously... + * but it can change because OHCI is working + * simultaneously via DMA... */ + if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) + return parse_halt (dev, transfer, actual); + else + return parse_success (dev, transfer, actual); } - grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x, errcode=0x%02x\n", - err, errcode); - grub_ohci_free_tds (o, td_head_virt); + return GRUB_USB_ERR_WAIT; +} - return err; +static grub_usb_err_t +grub_ohci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_ohci_td_t tderr_virt = NULL; + + pre_finish_transfer (dev, transfer); + + grub_dprintf("ohci", "Timeout !\n"); + + /* We should wait for next SOF to be sure that ED is unaccessed + * by OHCI */ + /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); + /* Wait for new SOF */ + while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); + + /* Possible retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys + = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head) + & ~0xf)->prev_td_phys; + + tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys); + + grub_dprintf ("ohci", "Cancel: tderr_phys=0x%x, tderr_virt=%p\n", + cdata->tderr_phys, tderr_virt); + + if (tderr_virt) + transfer->last_trans = tderr_virt->tr_index; + else + transfer->last_trans = -1; + + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_NONE; } static grub_err_t @@ -1214,6 +1209,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, { struct grub_ohci *o = (struct grub_ohci *) dev->data; grub_uint64_t endtime; + int i; grub_dprintf ("ohci", "begin of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); @@ -1234,31 +1230,47 @@ grub_ohci_portstatus (grub_usb_controller_t dev, return GRUB_ERR_NONE; } - /* Reset the port */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, - GRUB_OHCI_SET_PORT_RESET); - grub_millisleep (50); /* For root hub should be nominaly 50ms */ - - /* End the reset signaling. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, - GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); - grub_millisleep (10); + /* OHCI does one reset signal 10ms long but USB spec. + * requests 50ms for root hub (no need to be continuous). + * So, we do reset 5 times... */ + for (i = 0; i < 5; i++) + { + /* Reset the port - timing of reset is done by OHCI */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET); - /* Enable the port and wait for it. */ + /* Wait for reset completion */ + endtime = grub_get_time_ms () + 1000; + while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) + & GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE)) + if (grub_get_time_ms () > endtime) + return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset"); + + /* End the reset signaling - reset the reset status change */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); + } + + /* Enable port */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_SET_PORT_ENABLE); + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); + + /* Wait for signal enabled */ endtime = grub_get_time_ms () + 1000; while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable"); - grub_millisleep (10); - /* Reset bit Connect Status Change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_RESET_CONNECT_CHANGE); + /* "Reset recovery time" (USB spec.) */ + grub_millisleep (10); + grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); @@ -1275,8 +1287,16 @@ grub_ohci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status); - /* Connect Status Change bit - it detects change of connection */ - *changed = ((status & GRUB_OHCI_RESET_CONNECT_CHANGE) != 0); + /* Connect Status Change bit - it detects change of connection */ + if (status & GRUB_OHCI_RESET_CONNECT_CHANGE) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_RESET_CONNECT_CHANGE); + } + else + *changed = 0; if (! (status & 1)) return GRUB_USB_SPEED_NONE; @@ -1394,7 +1414,9 @@ static struct grub_usb_controller_dev usb_controller = { .name = "ohci", .iterate = grub_ohci_iterate, - .transfer = grub_ohci_transfer, + .setup_transfer = grub_ohci_setup_transfer, + .check_transfer = grub_ohci_check_transfer, + .cancel_transfer = grub_ohci_cancel_transfer, .hubports = grub_ohci_hubports, .portstatus = grub_ohci_portstatus, .detect_dev = grub_ohci_detect_dev @@ -1402,6 +1424,8 @@ static struct grub_usb_controller_dev usb_controller = GRUB_MOD_INIT(ohci) { + COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32); + COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16); grub_ohci_inithw (); grub_usb_controller_dev_register (&usb_controller); grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw, diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c new file mode 100644 index 000000000..ee8794de0 --- /dev/null +++ b/grub-core/bus/usb/serial/common.c @@ -0,0 +1,131 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,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 + +void +grub_usbserial_fini (struct grub_serial_port *port) +{ + port->usbdev->config[port->configno].interf[port->interfno].detach_hook = 0; + port->usbdev->config[port->configno].interf[port->interfno].attached = 0; +} + +void +grub_usbserial_detach (grub_usb_device_t usbdev, int configno, int interfno) +{ + static struct grub_serial_port *port; + port = usbdev->config[configno].interf[interfno].detach_data; + + grub_serial_unregister (port); +} + +static int usbnum = 0; + +int +grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, + struct grub_serial_driver *driver) +{ + struct grub_serial_port *port; + int j; + struct grub_usb_desc_if *interf; + grub_usb_err_t err = GRUB_USB_ERR_NONE; + + interf = usbdev->config[configno].interf[interfno].descif; + + port = grub_malloc (sizeof (*port)); + if (!port) + { + grub_print_error (); + return 0; + } + + port->name = grub_xasprintf ("usb%d", usbnum++); + if (!port->name) + { + grub_free (port); + grub_print_error (); + return 0; + } + + port->usbdev = usbdev; + port->driver = driver; + for (j = 0; j < interf->endpointcnt; j++) + { + struct grub_usb_desc_endp *endp; + endp = &usbdev->config[0].interf[interfno].descendp[j]; + + 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) + { + /* Bulk OUT endpoint. */ + port->out_endp = endp; + } + } + + /* Configure device */ + if (port->out_endp && port->in_endp) + err = grub_usb_set_configuration (usbdev, configno + 1); + + if (!port->out_endp || !port->in_endp || err) + { + grub_free (port->name); + grub_free (port); + return 0; + } + + port->configno = configno; + port->interfno = interfno; + + grub_serial_config_defaults (port); + grub_serial_register (port); + + port->usbdev->config[port->configno].interf[port->interfno].detach_hook + = grub_usbserial_detach; + port->usbdev->config[port->configno].interf[port->interfno].detach_data + = port; + + return 1; +} + +int +grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size) +{ + grub_usb_err_t err; + grub_size_t actual; + + if (port->bufstart < port->bufend) + return port->buf[port->bufstart++]; + + 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) + return -1; + + port->bufstart = header_size; + port->bufend = actual; + if (port->bufstart >= port->bufend) + return -1; + + return port->buf[port->bufstart++]; +} diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c new file mode 100644 index 000000000..bd1713b27 --- /dev/null +++ b/grub-core/bus/usb/serial/ftdi.c @@ -0,0 +1,205 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,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 + +enum + { + GRUB_FTDI_MODEM_CTRL = 0x01, + GRUB_FTDI_FLOW_CTRL = 0x02, + GRUB_FTDI_SPEED_CTRL = 0x03, + GRUB_FTDI_DATA_CTRL = 0x04 + }; + +#define GRUB_FTDI_MODEM_CTRL_DTRRTS 3 +#define GRUB_FTDI_FLOW_CTRL_DTRRTS 3 + +/* Convert speed to divisor. */ +static grub_uint32_t +get_divisor (unsigned int speed) +{ + unsigned int i; + + /* The structure for speed vs. divisor. */ + struct divisor + { + unsigned int speed; + grub_uint32_t div; + }; + + /* The table which lists common configurations. */ + /* Computed with a division formula with 3MHz as base frequency. */ + static struct divisor divisor_tab[] = + { + { 2400, 0x04e2 }, + { 4800, 0x0271 }, + { 9600, 0x4138 }, + { 19200, 0x809c }, + { 38400, 0xc04e }, + { 57600, 0xc034 }, + { 115200, 0x001a } + }; + + /* Set the baud rate. */ + for (i = 0; i < ARRAY_SIZE (divisor_tab); i++) + if (divisor_tab[i].speed == speed) + return divisor_tab[i].div; + return 0; +} + +static void +real_config (struct grub_serial_port *port) +{ + grub_uint32_t divisor; + const grub_uint16_t parities[] = { + [GRUB_SERIAL_PARITY_NONE] = 0x0000, + [GRUB_SERIAL_PARITY_ODD] = 0x0100, + [GRUB_SERIAL_PARITY_EVEN] = 0x0200 + }; + const grub_uint16_t stop_bits[] = { + [GRUB_SERIAL_STOP_BITS_1] = 0x0000, + [GRUB_SERIAL_STOP_BITS_2] = 0x1000, + }; + + if (port->configured) + return; + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + GRUB_FTDI_MODEM_CTRL, + GRUB_FTDI_MODEM_CTRL_DTRRTS, 0, 0, 0); + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + GRUB_FTDI_FLOW_CTRL, + GRUB_FTDI_FLOW_CTRL_DTRRTS, 0, 0, 0); + + divisor = get_divisor (port->config.speed); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + GRUB_FTDI_SPEED_CTRL, + divisor & 0xffff, divisor >> 16, 0, 0); + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + GRUB_FTDI_DATA_CTRL, + parities[port->config.parity] + | stop_bits[port->config.stop_bits] + | port->config.word_len, 0, 0, 0); + + port->configured = 1; +} + +/* Fetch a key. */ +static int +ftdi_hw_fetch (struct grub_serial_port *port) +{ + real_config (port); + + return grub_usbserial_fetch (port, 2); +} + +/* Put a character. */ +static void +ftdi_hw_put (struct grub_serial_port *port, const int c) +{ + char cc = c; + + real_config (port); + + grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); +} + +static grub_err_t +ftdi_hw_configure (struct grub_serial_port *port, + struct grub_serial_config *config) +{ + grub_uint16_t divisor; + + divisor = get_divisor (config->speed); + if (divisor == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); + + if (config->parity != GRUB_SERIAL_PARITY_NONE + && config->parity != GRUB_SERIAL_PARITY_ODD + && config->parity != GRUB_SERIAL_PARITY_EVEN) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity"); + + if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1 + && config->stop_bits != GRUB_SERIAL_STOP_BITS_2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits"); + + if (config->word_len < 5 || config->word_len > 8) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length"); + + port->config = *config; + port->configured = 0; + + return GRUB_ERR_NONE; +} + +static struct grub_serial_driver grub_ftdi_driver = + { + .configure = ftdi_hw_configure, + .fetch = ftdi_hw_fetch, + .put = ftdi_hw_put, + .fini = grub_usbserial_fini + }; + +static const struct +{ + grub_uint16_t vendor, product; +} products[] = + { + {0x0403, 0x6001} /* QEMU virtual USBserial. */ + }; + +static int +grub_ftdi_attach (grub_usb_device_t usbdev, int configno, int interfno) +{ + unsigned j; + + for (j = 0; j < ARRAY_SIZE (products); j++) + if (usbdev->descdev.vendorid == products[j].vendor + && usbdev->descdev.prodid == products[j].product) + break; + if (j == ARRAY_SIZE (products)) + return 0; + + return grub_usbserial_attach (usbdev, configno, interfno, + &grub_ftdi_driver); +} + +static struct grub_usb_attach_desc attach_hook = +{ + .class = 0xff, + .hook = grub_ftdi_attach +}; + +GRUB_MOD_INIT(usbserial_ftdi) +{ + grub_usb_register_attach_hook_class (&attach_hook); +} + +GRUB_MOD_FINI(usbserial_ftdi) +{ + grub_serial_unregister_driver (&grub_ftdi_driver); + grub_usb_unregister_attach_hook_class (&attach_hook); +} diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c new file mode 100644 index 000000000..9e3b9ae7e --- /dev/null +++ b/grub-core/bus/usb/serial/pl2303.c @@ -0,0 +1,218 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,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 + +/* Convert speed to divisor. */ +static grub_uint32_t +is_speed_supported (unsigned int speed) +{ + unsigned int i; + unsigned int supported[] = { 2400, 4800, 9600, 19200, 38400, 57600, 115200}; + + for (i = 0; i < ARRAY_SIZE (supported); i++) + if (supported[i] == speed) + return 1; + return 0; +} + +#define GRUB_PL2303_REQUEST_SET_CONFIG 0x20 +#define GRUB_PL2303_STOP_BITS_1 0x0 +#define GRUB_PL2303_STOP_BITS_2 0x2 + +#define GRUB_PL2303_PARITY_NONE 0 +#define GRUB_PL2303_PARITY_ODD 1 +#define GRUB_PL2303_PARITY_EVEN 2 + +struct grub_pl2303_config +{ + grub_uint32_t speed; + grub_uint8_t stop_bits; + grub_uint8_t parity; + grub_uint8_t word_len; +} __attribute__ ((packed)); + +static void +real_config (struct grub_serial_port *port) +{ + struct grub_pl2303_config config_pl2303; + char xx; + + if (port->configured) + return; + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_IN, + 1, 0x8484, 0, 1, &xx); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 0x0404, 0, 0, 0); + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_IN, + 1, 0x8484, 0, 1, &xx); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_IN, + 1, 0x8383, 0, 1, &xx); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_IN, + 1, 0x8484, 0, 1, &xx); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 0x0404, 1, 0, 0); + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_IN, + 1, 0x8484, 0, 1, &xx); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_IN, + 1, 0x8383, 0, 1, &xx); + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 0, 1, 0, 0); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 1, 0, 0, 0); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 2, 0x44, 0, 0); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 8, 0, 0, 0); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 9, 0, 0, 0); + + if (port->config.stop_bits == GRUB_SERIAL_STOP_BITS_2) + config_pl2303.stop_bits = GRUB_PL2303_STOP_BITS_2; + else + config_pl2303.stop_bits = GRUB_PL2303_STOP_BITS_1; + + switch (port->config.parity) + { + case GRUB_SERIAL_PARITY_NONE: + config_pl2303.parity = GRUB_PL2303_PARITY_NONE; + break; + case GRUB_SERIAL_PARITY_ODD: + config_pl2303.parity = GRUB_PL2303_PARITY_ODD; + break; + case GRUB_SERIAL_PARITY_EVEN: + config_pl2303.parity = GRUB_PL2303_PARITY_EVEN; + break; + } + + config_pl2303.word_len = port->config.word_len; + config_pl2303.speed = port->config.speed; + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + GRUB_PL2303_REQUEST_SET_CONFIG, 0, 0, + sizeof (config_pl2303), (char *) &config_pl2303); + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + 0x22, 3, 0, 0, 0); + + grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, + 1, 0, 0x61, 0, 0); + port->configured = 1; +} + +/* Fetch a key. */ +static int +pl2303_hw_fetch (struct grub_serial_port *port) +{ + real_config (port); + + return grub_usbserial_fetch (port, 0); +} + +/* Put a character. */ +static void +pl2303_hw_put (struct grub_serial_port *port, const int c) +{ + char cc = c; + + real_config (port); + + grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); +} + +static grub_err_t +pl2303_hw_configure (struct grub_serial_port *port, + struct grub_serial_config *config) +{ + if (!is_speed_supported (config->speed)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); + + if (config->parity != GRUB_SERIAL_PARITY_NONE + && config->parity != GRUB_SERIAL_PARITY_ODD + && config->parity != GRUB_SERIAL_PARITY_EVEN) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity"); + + if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1 + && config->stop_bits != GRUB_SERIAL_STOP_BITS_2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits"); + + if (config->word_len < 5 || config->word_len > 8) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length"); + + port->config = *config; + port->configured = 0; + + return GRUB_ERR_NONE; +} + +static struct grub_serial_driver grub_pl2303_driver = + { + .configure = pl2303_hw_configure, + .fetch = pl2303_hw_fetch, + .put = pl2303_hw_put, + .fini = grub_usbserial_fini + }; + +static const struct +{ + grub_uint16_t vendor, product; +} products[] = + { + {0x067b, 0x2303} + }; + +static int +grub_pl2303_attach (grub_usb_device_t usbdev, int configno, int interfno) +{ + unsigned j; + + for (j = 0; j < ARRAY_SIZE (products); j++) + if (usbdev->descdev.vendorid == products[j].vendor + && usbdev->descdev.prodid == products[j].product) + break; + if (j == ARRAY_SIZE (products)) + return 0; + + return grub_usbserial_attach (usbdev, configno, interfno, + &grub_pl2303_driver); +} + +static struct grub_usb_attach_desc attach_hook = +{ + .class = 0xff, + .hook = grub_pl2303_attach +}; + +GRUB_MOD_INIT(usbserial_pl2303) +{ + grub_usb_register_attach_hook_class (&attach_hook); +} + +GRUB_MOD_FINI(usbserial_pl2303) +{ + grub_serial_unregister_driver (&grub_pl2303_driver); + grub_usb_unregister_attach_hook_class (&attach_hook); +} diff --git a/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c similarity index 66% rename from bus/usb/uhci.c rename to grub-core/bus/usb/uhci.c index efdf3aceb..d082beac4 100644 --- a/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -28,6 +28,9 @@ #define GRUB_UHCI_IOMASK (0x7FF << 5) +#define N_QH 256 +#define N_TD 640 + typedef enum { GRUB_UHCI_REG_USBCMD = 0x00, @@ -39,6 +42,19 @@ typedef enum #define GRUB_UHCI_LINK_TERMINATE 1 #define GRUB_UHCI_LINK_QUEUE_HEAD 2 +enum + { + GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED = 0x0002, + GRUB_UHCI_REG_PORTSC_PORT_ENABLED = 0x0004, + GRUB_UHCI_REG_PORTSC_RESUME = 0x0040, + GRUB_UHCI_REG_PORTSC_RESET = 0x0200, + GRUB_UHCI_REG_PORTSC_SUSPEND = 0x1000, + GRUB_UHCI_REG_PORTSC_RW = GRUB_UHCI_REG_PORTSC_PORT_ENABLED + | GRUB_UHCI_REG_PORTSC_RESUME | GRUB_UHCI_REG_PORTSC_RESET + | GRUB_UHCI_REG_PORTSC_SUSPEND, + /* These bits should not be written as 1 unless we really need it */ + GRUB_UHCI_PORTSC_RWC = ((1 << 1) | (1 << 3) | (1 << 11) | (3 << 13)) + }; /* UHCI Queue Head. */ struct grub_uhci_qh @@ -87,15 +103,17 @@ struct grub_uhci int iobase; grub_uint32_t *framelist; - /* 256 Queue Heads. */ + /* N_QH Queue Heads. */ grub_uhci_qh_t qh; - /* 256 Transfer Descriptors. */ + /* N_TD Transfer Descriptors. */ grub_uhci_td_t td; /* Free Transfer Descriptors. */ grub_uhci_td_t tdfree; + int qh_busy[N_QH]; + struct grub_uhci *next; }; @@ -196,7 +214,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, /* The QH pointer of UHCI is only 32 bits, make sure this code works on on 64 bits architectures. */ - u->qh = (grub_uhci_qh_t) grub_memalign (4096, 4096); + u->qh = (grub_uhci_qh_t) grub_memalign (4096, sizeof(struct grub_uhci_qh)*N_QH); if (! u->qh) goto fail; @@ -210,7 +228,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, /* The TD pointer of UHCI is only 32 bits, make sure this code works on on 64 bits architectures. */ - u->td = (grub_uhci_td_t) grub_memalign (4096, 4096*2); + u->td = (grub_uhci_td_t) grub_memalign (4096, sizeof(struct grub_uhci_td)*N_TD); if (! u->td) goto fail; @@ -227,9 +245,9 @@ grub_uhci_pci_iter (grub_pci_device_t dev, /* Link all Transfer Descriptors in a list of available Transfer Descriptors. */ - for (i = 0; i < 256; i++) - u->td[i].linkptr = (grub_uint32_t) &u->td[i + 1]; - u->td[255 - 1].linkptr = 0; + for (i = 0; i < N_TD; i++) + u->td[i].linkptr = (grub_uint32_t) (grub_addr_t) &u->td[i + 1]; + u->td[N_TD - 2].linkptr = 0; u->tdfree = u->td; /* Make sure UHCI is disabled! */ @@ -238,20 +256,20 @@ grub_uhci_pci_iter (grub_pci_device_t dev, /* Setup the frame list pointers. Since no isochronous transfers are and will be supported, they all point to the (same!) queue head. */ - fp = (grub_uint32_t) u->qh & (~15); + fp = (grub_uint32_t) (grub_addr_t) u->qh & (~15); /* Mark this as a queue head. */ fp |= 2; for (i = 0; i < 1024; i++) u->framelist[i] = fp; /* Program the framelist address into the UHCI controller. */ grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD, - (grub_uint32_t) u->framelist); + (grub_uint32_t) (grub_addr_t) u->framelist); /* Make the Queue Heads point to each other. */ - for (i = 0; i < 256; i++) + for (i = 0; i < N_QH; i++) { /* Point to the next QH. */ - u->qh[i].linkptr = (grub_uint32_t) (&u->qh[i + 1]) & (~15); + u->qh[i].linkptr = (grub_uint32_t) (grub_addr_t) (&u->qh[i + 1]) & (~15); /* This is a QH. */ u->qh[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD; @@ -261,9 +279,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev, u->qh[i].elinkptr = 1; } - /* The last Queue Head should terminate. 256 are too many QHs so - just use 50. */ - u->qh[50 - 1].linkptr = 1; + /* The last Queue Head should terminate. */ + u->qh[N_QH - 1].linkptr = 1; /* Enable UHCI again. */ grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7)); @@ -319,7 +336,7 @@ grub_alloc_td (struct grub_uhci *u) return NULL; ret = u->tdfree; - u->tdfree = (grub_uhci_td_t) u->tdfree->linkptr; + u->tdfree = (grub_uhci_td_t) (grub_addr_t) u->tdfree->linkptr; return ret; } @@ -327,15 +344,19 @@ grub_alloc_td (struct grub_uhci *u) static void grub_free_td (struct grub_uhci *u, grub_uhci_td_t td) { - td->linkptr = (grub_uint32_t) u->tdfree; + td->linkptr = (grub_uint32_t) (grub_addr_t) u->tdfree; u->tdfree = td; } static void -grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td, - grub_usb_transfer_t transfer) +grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, + grub_usb_transfer_t transfer, grub_size_t *actual) { int i; /* Index of TD in transfer */ + + u->qh_busy[qh - u->qh] = 0; + + *actual = 0; /* Free the TDs in this queue and set last_trans. */ for (i=0; td; i++) @@ -345,10 +366,12 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td, /* Check state of TD and possibly set last_trans */ if (transfer && (td->linkptr & 1)) transfer->last_trans = i; + + *actual += (td->ctrl_status + 1) & 0x7ff; /* Unlink the queue. */ tdprev = td; - td = (grub_uhci_td_t) td->linkptr2; + td = (grub_uhci_td_t) (grub_addr_t) td->linkptr2; /* Free the TD. */ grub_free_td (u, tdprev); @@ -371,19 +394,21 @@ grub_alloc_qh (struct grub_uhci *u, #endif i = 1; - for (; i < 255; i++) + for (; i < N_QH; i++) { - if (u->qh[i].elinkptr & 1) + if (!u->qh_busy[i]) break; } qh = &u->qh[i]; - if (! (qh->elinkptr & 1)) + if (i == N_QH) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free queue heads available"); return NULL; } + u->qh_busy[qh - u->qh] = 1; + return qh; } @@ -391,7 +416,7 @@ static grub_uhci_td_t grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, grub_transfer_type_t type, unsigned int addr, unsigned int toggle, grub_size_t size, - grub_uint32_t data) + grub_uint32_t data, grub_usb_speed_t speed) { grub_uhci_td_t td; static const unsigned int tf[] = { 0x69, 0xE1, 0x2D }; @@ -409,14 +434,15 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, } grub_dprintf ("uhci", - "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=0x%x td=%p\n", - endp, type, addr, toggle, size, data, td); + "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%lu data=0x%x td=%p\n", + endp, type, addr, toggle, (unsigned long) size, data, td); /* Don't point to any TD, just terminate. */ td->linkptr = 1; /* Active! Only retry a transfer 3 times. */ - td->ctrl_status = (1 << 23) | (3 << 27); + td->ctrl_status = (1 << 23) | (3 << 27) | + ((speed == GRUB_USB_SPEED_LOW) ? (1 << 26) : 0); /* If zero bytes are transmitted, size is 0x7FF. Otherwise size is size-1. */ @@ -434,23 +460,35 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, return td; } +struct grub_uhci_transfer_controller_data +{ + grub_uhci_qh_t qh; + grub_uhci_td_t td_first; +}; + static grub_usb_err_t -grub_uhci_transfer (grub_usb_controller_t dev, - grub_usb_transfer_t transfer) +grub_uhci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) { struct grub_uhci *u = (struct grub_uhci *) dev->data; - grub_uhci_qh_t qh; grub_uhci_td_t td; - grub_uhci_td_t td_first = NULL; grub_uhci_td_t td_prev = NULL; - grub_usb_err_t err = GRUB_USB_ERR_NONE; int i; - grub_uint64_t endtime; + struct grub_uhci_transfer_controller_data *cdata; + + cdata = grub_malloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; + + cdata->td_first = NULL; /* Allocate a queue head for the transfer queue. */ - qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL); - if (! qh) - return grub_errno; + cdata->qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL); + if (! cdata->qh) + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; + } grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase); @@ -458,27 +496,30 @@ grub_uhci_transfer (grub_usb_controller_t dev, { grub_usb_transaction_t tr = &transfer->transactions[i]; - td = grub_uhci_transaction (u, transfer->endpoint, tr->pid, + td = grub_uhci_transaction (u, transfer->endpoint & 15, tr->pid, transfer->devaddr, tr->toggle, - tr->size, tr->data); + tr->size, tr->data, + transfer->dev->speed); if (! td) { + grub_size_t actual = 0; /* Terminate and free. */ td_prev->linkptr2 = 0; td_prev->linkptr = 1; - if (td_first) - grub_free_queue (u, td_first, NULL); + if (cdata->td_first) + grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } - if (! td_first) - td_first = td; + if (! cdata->td_first) + cdata->td_first = td; else { - td_prev->linkptr2 = (grub_uint32_t) td; - td_prev->linkptr = (grub_uint32_t) td; + td_prev->linkptr2 = (grub_uint32_t) (grub_addr_t) td; + td_prev->linkptr = (grub_uint32_t) (grub_addr_t) td; td_prev->linkptr |= 4; } td_prev = td; @@ -490,86 +531,112 @@ grub_uhci_transfer (grub_usb_controller_t dev, /* Link it into the queue and terminate. Now the transaction can take place. */ - qh->elinkptr = (grub_uint32_t) td_first; + cdata->qh->elinkptr = (grub_uint32_t) (grub_addr_t) cdata->td_first; grub_dprintf ("uhci", "initiate transaction\n"); - /* Wait until either the transaction completed or an error - occurred. */ - endtime = grub_get_time_ms () + 1000; - for (;;) + transfer->controller_data = cdata; + + return GRUB_USB_ERR_NONE; +} + +static grub_usb_err_t +grub_uhci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_uhci *u = (struct grub_uhci *) dev->data; + grub_uhci_td_t errtd; + struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data; + + *actual = 0; + + errtd = (grub_uhci_td_t) (grub_addr_t) (cdata->qh->elinkptr & ~0x0f); + + 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) { - grub_uhci_td_t errtd; + grub_dprintf ("uhci", "transaction complete\n"); - errtd = (grub_uhci_td_t) (qh->elinkptr & ~0x0f); - - 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 (qh->elinkptr & 1) - break; - - grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); - - /* Check if the TD is not longer active. */ - if (! (errtd->ctrl_status & (1 << 23))) - { - grub_dprintf ("uhci", ">>t status=0x%02x\n", errtd->ctrl_status); - - /* Check if the endpoint is stalled. */ - if (errtd->ctrl_status & (1 << 22)) - err = GRUB_USB_ERR_STALL; - - /* Check if an error related to the data buffer occurred. */ - if (errtd->ctrl_status & (1 << 21)) - err = GRUB_USB_ERR_DATA; - - /* Check if a babble error occurred. */ - if (errtd->ctrl_status & (1 << 20)) - err = GRUB_USB_ERR_BABBLE; - - /* Check if a NAK occurred. */ - if (errtd->ctrl_status & (1 << 19)) - err = GRUB_USB_ERR_NAK; - - /* Check if a timeout occurred. */ - if (errtd->ctrl_status & (1 << 18)) - err = GRUB_USB_ERR_TIMEOUT; - - /* Check if a bitstuff error occurred. */ - if (errtd->ctrl_status & (1 << 17)) - err = GRUB_USB_ERR_BITSTUFF; - - if (err) - goto fail; - - /* Fall through, no errors occurred, so the QH might be - updated. */ - grub_dprintf ("uhci", "transaction fallthrough\n"); - } - if (grub_get_time_ms () > endtime) - { - err = GRUB_USB_ERR_STALL; - grub_dprintf ("uhci", "transaction timed out\n"); - goto fail; - } - grub_cpu_idle (); + /* Place the QH back in the free list and deallocate the associated + TDs. */ + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual); + grub_free (cdata); + return GRUB_USB_ERR_NONE; } - grub_dprintf ("uhci", "transaction complete\n"); + grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); - fail: + if (!(errtd->ctrl_status & (1 << 23))) + { + grub_usb_err_t err = GRUB_USB_ERR_NONE; - if (err != GRUB_USB_ERR_NONE) - grub_dprintf ("uhci", "transaction failed\n"); + /* Check if the endpoint is stalled. */ + if (errtd->ctrl_status & (1 << 22)) + err = GRUB_USB_ERR_STALL; + + /* Check if an error related to the data buffer occurred. */ + else if (errtd->ctrl_status & (1 << 21)) + err = GRUB_USB_ERR_DATA; + + /* Check if a babble error occurred. */ + else if (errtd->ctrl_status & (1 << 20)) + err = GRUB_USB_ERR_BABBLE; + + /* Check if a NAK occurred. */ + else if (errtd->ctrl_status & (1 << 19)) + err = GRUB_USB_ERR_NAK; + + /* Check if a timeout occurred. */ + else if (errtd->ctrl_status & (1 << 18)) + err = GRUB_USB_ERR_TIMEOUT; + + /* Check if a bitstuff error occurred. */ + else if (errtd->ctrl_status & (1 << 17)) + err = GRUB_USB_ERR_BITSTUFF; + + if (err) + { + grub_dprintf ("uhci", "transaction failed\n"); + + /* Place the QH back in the free list and deallocate the associated + TDs. */ + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual); + grub_free (cdata); + + return err; + } + } + + /* Fall through, no errors occurred, so the QH might be + updated. */ + grub_dprintf ("uhci", "transaction fallthrough\n"); + + return GRUB_USB_ERR_WAIT; +} + +static grub_usb_err_t +grub_uhci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_uhci *u = (struct grub_uhci *) dev->data; + grub_size_t actual; + struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data; + + grub_dprintf ("uhci", "transaction cancel\n"); /* Place the QH back in the free list and deallocate the associated TDs. */ - qh->elinkptr = 1; - grub_free_queue (u, td_first, transfer); + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, &actual); + grub_free (cdata); - return err; + return GRUB_USB_ERR_NONE; } static int @@ -620,7 +687,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while ((grub_uhci_readreg16 (u, reg) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out"); + return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable"); status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", ">3detect=0x%02x\n", status); @@ -628,28 +695,37 @@ grub_uhci_portstatus (grub_usb_controller_t dev, } /* Reset the port. */ - grub_uhci_writereg16 (u, reg, 1 << 9); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 9)); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ /* Wait for the reset to complete. XXX: How long exactly? */ grub_millisleep (50); /* For root hub should be nominaly 50ms */ - status = grub_uhci_readreg16 (u, reg); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; grub_uhci_writereg16 (u, reg, status & ~(1 << 9)); - grub_dprintf ("uhci", "reset completed\n"); - grub_millisleep (10); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ + + /* Note: some debug prints were removed because they affected reset/enable timing. */ + + grub_millisleep (1); /* Probably not needed at all or only few microsecs. */ + + /* Reset bits Connect & Enable Status Change */ + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 3) | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ /* Enable the port. */ - grub_uhci_writereg16 (u, reg, 1 << 2); - grub_millisleep (10); - - grub_dprintf ("uhci", "waiting for the port to be enabled\n"); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 2)); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ endtime = grub_get_time_ms () + 1000; while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out"); + return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable"); - /* Reset bit Connect Status Change */ - grub_uhci_writereg16 (u, reg, status | (1 << 1)); + /* Reset recovery time */ + grub_millisleep (10); /* Read final port status */ status = grub_uhci_readreg16 (u, reg); @@ -681,7 +757,15 @@ 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 */ - *changed = ((status & (1 << 1)) != 0); + if (status & (1 << 1)) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_uhci_writereg16 (u, reg, (status & GRUB_UHCI_REG_PORTSC_RW) + | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + } + else + *changed = 0; if (! (status & 1)) return GRUB_USB_SPEED_NONE; @@ -703,7 +787,9 @@ static struct grub_usb_controller_dev usb_controller = { .name = "uhci", .iterate = grub_uhci_iterate, - .transfer = grub_uhci_transfer, + .setup_transfer = grub_uhci_setup_transfer, + .check_transfer = grub_uhci_check_transfer, + .cancel_transfer = grub_uhci_cancel_transfer, .hubports = grub_uhci_hubports, .portstatus = grub_uhci_portstatus, .detect_dev = grub_uhci_detect_dev diff --git a/bus/usb/usb.c b/grub-core/bus/usb/usb.c similarity index 89% rename from bus/usb/usb.c rename to grub-core/bus/usb/usb.c index f6a0a8b56..2bd805ef2 100644 --- a/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -22,6 +22,7 @@ #include #include #include +#include static grub_usb_controller_dev_t grub_usb_list; struct grub_usb_attach_desc *attach_hooks; @@ -208,14 +209,23 @@ grub_usb_device_initialize (grub_usb_device_t dev) goto fail; /* Skip the configuration descriptor. */ - pos = sizeof (struct grub_usb_desc_config); + pos = dev->config[i].descconf->length; /* Read all interfaces. */ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) { + while (pos < config.totallen + && ((struct grub_usb_desc *)&data[pos])->type + != GRUB_USB_DESCRIPTOR_INTERFACE) + pos += ((struct grub_usb_desc *)&data[pos])->length; dev->config[i].interf[currif].descif = (struct grub_usb_desc_if *) &data[pos]; - pos += sizeof (struct grub_usb_desc_if); + pos += dev->config[i].interf[currif].descif->length; + + while (pos < config.totallen + && ((struct grub_usb_desc *)&data[pos])->type + != GRUB_USB_DESCRIPTOR_ENDPOINT) + pos += ((struct grub_usb_desc *)&data[pos])->length; /* Point to the first endpoint. */ dev->config[i].interf[currif].descendp @@ -256,6 +266,24 @@ void grub_usb_device_attach (grub_usb_device_t dev) for (desc = attach_hooks; desc; desc = desc->next) if (interf->class == desc->class && desc->hook (dev, 0, i)) dev->config[0].interf[i].attached = 1; + + if (dev->config[0].interf[i].attached) + continue; + + switch (interf->class) + { + case GRUB_USB_CLASS_MASS_STORAGE: + grub_dl_load ("usbms"); + break; + case GRUB_USB_CLASS_HID: + grub_dl_load ("usb_keyboard"); + break; + case 0xff: + /* FIXME: don't load useless modules. */ + grub_dl_load ("usbserial_ftdi"); + grub_dl_load ("usbserial_pl2303"); + break; + } } } @@ -306,3 +334,14 @@ grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc) { grub_list_remove (GRUB_AS_LIST_P (&attach_hooks), GRUB_AS_LIST (desc)); } + + +GRUB_MOD_INIT(usb) +{ + grub_term_poll_usb = grub_usb_poll_devices; +} + +GRUB_MOD_FINI(usb) +{ + grub_term_poll_usb = NULL; +} diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c new file mode 100644 index 000000000..f08910d2b --- /dev/null +++ b/grub-core/bus/usb/usbhub.c @@ -0,0 +1,559 @@ +/* usb.c - USB Hub Support. */ +/* + * 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 + +#define GRUB_USBHUB_MAX_DEVICES 128 + +/* USB Supports 127 devices, with device 0 as special case. */ +static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; + +static int rescan = 0; + +struct grub_usb_hub +{ + struct grub_usb_hub *next; + grub_usb_controller_t controller; + int nports; + struct grub_usb_device **devices; + grub_usb_device_t dev; +}; + +struct grub_usb_hub *hubs; + +/* 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) +{ + grub_usb_device_t dev; + int i; + grub_usb_err_t err; + + dev = grub_zalloc (sizeof (struct grub_usb_device)); + if (! dev) + return NULL; + + dev->controller = *controller; + dev->speed = speed; + + err = grub_usb_device_initialize (dev); + if (err) + { + grub_free (dev); + return NULL; + } + + /* Assign a new address to the device. */ + for (i = 1; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + if (! grub_usb_devs[i]) + break; + } + if (i == GRUB_USBHUB_MAX_DEVICES) + { + grub_error (GRUB_ERR_IO, "can't assign address to USB device"); + for (i = 0; i < 8; i++) + grub_free (dev->config[i].descconf); + grub_free (dev); + return NULL; + } + + err = grub_usb_control_msg (dev, + (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_STANDARD + | GRUB_USB_REQTYPE_TARGET_DEV), + GRUB_USB_REQ_SET_ADDRESS, + i, 0, 0, NULL); + if (err) + { + for (i = 0; i < 8; i++) + grub_free (dev->config[i].descconf); + grub_free (dev); + return NULL; + } + + dev->addr = i; + dev->initialized = 1; + grub_usb_devs[i] = dev; + + /* Wait "recovery interval", spec. says 2ms */ + grub_millisleep (2); + + grub_usb_device_attach (dev); + + return dev; +} + + +static grub_usb_err_t +grub_usb_add_hub (grub_usb_device_t dev) +{ + struct grub_usb_usb_hubdesc hubdesc; + grub_err_t err; + int i; + + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_DEV), + GRUB_USB_REQ_GET_DESCRIPTOR, + (GRUB_USB_DESCRIPTOR_HUB << 8) | 0, + 0, sizeof (hubdesc), (char *) &hubdesc); + if (err) + return err; + grub_dprintf ("usb", "Hub descriptor:\n\t\t len:%d, typ:0x%02x, cnt:%d, char:0x%02x, pwg:%d, curr:%d\n", + hubdesc.length, hubdesc.type, hubdesc.portcnt, + hubdesc.characteristics, hubdesc.pwdgood, + hubdesc.current); + + /* Activate the first configuration. Hubs should have only one conf. */ + 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; + + /* Power on all Hub ports. */ + for (i = 1; i <= hubdesc.portcnt; i++) + { + grub_dprintf ("usb", "Power on - port %d\n", i); + /* Power on the port and wait for possible device connect */ + 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_POWER, + i, 0, NULL); + } + + /* Rest will be done on next usb poll. */ + for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt; + i++) + { + struct grub_usb_desc_endp *endp = NULL; + endp = &dev->config[0].interf[0].descendp[i]; + + if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) + == GRUB_USB_EP_INTERRUPT) + { + dev->hub_endpoint = endp; + dev->hub_transfer + = grub_usb_bulk_read_background (dev, endp->endp_addr, + grub_min (endp->maxpacket, + sizeof (dev->statuschange)), + (char *) &dev->statuschange); + break; + } + } + + rescan = 1; + + return GRUB_ERR_NONE; +} + +static void +attach_root_port (struct grub_usb_hub *hub, int portno, + grub_usb_speed_t speed) +{ + grub_usb_device_t dev; + grub_err_t err; + int total, i; + grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; + int changed=0; + +#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; + + /* Enable the port and create a device. */ + dev = grub_usb_hub_add_dev (hub->controller, speed); + hub->controller->dev->pending_reset = 0; + if (! dev) + return; + + hub->devices[portno] = dev; + + /* If the device is a Hub, scan it for more devices. */ + if (dev->descdev.class == 0x09) + grub_usb_add_hub (dev); +} + +grub_usb_err_t +grub_usb_root_hub (grub_usb_controller_t controller) +{ + int i; + struct grub_usb_hub *hub; + int changed=0; + + hub = grub_malloc (sizeof (*hub)); + if (!hub) + return GRUB_USB_ERR_INTERNAL; + + hub->next = hubs; + hubs = hub; + hub->controller = grub_malloc (sizeof (*controller)); + if (!hub->controller) + { + grub_free (hub); + return GRUB_USB_ERR_INTERNAL; + } + + grub_memcpy (hub->controller, controller, sizeof (*controller)); + hub->dev = 0; + + /* Query the number of ports the root Hub has. */ + hub->nports = controller->dev->hubports (controller); + hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports); + if (!hub->devices) + { + grub_free (hub->controller); + grub_free (hub); + return GRUB_USB_ERR_INTERNAL; + } + + for (i = 0; i < hub->nports; i++) + { + grub_usb_speed_t speed; + if (!controller->dev->pending_reset) + { + speed = controller->dev->detect_dev (hub->controller, i, + &changed); + + if (speed != GRUB_USB_SPEED_NONE) + attach_root_port (hub, i, speed); + } + } + + return GRUB_USB_ERR_NONE; +} + +static void detach_device (grub_usb_device_t dev); + +static void +detach_device (grub_usb_device_t dev) +{ + unsigned i; + int k; + if (!dev) + return; + if (dev->descdev.class == GRUB_USB_CLASS_HUB) + { + if (dev->hub_transfer) + grub_usb_cancel_transfer (dev->hub_transfer); + + for (i = 0; i < dev->nports; i++) + detach_device (dev->children[i]); + grub_free (dev->children); + } + for (i = 0; i < ARRAY_SIZE (dev->config); i++) + if (dev->config[i].descconf) + for (k = 0; k < dev->config[i].descconf->numif; k++) + { + struct grub_usb_interface *inter = &dev->config[i].interf[k]; + if (inter && inter->detach_hook) + inter->detach_hook (dev, i, k); + } + grub_usb_devs[dev->addr] = 0; +} + +static void +poll_nonroot_hub (grub_usb_device_t dev) +{ + grub_usb_err_t err; + unsigned i; + grub_uint8_t changed; + grub_size_t actual; + int j, total; + + if (!dev->hub_transfer) + return; + + err = grub_usb_check_transfer (dev->hub_transfer, &actual); + + if (err == GRUB_USB_ERR_WAIT) + return; + + changed = dev->statuschange; + + dev->hub_transfer + = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, + grub_min (dev->hub_endpoint->maxpacket, + sizeof (dev->statuschange)), + (char *) &dev->statuschange); + + if (err || actual == 0 || changed == 0) + return; + + /* Iterate over the Hub ports. */ + for (i = 1; i <= dev->nports; i++) + { + grub_uint32_t status; + grub_uint32_t current_status = 0; + + if (!(changed & (1 << i))) + continue; + + /* 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 (status), (char *) &status); + + grub_printf ("dev = %p, i = %d, status = %08x\n", + dev, i, status); + + if (err) + continue; + + /* FIXME: properly handle these conditions. */ + if (status & GRUB_USB_HUB_STATUS_C_PORT_ENABLED) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_ENABLED, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_SUSPEND) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0); + + if (!dev->controller.dev->pending_reset && + (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) + { + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); + + detach_device (dev->children[i - 1]); + dev->children[i - 1] = NULL; + + /* Connected and status of connection changed ? */ + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) + { + /* A device is actually connected to this port. */ + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (total = j = 0; (j < 250) && (total < 2000); j++, total++) + { + grub_millisleep (1); + /* Get the port status. */ + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_GET_STATUS, + 0, i, + sizeof (current_status), + (char *) ¤t_status); + if (err) + { + total = 2000; + break; + } + if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) + j = 0; + } + grub_dprintf ("usb", "(non-root) total=%d\n", total); + if (total >= 2000) + continue; + + /* Now do reset of port. */ + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_RESET, + i, 0, 0); + rescan = 1; + /* We cannot reset more than one device at the same time ! + * Resetting more devices together results in very bad + * situation: more than one device has default address 0 + * at the same time !!! + * Additionaly, we cannot perform another reset + * anywhere on the same OHCI controller until + * we will finish addressing of reseted device ! */ + dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + return; + } + } + + if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET) + { + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) + { + grub_usb_speed_t speed; + grub_usb_device_t next_dev; + + /* Determine the device speed. */ + if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) + speed = GRUB_USB_SPEED_LOW; + else + { + if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) + speed = GRUB_USB_SPEED_HIGH; + else + speed = GRUB_USB_SPEED_FULL; + } + + /* Wait a recovery time after reset, spec. says 10ms */ + grub_millisleep (10); + + /* Add the device and assign a device address to it. */ + next_dev = grub_usb_hub_add_dev (&dev->controller, speed); + dev->controller.dev->pending_reset = 0; + if (! next_dev) + continue; + + dev->children[i - 1] = next_dev; + + /* If the device is a Hub, scan it for more devices. */ + if (next_dev->descdev.class == 0x09) + grub_usb_add_hub (next_dev); + } + } + } +} + +void +grub_usb_poll_devices (void) +{ + struct grub_usb_hub *hub; + int i; + + for (hub = hubs; hub; hub = hub->next) + { + /* Do we have to recheck number of ports? */ + /* No, it should be never changed, it should be constant. */ + for (i = 0; i < hub->nports; i++) + { + grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; + int changed = 0; + + if (!hub->controller->dev->pending_reset) + { + /* Check for possible timeout */ + if (grub_get_time_ms () > hub->controller->dev->pending_reset) + { + /* Something went wrong, reset device was not + * addressed properly, timeout happened */ + hub->controller->dev->pending_reset = 0; + speed = hub->controller->dev->detect_dev (hub->controller, + i, &changed); + } + } + if (changed) + { + detach_device (hub->devices[i]); + hub->devices[i] = NULL; + if (speed != GRUB_USB_SPEED_NONE) + attach_root_port (hub, i, speed); + } + } + } + + while (1) + { + rescan = 0; + + /* We should check changes of non-root hubs too. */ + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + grub_usb_device_t dev = grub_usb_devs[i]; + + if (dev && dev->descdev.class == 0x09) + poll_nonroot_hub (dev); + } + if (!rescan) + break; + grub_millisleep (50); + } + +} + +int +grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) +{ + int i; + + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + if (grub_usb_devs[i]) + { + if (hook (grub_usb_devs[i])) + return 1; + } + } + + return 0; +} diff --git a/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c similarity index 64% rename from bus/usb/usbtrans.c rename to grub-core/bus/usb/usbtrans.c index 4a55cab11..ebb8a2eb6 100644 --- a/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -23,6 +23,41 @@ #include #include #include +#include + +static grub_usb_err_t +grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, + grub_usb_transfer_t transfer, + int timeout, grub_size_t *actual) +{ + grub_usb_err_t err; + grub_uint64_t endtime; + + err = dev->controller.dev->setup_transfer (&dev->controller, transfer); + if (err) + return err; + /* endtime moved behind setup transfer to prevent false timeouts + * while debugging... */ + endtime = grub_get_time_ms () + timeout; + while (1) + { + err = dev->controller.dev->check_transfer (&dev->controller, transfer, + actual); + if (!err) + return GRUB_USB_ERR_NONE; + if (err != GRUB_USB_ERR_WAIT) + return err; + if (grub_get_time_ms () > endtime) + { + err = dev->controller.dev->cancel_transfer (&dev->controller, + transfer); + if (err) + return err; + return GRUB_USB_ERR_TIMEOUT; + } + grub_cpu_idle (); + } +} grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, @@ -43,6 +78,7 @@ grub_usb_control_msg (grub_usb_device_t dev, volatile char *data; grub_uint32_t data_addr; grub_size_t size = size0; + grub_size_t actual; /* FIXME: avoid allocation any kind of buffer in a first place. */ data_chunk = grub_memalign_dma32 (128, size ? : 16); @@ -53,8 +89,8 @@ grub_usb_control_msg (grub_usb_device_t dev, grub_memcpy ((char *) data, data_in, size); grub_dprintf ("usb", - "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n", - reqtype, request, value, index, size); + "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n", + reqtype, request, value, index, (unsigned long)size); /* Create a transfer. */ transfer = grub_malloc (sizeof (*transfer)); @@ -132,6 +168,7 @@ grub_usb_control_msg (grub_usb_device_t dev, else tr->pid = GRUB_USB_TRANSFER_TYPE_OUT; tr->data = data_addr + i * max; + tr->preceding = i * max; size -= max; } @@ -145,7 +182,8 @@ grub_usb_control_msg (grub_usb_device_t dev, transfer->transactions[datablocks + 1].toggle = 1; - err = dev->controller.dev->transfer (&dev->controller, transfer); + err = grub_usb_execute_and_wait_transfer (dev, transfer, 1000, &actual); + grub_dprintf ("usb", "control: err=%d\n", err); grub_free (transfer->transactions); @@ -159,28 +197,28 @@ grub_usb_control_msg (grub_usb_device_t dev, return err; } -static grub_usb_err_t -grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, - grub_transfer_type_t type) +static grub_usb_transfer_t +grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, + int endpoint, grub_size_t size0, char *data_in, + grub_transfer_type_t type) { int i; grub_usb_transfer_t transfer; int datablocks; unsigned int max; - grub_usb_err_t err; - int toggle = dev->toggle[endpoint]; volatile char *data; grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; + int toggle = dev->toggle[endpoint]; - grub_dprintf ("usb", "bulk: size=0x%02x type=%d\n", size, type); + grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size, + type); /* FIXME: avoid allocation any kind of buffer in a first place. */ data_chunk = grub_memalign_dma32 (128, size); if (!data_chunk) - return GRUB_USB_ERR_INTERNAL; + return NULL; data = grub_dma_get_virt (data_chunk); data_addr = grub_dma_get_phys (data_chunk); if (type == GRUB_USB_TRANSFER_TYPE_OUT) @@ -190,7 +228,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (dev->initialized) { struct grub_usb_desc_endp *endpdesc; - endpdesc = grub_usb_get_endpdescriptor (dev, 0); + endpdesc = grub_usb_get_endpdescriptor (dev, endpoint); if (endpdesc) max = endpdesc->maxpacket; @@ -205,18 +243,21 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (! transfer) { grub_dma_free (data_chunk); - return grub_errno; + return NULL; } datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint & 15; + transfer->endpoint = endpoint; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; + transfer->dir = type; transfer->max = max; transfer->dev = dev; transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */ + transfer->data_chunk = data_chunk; + transfer->data = data_in; /* Allocate an array of transfer data structures. */ transfer->transactions = grub_malloc (transfer->transcnt @@ -225,7 +266,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, { grub_free (transfer); grub_dma_free (data_chunk); - return grub_errno; + return NULL; } /* Set up all transfers. */ @@ -240,26 +281,54 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, toggle = toggle ? 0 : 1; tr->pid = type; tr->data = data_addr + i * max; + tr->preceding = i * max; size -= tr->size; } + return transfer; +} + +static void +grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) +{ + grub_usb_device_t dev = transfer->dev; + int toggle = dev->toggle[transfer->endpoint]; - err = dev->controller.dev->transfer (&dev->controller, transfer); /* We must remember proper toggle value even if some transactions * were not processed - correct value should be inversion of last * processed transaction (TD). */ if (transfer->last_trans >= 0) toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1; else - toggle = dev->toggle[endpoint]; /* Nothing done, take original */ - grub_dprintf ("usb", "bulk: err=%d, toggle=%d\n", err, toggle); - dev->toggle[endpoint] = toggle; + toggle = dev->toggle[transfer->endpoint]; /* Nothing done, take original */ + grub_dprintf ("usb", "bulk: toggle=%d\n", toggle); + dev->toggle[transfer->endpoint] = toggle; + + if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) + grub_memcpy (transfer->data, (void *) + grub_dma_get_virt (transfer->data_chunk), + transfer->size + 1); grub_free (transfer->transactions); grub_free (transfer); - grub_dma_free (data_chunk); + grub_dma_free (transfer->data_chunk); +} - if (type == GRUB_USB_TRANSFER_TYPE_IN) - grub_memcpy (data_in, (char *) data, size0); +static grub_usb_err_t +grub_usb_bulk_readwrite (grub_usb_device_t dev, + int endpoint, grub_size_t size0, char *data_in, + grub_transfer_type_t type, int timeout, + grub_size_t *actual) +{ + grub_usb_err_t err; + grub_usb_transfer_t transfer; + + transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size0, + data_in, type); + if (!transfer) + return GRUB_USB_ERR_INTERNAL; + err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual); + + grub_usb_bulk_finish_readwrite (transfer); return err; } @@ -268,14 +337,77 @@ grub_usb_err_t grub_usb_bulk_write (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data) { - return grub_usb_bulk_readwrite (dev, endpoint, size, data, - GRUB_USB_TRANSFER_TYPE_OUT); + grub_size_t actual; + grub_usb_err_t err; + + 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_read (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data) { - return grub_usb_bulk_readwrite (dev, endpoint, size, data, - GRUB_USB_TRANSFER_TYPE_IN); + 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 +grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) +{ + grub_usb_err_t err; + grub_usb_device_t dev = transfer->dev; + + err = dev->controller.dev->check_transfer (&dev->controller, transfer, + actual); + if (err == GRUB_USB_ERR_WAIT) + return err; + + grub_usb_bulk_finish_readwrite (transfer); + + return err; +} + +grub_usb_transfer_t +grub_usb_bulk_read_background (grub_usb_device_t dev, + int endpoint, grub_size_t size, void *data) +{ + grub_usb_err_t err; + grub_usb_transfer_t transfer; + + transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size, + data, GRUB_USB_TRANSFER_TYPE_IN); + if (!transfer) + return NULL; + + err = dev->controller.dev->setup_transfer (&dev->controller, transfer); + if (err) + return NULL; + + return transfer; +} + +void +grub_usb_cancel_transfer (grub_usb_transfer_t transfer) +{ + grub_usb_device_t dev = transfer->dev; + dev->controller.dev->cancel_transfer (&dev->controller, transfer); + grub_errno = GRUB_ERR_NONE; +} + +grub_usb_err_t +grub_usb_bulk_read_extended (grub_usb_device_t dev, + int endpoint, grub_size_t size, char *data, + int timeout, grub_size_t *actual) +{ + return grub_usb_bulk_readwrite (dev, endpoint, size, data, + GRUB_USB_TRANSFER_TYPE_IN, timeout, actual); } diff --git a/commands/acpi.c b/grub-core/commands/acpi.c similarity index 97% rename from commands/acpi.c rename to grub-core/commands/acpi.c index 884ddf000..4f03997e0 100644 --- a/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -23,10 +23,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -152,10 +150,10 @@ grub_acpi_create_ebda (void) 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_uint32_t type) + grub_memory_type_t type) { grub_uint64_t end = start + size; - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (end > 0x100000) end = 0x100000; @@ -181,7 +179,7 @@ grub_acpi_create_ebda (void) "couldn't find space for the new EBDA"); mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len, - GRUB_MACHINE_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -325,7 +323,7 @@ setup_common_tables (void) /* If it's FADT correct DSDT and FACS addresses. */ fadt = (struct grub_acpi_fadt *) cur->addr; - if (grub_memcmp (fadt->hdr.signature, "FACP", + if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, sizeof (fadt->hdr.signature)) == 0) { fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); @@ -458,10 +456,9 @@ free_tables (void) } static grub_err_t -grub_cmd_acpi (struct grub_extcmd *cmd, - int argc, char **args) +grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; struct grub_acpi_rsdp_v10 *rsdp; struct efiemu_acpi_table *cur, *t; grub_err_t err; @@ -529,7 +526,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable; /* Set root header variables to the same values - as FACP by default. */ + as FADT by default. */ grub_memcpy (&root_oemid, &(fadt->hdr.oemid), sizeof (root_oemid)); grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable), @@ -629,7 +626,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, grub_size_t size; char *buf; - file = grub_gzfile_open (args[i], 1); + file = grub_file_open (args[i]); if (! file) { free_tables (); @@ -706,7 +703,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, playground = playground_ptr = grub_mmap_malign_and_register (1, playground_size, &mmapregion, - GRUB_MACHINE_MEMORY_ACPI, 0); + GRUB_MEMORY_ACPI, 0); if (! playground) { @@ -760,8 +757,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(acpi) { - cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0, N_("[-1|-2] [--exclude=TABLE1,TABLE2|" "--load-only=table1,table2] FILE1" " [FILE2] [...]"), diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c new file mode 100644 index 000000000..2789e2eca --- /dev/null +++ b/grub-core/commands/acpihalt.c @@ -0,0 +1,329 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#ifdef GRUB_DSDT_TEST +#include +#include +#include +#include +#include + +#define grub_dprintf(cond, args...) printf ( args ) +#define grub_printf printf +typedef uint64_t grub_uint64_t; +typedef uint32_t grub_uint32_t; +typedef uint16_t grub_uint16_t; +typedef uint8_t grub_uint8_t; + +#endif + +#include + +#ifndef GRUB_DSDT_TEST +#include +#include +#endif + +static inline grub_uint32_t +decode_length (const grub_uint8_t *ptr, int *numlen) +{ + int num_bytes, i; + grub_uint32_t ret; + if (*ptr < 64) + { + if (numlen) + *numlen = 1; + return *ptr; + } + num_bytes = *ptr >> 6; + if (numlen) + *numlen = num_bytes + 1; + ret = *ptr & 0xf; + ptr++; + for (i = 0; i < num_bytes; i++) + { + ret |= *ptr << (8 * i + 4); + ptr++; + } + return ret; +} + +static inline grub_uint32_t +skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + + while (ptr < end && (*ptr == '^' || *ptr == '\\')) + ptr++; + switch (*ptr) + { + case '.': + ptr++; + ptr += 8; + break; + case '/': + ptr++; + ptr += 1 + (*ptr) * 4; + break; + case 0: + ptr++; + break; + default: + ptr += 4; + break; + } + return ptr - ptr0; +} + +static inline grub_uint32_t +skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + grub_dprintf ("acpi", "data type = 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_PACKAGE: + return 1 + decode_length (ptr + 1, 0); + case GRUB_ACPI_OPCODE_ZERO: + case GRUB_ACPI_OPCODE_ONES: + case GRUB_ACPI_OPCODE_ONE: + return 1; + case GRUB_ACPI_OPCODE_BYTE_CONST: + return 2; + case GRUB_ACPI_OPCODE_WORD_CONST: + return 3; + case GRUB_ACPI_OPCODE_DWORD_CONST: + return 5; + default: + if (*ptr == '^' || *ptr == '\\' || *ptr == '_' + || (*ptr >= 'A' && *ptr <= 'Z')) + return skip_name_string (ptr, end); + grub_printf ("Unknown opcode 0x%x\n", *ptr); + return 0; + } +} + +static inline grub_uint32_t +skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + int add; + grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_EXTOPCODE_MUTEX: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + break; + case GRUB_ACPI_EXTOPCODE_OPERATION_REGION: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return 0; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return 0; + break; + case GRUB_ACPI_EXTOPCODE_FIELD_OP: + case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP: + ptr++; + ptr += decode_length (ptr, 0); + break; + default: + grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr); + return 0; + } + return ptr - ptr0; +} + +static int +get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) +{ + grub_uint8_t *ptr, *prev = table; + int sleep_type = -1; + + ptr = table + sizeof (struct grub_acpi_table_header); + while (ptr < end && prev < ptr) + { + int add; + prev = ptr; + grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr); + grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table)); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_EXTOP: + ptr++; + ptr += add = skip_ext_op (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_NAME: + ptr++; + if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0) + { + int ll; + grub_uint8_t *ptr2 = ptr; + grub_dprintf ("acpi", "S5 found\n"); + ptr2 += skip_name_string (ptr, end); + if (*ptr2 != 0x12) + { + grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2); + return -1; + } + ptr2++; + decode_length (ptr2, &ll); + ptr2 += ll; + ptr2++; + switch (*ptr2) + { + case GRUB_ACPI_OPCODE_ZERO: + sleep_type = 0; + break; + case GRUB_ACPI_OPCODE_ONE: + sleep_type = 1; + break; + case GRUB_ACPI_OPCODE_BYTE_CONST: + sleep_type = ptr2[1]; + break; + default: + grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); + return -1; + } + } + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_SCOPE: + case GRUB_ACPI_OPCODE_IF: + case GRUB_ACPI_OPCODE_METHOD: + { + ptr++; + ptr += decode_length (ptr, 0); + break; + } + } + } + + grub_dprintf ("acpi", "TYP = %d\n", sleep_type); + return sleep_type; +} + +#ifdef GRUB_DSDT_TEST +int +main (int argc, char **argv) +{ + FILE *f; + size_t len; + unsigned char *buf; + if (argc < 2) + printf ("Usage: %s FILE\n", argv[0]); + f = fopen (argv[1], "rb"); + if (!f) + { + printf ("Couldn't open file\n"); + return 1; + } + fseek (f, 0, SEEK_END); + len = ftell (f); + fseek (f, 0, SEEK_SET); + buf = malloc (len); + if (!buf) + { + printf ("Couldn't malloc buffer\n"); + fclose (f); + return 2; + } + if (fread (buf, 1, len, f) != len) + { + printf ("Read failed\n"); + free (buf); + fclose (f); + return 2; + } + + printf ("Sleep type = %d\n", get_sleep_type (buf, buf + len)); + free (buf); + fclose (f); + return 0; +} + +#else + +void +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; + + rsdp2 = grub_acpi_get_rsdpv2 (); + if (rsdp2) + rsdp1 = &(rsdp2->rsdpv1); + else + rsdp1 = grub_acpi_get_rsdpv1 (); + grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1); + if (!rsdp1) + return; + + rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr; + for (entry_ptr = (grub_uint32_t *) (rsdt + 1); + entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) + + rsdt->length); + entry_ptr++) + { + if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0) + { + grub_uint32_t port; + struct grub_acpi_fadt *fadt + = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr); + struct grub_acpi_table_header *dsdt + = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr; + int sleep_type = -1; + + port = fadt->pm1a; + + grub_dprintf ("acpi", "PM1a port=%x\n", port); + + if (grub_memcmp (dsdt->signature, "DSDT", + sizeof (dsdt->signature)) != 0) + break; + + sleep_type = get_sleep_type ((grub_uint8_t *) dsdt, + (grub_uint8_t *) dsdt + dsdt->length); + + 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_printf ("ACPI shutdown failed\n"); +} +#endif diff --git a/commands/blocklist.c b/grub-core/commands/blocklist.c similarity index 98% rename from commands/blocklist.c rename to grub-core/commands/blocklist.c index cace31113..4651fb32a 100644 --- a/commands/blocklist.c +++ b/grub-core/commands/blocklist.c @@ -82,6 +82,7 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + grub_file_filter_disable_compression (); file = grub_file_open (args[0]); if (! file) return grub_errno; diff --git a/commands/boot.c b/grub-core/commands/boot.c similarity index 100% rename from commands/boot.c rename to grub-core/commands/boot.c diff --git a/commands/cat.c b/grub-core/commands/cat.c similarity index 88% rename from commands/cat.c rename to grub-core/commands/cat.c index 77a4cc793..79ecf75c7 100644 --- a/commands/cat.c +++ b/grub-core/commands/cat.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -33,9 +32,9 @@ static const struct grub_arg_option options[] = }; static grub_err_t -grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int dos = 0; grub_file_t file; char buf[GRUB_DISK_SECTOR_SIZE]; @@ -48,7 +47,7 @@ grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args) if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - file = grub_gzfile_open (args[0], 1); + file = grub_file_open (args[0]); if (! file) return grub_errno; @@ -77,7 +76,7 @@ grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args) } while (grub_checkkey () >= 0 && - (key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC) + (key = grub_getkey ()) != GRUB_TERM_ESC) ; } @@ -92,7 +91,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(cat) { - cmd = grub_register_extcmd ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("cat", grub_cmd_cat, 0, N_("FILE"), N_("Show the contents of a file."), options); } diff --git a/commands/cmp.c b/grub-core/commands/cmp.c similarity index 96% rename from commands/cmp.c rename to grub-core/commands/cmp.c index 626e1d022..d9e76a4d7 100644 --- a/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -44,8 +43,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), grub_printf ("Compare file `%s' with `%s':\n", args[0], args[1]); - file1 = grub_gzfile_open (args[0], 1); - file2 = grub_gzfile_open (args[1], 1); + file1 = grub_file_open (args[0]); + file2 = grub_file_open (args[1]); if (! file1 || ! file2) goto cleanup; diff --git a/commands/configfile.c b/grub-core/commands/configfile.c similarity index 66% rename from commands/configfile.c rename to grub-core/commands/configfile.c index 469447711..2568b7ee6 100644 --- a/commands/configfile.c +++ b/grub-core/commands/configfile.c @@ -27,28 +27,34 @@ static grub_err_t grub_cmd_source (grub_command_t cmd, int argc, char **args) { - int new_env; + int new_env, extractor; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - new_env = (cmd->name[0] == 'c'); + extractor = (cmd->name[0] == 'e'); + new_env = (cmd->name[extractor ? sizeof ("extract_entries_") - 1 : 0] == 'c'); if (new_env) - { - grub_cls (); - grub_env_context_open (1); - } + grub_cls (); + + if (new_env && !extractor) + grub_env_context_open (); + if (extractor) + grub_env_extractor_open (!new_env); grub_normal_execute (args[0], 1, ! new_env); - if (new_env) + if (new_env && !extractor) grub_env_context_close (); + if (extractor) + grub_env_extractor_close (!new_env); return 0; } static grub_command_t cmd_configfile, cmd_source, cmd_dot; +static grub_command_t cmd_extractor_source, cmd_extractor_configfile; GRUB_MOD_INIT(configfile) { @@ -60,6 +66,19 @@ GRUB_MOD_INIT(configfile) N_("FILE"), N_("Load another config file without changing context.") ); + + cmd_extractor_source = + grub_register_command ("extract_entries_source", grub_cmd_source, + N_("FILE"), + N_("Load another config file without changing context but take only menuentries.") + ); + + cmd_extractor_configfile = + grub_register_command ("extract_entries_configfile", grub_cmd_source, + N_("FILE"), + N_("Load another config file without changing context but take only menuentries.") + ); + cmd_dot = grub_register_command (".", grub_cmd_source, N_("FILE"), @@ -71,5 +90,7 @@ GRUB_MOD_FINI(configfile) { grub_unregister_command (cmd_configfile); grub_unregister_command (cmd_source); + grub_unregister_command (cmd_extractor_configfile); + grub_unregister_command (cmd_extractor_source); grub_unregister_command (cmd_dot); } diff --git a/commands/date.c b/grub-core/commands/date.c similarity index 100% rename from commands/date.c rename to grub-core/commands/date.c diff --git a/commands/echo.c b/grub-core/commands/echo.c similarity index 90% rename from commands/echo.c rename to grub-core/commands/echo.c index 4fea091cb..13bc1c3fd 100644 --- a/commands/echo.c +++ b/grub-core/commands/echo.c @@ -30,9 +30,9 @@ static const struct grub_arg_option options[] = }; static grub_err_t -grub_cmd_echo (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int newline = 1; int i; @@ -113,7 +113,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(echo) { - cmd = grub_register_extcmd ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("echo", grub_cmd_echo, + GRUB_COMMAND_ACCEPT_DASH + | GRUB_COMMAND_OPTIONS_AT_START, N_("[-e|-n] STRING"), N_("Display a line of text."), options); } diff --git a/commands/efi/acpi.c b/grub-core/commands/efi/acpi.c similarity index 100% rename from commands/efi/acpi.c rename to grub-core/commands/efi/acpi.c diff --git a/commands/efi/fixvideo.c b/grub-core/commands/efi/fixvideo.c similarity index 100% rename from commands/efi/fixvideo.c rename to grub-core/commands/efi/fixvideo.c diff --git a/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c similarity index 100% rename from commands/efi/loadbios.c rename to grub-core/commands/efi/loadbios.c diff --git a/grub-core/commands/efi/lsefimmap.c b/grub-core/commands/efi/lsefimmap.c new file mode 100644 index 000000000..2bb5dcb5d --- /dev/null +++ b/grub-core/commands/efi/lsefimmap.c @@ -0,0 +1,143 @@ +/* lsefimemmap.c - Display memory map. */ +/* + * 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 + +#define ADD_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) + +static grub_err_t +grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_uintn_t map_size; + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; + grub_efi_memory_descriptor_t *desc; + grub_efi_uintn_t desc_size; + + map_size = 0; + if (grub_efi_get_memory_map (&map_size, NULL, NULL, &desc_size, 0) < 0) + return 0; + + memory_map = grub_malloc (map_size); + if (memory_map == NULL) + return grub_errno; + if (grub_efi_get_memory_map (&map_size, memory_map, NULL, &desc_size, 0) <= 0) + goto fail; + + grub_printf + ("Type Physical start - end #Pages " + " Size Attributes\n"); + memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size); + for (desc = memory_map; + desc < memory_map_end; + desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) + { + grub_efi_uint64_t size; + grub_efi_uint64_t attr; + static const char types_str[][9] = + { + "reserved", + "ldr-code", + "ldr-data", + "BS-code ", + "BS-data ", + "RT-code ", + "RT-data ", + "conv-mem", + "unusable", + "ACPI-rec", + "ACPI-nvs", + "MMIO ", + "IO-ports", + "PAL-code" + }; + if (desc->type < ARRAY_SIZE (types_str)) + grub_printf ("%s ", types_str[desc->type]); + else + grub_printf ("Unk %02x ", desc->type); + + grub_printf (" %016" PRIxGRUB_UINT64_T "-%016" PRIxGRUB_UINT64_T + " %08" PRIxGRUB_UINT64_T, + desc->physical_start, + desc->physical_start + (desc->num_pages << 12) - 1, + desc->num_pages); + + size = desc->num_pages; + size <<= (12 - 10); + if (size < 1024) + grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size); + else + { + size /= 1024; + if (size < 1024) + grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size); + else + { + size /= 1024; + grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size); + } + } + + attr = desc->attribute; + if (attr & GRUB_EFI_MEMORY_RUNTIME) + grub_printf (" RT"); + if (attr & GRUB_EFI_MEMORY_UC) + grub_printf (" UC"); + if (attr & GRUB_EFI_MEMORY_WC) + grub_printf (" WC"); + if (attr & GRUB_EFI_MEMORY_WT) + grub_printf (" WT"); + if (attr & GRUB_EFI_MEMORY_WB) + grub_printf (" WB"); + if (attr & GRUB_EFI_MEMORY_UCE) + grub_printf (" UCE"); + if (attr & GRUB_EFI_MEMORY_WP) + grub_printf (" WP"); + if (attr & GRUB_EFI_MEMORY_RP) + grub_printf (" RP"); + if (attr & GRUB_EFI_MEMORY_XP) + grub_printf (" XP"); + + grub_printf ("\n"); + } + + fail: + grub_free (memory_map); + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsefimmap) +{ + cmd = grub_register_command ("lsefimmap", grub_cmd_lsefimmap, + "", "Display EFI memory map."); +} + +GRUB_MOD_FINI(lsefimmap) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c new file mode 100644 index 000000000..aa3e05aee --- /dev/null +++ b/grub-core/commands/efi/lsefisystab.c @@ -0,0 +1,107 @@ +/* lsefisystab.c - Display EFI systab. */ +/* + * 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 + +struct guid_mapping +{ + grub_efi_guid_t guid; + const char *name; +}; + +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_SAL_TABLE_GUID, "SAL"}, + { GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"}, + { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, + { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"} + }; + +static grub_err_t +grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t; + unsigned int i; + + grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n", + st->hdr.signature, st->hdr.revision); + { + char *vendor; + grub_uint16_t *vendor_utf16; + grub_printf ("Vendor: "); + + for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++); + vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1); + if (!vendor) + return grub_errno; + *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, + vendor_utf16 - st->firmware_vendor) = 0; + grub_printf ("%s", vendor); + grub_free (vendor); + } + + grub_printf (", Version=%x\n", st->firmware_revision); + + grub_printf ("%ld tables:\n", st->num_table_entries); + t = st->configuration_table; + for (i = 0; i < st->num_table_entries; i++) + { + unsigned int j; + + grub_printf ("%p ", t->vendor_table); + + grub_printf ("%08x-%04x-%04x-", + t->vendor_guid.data1, t->vendor_guid.data2, + t->vendor_guid.data3); + for (j = 0; j < 8; j++) + grub_printf ("%02x", t->vendor_guid.data4[j]); + + for (j = 0; j < ARRAY_SIZE (guid_mappings); j++) + if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + grub_printf (" %s", guid_mappings[j].name); + + grub_printf ("\n"); + t++; + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsefisystab) +{ + cmd = grub_register_command ("lsefisystab", grub_cmd_lsefisystab, + "", "Display EFI system tables."); +} + +GRUB_MOD_FINI(lsefisystab) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/lssal.c b/grub-core/commands/efi/lssal.c new file mode 100644 index 000000000..2ee993033 --- /dev/null +++ b/grub-core/commands/efi/lssal.c @@ -0,0 +1,162 @@ +/* lssal.c - Display EFI SAL systab. */ +/* + * 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 + +static void +disp_sal (void *table) +{ + struct grub_efi_sal_system_table *t = table; + void *desc; + grub_uint32_t len, l; + + grub_printf ("SAL rev: %02x, signature: %x, len:%x\n", + t->sal_rev, t->signature, t->total_table_len); + grub_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n", + t->entry_count, t->checksum, + t->sal_a_version, t->sal_b_version); + grub_printf ("OEM-ID: %-32s\n", t->oem_id); + grub_printf ("Product-ID: %-32s\n", t->product_id); + + desc = t->entries; + len = t->total_table_len - sizeof (struct grub_efi_sal_system_table); + while (len > 0) + { + switch (*(grub_uint8_t *) desc) + { + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR: + { + struct grub_efi_sal_system_table_entrypoint_descriptor *c = desc; + l = sizeof (*c); + grub_printf (" Entry point: PAL=%016" PRIxGRUB_UINT64_T + " SAL=%016" PRIxGRUB_UINT64_T " GP=%016" + PRIxGRUB_UINT64_T "\n", + c->pal_proc_addr, c->sal_proc_addr, + c->global_data_ptr); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR: + { + struct grub_efi_sal_system_table_memory_descriptor *c = desc; + l = sizeof (*c); + grub_printf (" Memory descriptor entry addr=%016" PRIxGRUB_UINT64_T + " len=%" PRIuGRUB_UINT64_T "KB\n", + c->addr, c->len * 4); + grub_printf (" sal_used=%d attr=%x AR=%x attr_mask=%x " + "type=%x usage=%x\n", + c->sal_used, c->attr, c->ar, c->attr_mask, c->mem_type, + c->usage); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES: + { + struct grub_efi_sal_system_table_platform_features *c = desc; + l = sizeof (*c); + grub_printf (" Platform features: %02x", c->flags); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK) + grub_printf (" BusLock"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT) + grub_printf (" IrqRedirect"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT) + + grub_printf (" IPIRedirect"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT) + + grub_printf (" ITCDrift"); + grub_printf ("\n"); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR: + { + struct grub_efi_sal_system_table_translation_register_descriptor *c + = desc; + l = sizeof (*c); + grub_printf (" TR type=%d num=%d va=%016" PRIxGRUB_UINT64_T + " pte=%016" PRIxGRUB_UINT64_T "\n", + c->register_type, c->register_number, + c->addr, c->page_size); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE: + { + struct grub_efi_sal_system_table_purge_translation_coherence *c + = desc; + l = sizeof (*c); + grub_printf (" PTC coherence nbr=%d addr=%016" PRIxGRUB_UINT64_T "\n", + c->ndomains, c->coherence); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP: + { + struct grub_efi_sal_system_table_ap_wakeup *c = desc; + l = sizeof (*c); + grub_printf (" AP wake-up: mec=%d vect=%" PRIxGRUB_UINT64_T "\n", + c->mechanism, c->vector); + } + break; + default: + grub_printf (" unknown entry 0x%x\n", *(grub_uint8_t *)desc); + return; + } + desc = (grub_uint8_t *)desc + l; + len -= l; + } +} + +static grub_err_t +grub_cmd_lssal (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t = st->configuration_table; + unsigned int i; + grub_efi_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; + + for (i = 0; i < st->num_table_entries; i++) + { + if (grub_memcmp (&guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + { + disp_sal (t->vendor_table); + return GRUB_ERR_NONE; + } + t++; + } + grub_printf ("SAL not found\n"); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lssal) +{ + cmd = grub_register_command ("lssal", grub_cmd_lssal, "", + "Display SAL system table."); +} + +GRUB_MOD_FINI(lssal) +{ + grub_unregister_command (cmd); +} diff --git a/commands/extcmd.c b/grub-core/commands/extcmd.c similarity index 59% rename from commands/extcmd.c rename to grub-core/commands/extcmd.c index 16796febf..e9274fbab 100644 --- a/commands/extcmd.c +++ b/grub-core/commands/extcmd.c @@ -21,46 +21,55 @@ #include #include #include +#include -static grub_err_t -grub_extcmd_dispatcher (struct grub_command *cmd, - int argc, char **args) +grub_err_t +grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, + struct grub_script *script) { int new_argc; char **new_args; - struct grub_arg_option *parser; struct grub_arg_list *state; - int maxargs = 0; + struct grub_extcmd_context context; grub_err_t ret; - grub_extcmd_t ext; + grub_extcmd_t ext = cmd->data; - ext = cmd->data; - parser = (struct grub_arg_option *) ext->options; - while (parser && (parser++)->doc) - maxargs++; + context.state = 0; + context.extcmd = ext; + context.script = script; - /* Set up the option state. */ - state = grub_zalloc (sizeof (struct grub_arg_list) * maxargs); + if (! ext->options) + { + ret = (ext->func) (&context, argc, args); + return ret; + } + state = grub_arg_list_alloc (ext, argc, args); if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) { - ext->state = state; - ret = (ext->func) (ext, new_argc, new_args); + context.state = state; + ret = (ext->func) (&context, new_argc, new_args); grub_free (new_args); + grub_free (state); + return ret; } - else - ret = grub_errno; grub_free (state); + return grub_errno; +} - return ret; +static grub_err_t +grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args) +{ + return grub_extcmd_dispatcher (cmd, argc, args, 0); } grub_extcmd_t -grub_register_extcmd (const char *name, grub_extcmd_func_t func, - unsigned flags, const char *summary, - const char *description, - const struct grub_arg_option *parser) +grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, + grub_command_flags_t flags, const char *summary, + const char *description, + const struct grub_arg_option *parser, + int prio) { grub_extcmd_t ext; grub_command_t cmd; @@ -69,8 +78,8 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func, if (! ext) return 0; - cmd = grub_register_command_prio (name, grub_extcmd_dispatcher, - summary, description, 1); + cmd = grub_register_command_prio (name, grub_extcmd_dispatch, + summary, description, prio); if (! cmd) { grub_free (ext); @@ -88,6 +97,16 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func, return ext; } +grub_extcmd_t +grub_register_extcmd (const char *name, grub_extcmd_func_t func, + grub_command_flags_t flags, const char *summary, + const char *description, + const struct grub_arg_option *parser) +{ + return grub_register_extcmd_prio (name, func, flags, + summary, description, parser, 1); +} + void grub_unregister_extcmd (grub_extcmd_t ext) { diff --git a/commands/gptsync.c b/grub-core/commands/gptsync.c similarity index 100% rename from commands/gptsync.c rename to grub-core/commands/gptsync.c diff --git a/commands/halt.c b/grub-core/commands/halt.c similarity index 100% rename from commands/halt.c rename to grub-core/commands/halt.c diff --git a/commands/hashsum.c b/grub-core/commands/hashsum.c similarity index 81% rename from commands/hashsum.c rename to grub-core/commands/hashsum.c index d5f551dbb..8b6806e45 100644 --- a/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -32,6 +32,7 @@ static const struct grub_arg_option options[] = { {"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIRECTORY"), ARG_TYPE_STRING}, {"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0}, + {"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -39,7 +40,9 @@ struct { const char *name; const char *hashname; } aliases[] = { {"sha256sum", "sha256"}, {"sha512sum", "sha512"}, + {"sha1sum", "sha1"}, {"md5sum", "md5"}, + {"crc", "crc32"}, }; static inline int @@ -80,7 +83,7 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) static grub_err_t check_list (const gcry_md_spec_t *hash, const char *hashfilename, - const char *prefix, int keep) + const char *prefix, int keep, int uncompress) { grub_file_t hashlist, file; char *buf = NULL; @@ -115,11 +118,17 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, filename = grub_xasprintf ("%s/%s", prefix, p); if (!filename) return grub_errno; + if (!uncompress) + grub_file_filter_disable_compression (); file = grub_file_open (filename); grub_free (filename); } else - file = grub_file_open (p); + { + if (!uncompress) + grub_file_filter_disable_compression (); + file = grub_file_open (p); + } if (!file) { grub_file_close (hashlist); @@ -165,19 +174,20 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, } static grub_err_t -grub_cmd_hashsum (struct grub_extcmd *cmd, +grub_cmd_hashsum (struct grub_extcmd_context *ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; const char *hashname = NULL; const char *prefix = NULL; const gcry_md_spec_t *hash; unsigned i; int keep = state[3].set; + int uncompress = state[4].set; unsigned unread = 0; for (i = 0; i < ARRAY_SIZE (aliases); i++) - if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0) + if (grub_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0) hashname = aliases[i].hashname; if (state[0].set) hashname = state[0].arg; @@ -197,7 +207,7 @@ grub_cmd_hashsum (struct grub_extcmd *cmd, if (argc != 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "--check is incompatible with file list"); - return check_list (hash, state[1].arg, prefix, keep); + return check_list (hash, state[1].arg, prefix, keep, uncompress); } for (i = 0; i < (unsigned) argc; i++) @@ -206,6 +216,8 @@ grub_cmd_hashsum (struct grub_extcmd *cmd, grub_file_t file; grub_err_t err; unsigned j; + if (!uncompress) + grub_file_filter_disable_compression (); file = grub_file_open (args[i]); if (!file) { @@ -238,30 +250,37 @@ grub_cmd_hashsum (struct grub_extcmd *cmd, return GRUB_ERR_NONE; } -static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512; +static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc; GRUB_MOD_INIT(hashsum) { - cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0, "hashsum -h HASH [-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]", - "Compute or check hash checksum.", + N_("Compute or check hash checksum."), options); - cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), options); - cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_sha1 = grub_register_extcmd ("sha1sum", grub_cmd_hashsum, 0, + N_("[-c FILE [-p PREFIX]] " + "[FILE1 [FILE2 ...]]"), + N_("Compute or check hash checksum."), + options); + cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), - "Compute or check hash checksum.", + N_("Compute or check hash checksum."), options); - cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, 0, + N_("[-c FILE [-p PREFIX]] " + "[FILE1 [FILE2 ...]]"), + N_("Compute or check hash checksum."), + options); + + cmd_crc = grub_register_extcmd ("crc", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), @@ -272,6 +291,8 @@ GRUB_MOD_FINI(hashsum) { grub_unregister_extcmd (cmd); grub_unregister_extcmd (cmd_md5); + grub_unregister_extcmd (cmd_sha1); grub_unregister_extcmd (cmd_sha256); grub_unregister_extcmd (cmd_sha512); + grub_unregister_extcmd (cmd_crc); } diff --git a/commands/hdparm.c b/grub-core/commands/hdparm.c similarity index 98% rename from commands/hdparm.c rename to grub-core/commands/hdparm.c index a3f8bbff0..b6ab78755 100644 --- a/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -270,9 +270,9 @@ static int get_int_arg (const struct grub_arg_list *state) } static grub_err_t -grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? +grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; /* Check command line. */ if (argc != 1) @@ -409,8 +409,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hdparm) { - cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0, N_("[OPTIONS] DISK"), N_("Get/set ATA disk parameters."), options); } diff --git a/commands/help.c b/grub-core/commands/help.c similarity index 91% rename from commands/help.c rename to grub-core/commands/help.c index e7d108c33..ff6d7ed2e 100644 --- a/commands/help.c +++ b/grub-core/commands/help.c @@ -27,7 +27,7 @@ #include static grub_err_t -grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, +grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char **args) { int cnt = 0; @@ -38,8 +38,7 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, grub_command_t cmd; FOR_COMMANDS(cmd) { - if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && - (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) + if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)) { struct grub_term_output *term; const char *summary_translated = _(cmd->summary); @@ -112,7 +111,8 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, if (cnt++ > 0) grub_printf ("\n\n"); - if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) + if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) && + ! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD)) grub_arg_show_help ((grub_extcmd_t) cmd->data); else grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary), @@ -130,8 +130,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(help) { - cmd = grub_register_extcmd ("help", grub_cmd_help, - GRUB_COMMAND_FLAG_CMDLINE, + cmd = grub_register_extcmd ("help", grub_cmd_help, 0, N_("[PATTERN ...]"), N_("Show a help message."), 0); } diff --git a/commands/hexdump.c b/grub-core/commands/hexdump.c similarity index 92% rename from commands/hexdump.c rename to grub-core/commands/hexdump.c index c1d4ecba9..629f2a069 100644 --- a/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -34,9 +33,9 @@ static const struct grub_arg_option options[] = { }; static grub_err_t -grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; char buf[GRUB_DISK_SECTOR_SIZE * 4]; grub_ssize_t size, length; grub_disk_addr_t skip; @@ -89,7 +88,7 @@ grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args) { grub_file_t file; - file = grub_gzfile_open (args[0], 1); + file = grub_file_open (args[0]); if (! file) return 0; @@ -120,8 +119,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (hexdump) { - cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, 0, N_("[OPTIONS] FILE_OR_DEVICE"), N_("Dump the contents of a file or memory."), options); diff --git a/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c similarity index 64% rename from commands/i386/cmostest.c rename to grub-core/commands/i386/cmostest.c index 36c35e6c4..994da11b0 100644 --- a/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -22,20 +22,32 @@ #include static grub_err_t -grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) +parse_args (int argc, char *argv[], int *byte, int *bit) { - int byte, bit; char *rest; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); - byte = grub_strtoul (argv[0], &rest, 0); + *byte = grub_strtoul (argv[0], &rest, 0); if (*rest != ':') return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); - bit = grub_strtoul (rest + 1, 0, 0); + *bit = grub_strtoul (rest + 1, 0, 0); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; if (grub_cmos_read (byte) & (1 << bit)) return GRUB_ERR_NONE; @@ -43,7 +55,22 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_TEST_FAILURE, "false"); } -static grub_command_t cmd; +static grub_err_t +grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + + grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit))); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd, cmd_clean; GRUB_MOD_INIT(cmostest) @@ -51,9 +78,13 @@ GRUB_MOD_INIT(cmostest) cmd = grub_register_command ("cmostest", grub_cmd_cmostest, "cmostest BYTE:BIT", "Test bit at BYTE:BIT in CMOS."); + cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, + "cmosclean BYTE:BIT", + "Clean bit at BYTE:BIT in CMOS."); } GRUB_MOD_FINI(cmostest) { grub_unregister_command (cmd); + grub_unregister_command (cmd_clean); } diff --git a/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c similarity index 94% rename from commands/i386/cpuid.c rename to grub-core/commands/i386/cpuid.c index 6eebf91a1..f5f0f15a8 100644 --- a/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -43,7 +43,7 @@ static const struct grub_arg_option options[] = unsigned char grub_cpuid_has_longmode = 0; static grub_err_t -grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)), +grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { @@ -88,7 +88,7 @@ GRUB_MOD_INIT(cpuid) done: #endif - cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, 0, "[-l]", N_("Check for CPU features."), options); } diff --git a/commands/i386/pc/acpi.c b/grub-core/commands/i386/pc/acpi.c similarity index 100% rename from commands/i386/pc/acpi.c rename to grub-core/commands/i386/pc/acpi.c diff --git a/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c similarity index 96% rename from commands/i386/pc/drivemap.c rename to grub-core/commands/i386/pc/drivemap.c index 4afc43358..ed4211cca 100644 --- a/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -24,9 +24,10 @@ #include #include #include -#include #include #include +#include +#include /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ @@ -196,13 +197,13 @@ list_mappings (void) } static grub_err_t -grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) +grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args) { - if (cmd->state[OPTIDX_LIST].set) + if (ctxt->state[OPTIDX_LIST].set) { return list_mappings (); } - else if (cmd->state[OPTIDX_RESET].set) + else if (ctxt->state[OPTIDX_RESET].set) { /* Reset: just delete all mappings, freeing their memory. */ drivemap_node_t *curnode = map_head; @@ -216,7 +217,7 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) map_head = 0; return GRUB_ERR_NONE; } - else if (!cmd->state[OPTIDX_SWAP].set && argc == 0) + else if (!ctxt->state[OPTIDX_SWAP].set && argc == 0) { /* No arguments */ return list_mappings (); @@ -248,11 +249,11 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) } /* Set the mapping for the disk (overwrites any existing mapping). */ grub_dprintf ("drivemap", "%s %s (%02x) = %s (%02x)\n", - cmd->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping", + ctxt->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping", args[1], mapto, args[0], mapfrom); err = drivemap_set (mapto, mapfrom); /* If -s, perform the reverse mapping too (only if the first was OK). */ - if (cmd->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE) + if (ctxt->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE) err = drivemap_set (mapfrom, mapto); return err; } @@ -306,7 +307,7 @@ install_int13_handler (int noret __attribute__ ((unused))) grub_dprintf ("drivemap", "Payload is %u bytes long\n", total_size); handler_base = grub_mmap_malign_and_register (16, total_size, &drivemap_mmap, - GRUB_MACHINE_MEMORY_RESERVED, + GRUB_MEMORY_RESERVED, GRUB_MMAP_MALLOC_LOW); if (! handler_base) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't reserve " @@ -401,8 +402,7 @@ GRUB_MOD_INIT (drivemap) { grub_get_root_biosnumber_saved = grub_get_root_biosnumber; grub_get_root_biosnumber = grub_get_root_biosnumber_drivemap; - cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, 0, N_("-l | -r | [-s] grubdev osdisk."), N_("Manage the BIOS drive mappings."), options); diff --git a/commands/i386/pc/drivemap_int13h.S b/grub-core/commands/i386/pc/drivemap_int13h.S similarity index 100% rename from commands/i386/pc/drivemap_int13h.S rename to grub-core/commands/i386/pc/drivemap_int13h.S diff --git a/grub-core/commands/i386/pc/halt.c b/grub-core/commands/i386/pc/halt.c new file mode 100644 index 000000000..81eb6a1bb --- /dev/null +++ b/grub-core/commands/i386/pc/halt.c @@ -0,0 +1,125 @@ +/* halt.c - command to halt the computer. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,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 + +static const struct grub_arg_option options[] = + { + {"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static inline void __attribute__ ((noreturn)) +stop (void) +{ + while (1) + { + asm volatile ("hlt"); + } +} +/* + * Halt the system, using APM if possible. If NO_APM is true, don't use + * APM even if it is available. + */ +void +grub_halt (int no_apm) +{ + struct grub_bios_int_registers regs; + + grub_acpi_halt (); + + if (no_apm) + stop (); + + /* detect APM */ + regs.eax = 0x5300; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + stop (); + + /* disconnect APM first */ + regs.eax = 0x5304; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + /* connect APM */ + regs.eax = 0x5301; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + stop (); + + /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */ + regs.eax = 0x530E; + regs.ebx = 0; + regs.ecx = 0x0101; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + stop (); + + /* set the power state to off */ + regs.eax = 0x5307; + regs.ebx = 1; + regs.ecx = 3; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + /* shouldn't reach here */ + stop (); +} + +static grub_err_t +grub_cmd_halt (grub_extcmd_context_t ctxt, + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) + +{ + struct grub_arg_list *state = ctxt->state; + int no_apm = 0; + + if (state[0].set) + no_apm = 1; + grub_halt (no_apm); + return 0; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(halt) +{ + cmd = grub_register_extcmd ("halt", grub_cmd_halt, 0, "[-n]", + N_("Halt the system, if possible using APM."), + options); +} + +GRUB_MOD_FINI(halt) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c new file mode 100644 index 000000000..30475d2ec --- /dev/null +++ b/grub-core/commands/i386/pc/lsapm.c @@ -0,0 +1,113 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include + +int +grub_apm_get_info (struct grub_apm_info *info) +{ + struct grub_bios_int_registers regs; + + /* detect APM */ + regs.eax = 0x5300; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + info->version = regs.eax & 0xffff; + info->flags = regs.ecx & 0xffff; + + /* disconnect APM first */ + regs.eax = 0x5304; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + /* connect APM */ + regs.eax = 0x5303; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + + info->cseg = regs.eax & 0xffff; + info->offset = regs.ebx; + info->cseg_16 = regs.ecx & 0xffff; + info->dseg = regs.edx & 0xffff; + info->cseg_len = regs.esi >> 16; + info->cseg_16_len = regs.esi & 0xffff; + info->dseg_len = regs.edi; + + return 1; +} + +static grub_err_t +grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) +{ + struct grub_apm_info info; + if (!grub_apm_get_info (&info)) + return grub_error (GRUB_ERR_IO, "no APM found"); + + grub_printf ("Vesion %u.%u\n" + "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" + "16-bit CS = 0x%x, len = 0x%x\n" + "DS = 0x%x, len = 0x%x\n", + info.version >> 8, info.version & 0xff, + info.cseg, info.cseg_len, info.offset, + info.cseg_16, info.cseg_16_len, + info.dseg, info.dseg_len); + grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED + ? "16-bit protected interface supported\n" + : "16-bit protected interface unsupported\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED + ? "32-bit protected interface supported\n" + : "32-bit protected interface unsupported\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN + ? "CPU Idle slows down processor\n" + : "CPU Idle doesn't slow down processor\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED + ? "APM disabled\n" : "APM enabled\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED + ? "APM disengaged\n" : "APM engaged\n"); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsapm) +{ + cmd = grub_register_command ("lsapm", grub_cmd_lsapm, 0, + N_("Show APM information.")); +} + +GRUB_MOD_FINI(lsapm) +{ + grub_unregister_command (cmd); +} + + diff --git a/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c similarity index 100% rename from commands/i386/pc/play.c rename to grub-core/commands/i386/pc/play.c diff --git a/commands/i386/pc/pxecmd.c b/grub-core/commands/i386/pc/pxecmd.c similarity index 100% rename from commands/i386/pc/pxecmd.c rename to grub-core/commands/i386/pc/pxecmd.c diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c new file mode 100644 index 000000000..c777ea60a --- /dev/null +++ b/grub-core/commands/i386/pc/sendkey.c @@ -0,0 +1,383 @@ +/* sendkey.c - fake keystroke. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static char sendkey[0x20]; +/* Length of sendkey. */ +static int keylen = 0; +static int noled = 0; +static const struct grub_arg_option options[] = + { + {"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING}, + {"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING}, + {"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING}, + {"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING}, + {"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING}, + {"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING}, + {"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING}, + {"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING}, + {"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING}, + {"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING}, + {"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING}, + {"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING}, + {"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING}, + {"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING}, + {"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING}, + {"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING}, + {"no-led", 0, 0, "don't update LED state", 0, 0}, + {0, 0, 0, 0, 0, 0} + }; +static int simple_flag_offsets[] += {5, 6, 4, 7, 11, 1, 0, 10, 13, 14, 12, 15, 9, 3, 8, 2}; + +static grub_uint32_t andmask = 0xffffffff, ormask = 0; + +struct +keysym +{ + char *unshifted_name; /* the name in unshifted state */ + char *shifted_name; /* the name in shifted state */ + unsigned char unshifted_ascii; /* the ascii code in unshifted state */ + unsigned char shifted_ascii; /* the ascii code in shifted state */ + unsigned char keycode; /* keyboard scancode */ +}; + +/* The table for key symbols. If the "shifted" member of an entry is + NULL, the entry does not have shifted state. Copied from GRUB Legacy setkey fuction */ +static struct keysym keysym_table[] = +{ + {"escape", 0, 0x1b, 0, 0x01}, + {"1", "exclam", '1', '!', 0x02}, + {"2", "at", '2', '@', 0x03}, + {"3", "numbersign", '3', '#', 0x04}, + {"4", "dollar", '4', '$', 0x05}, + {"5", "percent", '5', '%', 0x06}, + {"6", "caret", '6', '^', 0x07}, + {"7", "ampersand", '7', '&', 0x08}, + {"8", "asterisk", '8', '*', 0x09}, + {"9", "parenleft", '9', '(', 0x0a}, + {"0", "parenright", '0', ')', 0x0b}, + {"minus", "underscore", '-', '_', 0x0c}, + {"equal", "plus", '=', '+', 0x0d}, + {"backspace", 0, '\b', 0, 0x0e}, + {"tab", 0, '\t', 0, 0x0f}, + {"q", "Q", 'q', 'Q', 0x10}, + {"w", "W", 'w', 'W', 0x11}, + {"e", "E", 'e', 'E', 0x12}, + {"r", "R", 'r', 'R', 0x13}, + {"t", "T", 't', 'T', 0x14}, + {"y", "Y", 'y', 'Y', 0x15}, + {"u", "U", 'u', 'U', 0x16}, + {"i", "I", 'i', 'I', 0x17}, + {"o", "O", 'o', 'O', 0x18}, + {"p", "P", 'p', 'P', 0x19}, + {"bracketleft", "braceleft", '[', '{', 0x1a}, + {"bracketright", "braceright", ']', '}', 0x1b}, + {"enter", 0, '\r', 0, 0x1c}, + {"control", 0, 0, 0, 0x1d}, + {"a", "A", 'a', 'A', 0x1e}, + {"s", "S", 's', 'S', 0x1f}, + {"d", "D", 'd', 'D', 0x20}, + {"f", "F", 'f', 'F', 0x21}, + {"g", "G", 'g', 'G', 0x22}, + {"h", "H", 'h', 'H', 0x23}, + {"j", "J", 'j', 'J', 0x24}, + {"k", "K", 'k', 'K', 0x25}, + {"l", "L", 'l', 'L', 0x26}, + {"semicolon", "colon", ';', ':', 0x27}, + {"quote", "doublequote", '\'', '"', 0x28}, + {"backquote", "tilde", '`', '~', 0x29}, + {"shift", 0, 0, 0, 0x2a}, + {"backslash", "bar", '\\', '|', 0x2b}, + {"z", "Z", 'z', 'Z', 0x2c}, + {"x", "X", 'x', 'X', 0x2d}, + {"c", "C", 'c', 'C', 0x2e}, + {"v", "V", 'v', 'V', 0x2f}, + {"b", "B", 'b', 'B', 0x30}, + {"n", "N", 'n', 'N', 0x31}, + {"m", "M", 'm', 'M', 0x32}, + {"comma", "less", ',', '<', 0x33}, + {"period", "greater", '.', '>', 0x34}, + {"slash", "question", '/', '?', 0x35}, + {"rshift", 0, 0, 0, 0x36}, + {"numasterisk", 0, '*', 0, 0x37}, + {"alt", 0, 0, 0, 0x38}, + {"space", 0, ' ', 0, 0x39}, + {"capslock", 0, 0, 0, 0x3a}, + {"F1", 0, 0, 0, 0x3b}, + {"F2", 0, 0, 0, 0x3c}, + {"F3", 0, 0, 0, 0x3d}, + {"F4", 0, 0, 0, 0x3e}, + {"F5", 0, 0, 0, 0x3f}, + {"F6", 0, 0, 0, 0x40}, + {"F7", 0, 0, 0, 0x41}, + {"F8", 0, 0, 0, 0x42}, + {"F9", 0, 0, 0, 0x43}, + {"F10", 0, 0, 0, 0x44}, + {"num7", "numhome", '7', 0, 0x47}, + {"num8", "numup", '8', 0, 0x48}, + {"num9", "numpgup", '9', 0, 0x49}, + {"numminus", 0, '-', 0, 0x4a}, + {"num4", "numleft", '4', 0, 0x4b}, + {"num5", "numcenter", '5', 0, 0x4c}, + {"num6", "numright", '6', 0, 0x4d}, + {"numplus", 0, '-', 0, 0x4e}, + {"num1", "numend", '1', 0, 0x4f}, + {"num2", "numdown", '2', 0, 0x50}, + {"num3", "numpgdown", '3', 0, 0x51}, + {"num0", "numinsert", '0', 0, 0x52}, + {"numperiod", "numdelete", 0, 0x7f, 0x53}, + {"F11", 0, 0, 0, 0x57}, + {"F12", 0, 0, 0, 0x58}, + {"numenter", 0, '\r', 0, 0xe0}, + {"numslash", 0, '/', 0, 0xe0}, + {"delete", 0, 0x7f, 0, 0xe0}, + {"insert", 0, 0xe0, 0, 0x52}, + {"home", 0, 0xe0, 0, 0x47}, + {"end", 0, 0xe0, 0, 0x4f}, + {"pgdown", 0, 0xe0, 0, 0x51}, + {"pgup", 0, 0xe0, 0, 0x49}, + {"down", 0, 0xe0, 0, 0x50}, + {"up", 0, 0xe0, 0, 0x48}, + {"left", 0, 0xe0, 0, 0x4b}, + {"right", 0, 0xe0, 0, 0x4d} +}; + +/* Set a simple flag in flags variable + OUTOFFSET - offset of flag in FLAGS, + OP - action id +*/ +static void +grub_sendkey_set_simple_flag (int outoffset, int op) +{ + if (op == 2) + { + andmask |= (1 << outoffset); + ormask &= ~(1 << outoffset); + } + else + { + andmask &= (~(1 << outoffset)); + if (op == 1) + ormask |= (1 << outoffset); + else + ormask &= ~(1 << outoffset); + } +} + +static int +grub_sendkey_parse_op (struct grub_arg_list state) +{ + if (! state.set) + return 2; + + if (grub_strcmp (state.arg, "off") == 0 || grub_strcmp (state.arg, "0") == 0 + || grub_strcmp (state.arg, "unpress") == 0) + return 0; + + if (grub_strcmp (state.arg, "on") == 0 || grub_strcmp (state.arg, "1") == 0 + || grub_strcmp (state.arg, "press") == 0) + return 1; + + return 2; +} + +static grub_uint32_t oldflags; + +static grub_err_t +grub_sendkey_postboot (void) +{ + /* For convention: pointer to flags. */ + grub_uint32_t *flags = (grub_uint32_t *) 0x417; + + *flags = oldflags; + + *((char *) 0x41a) = 0x1e; + *((char *) 0x41c) = 0x1e; + + return GRUB_ERR_NONE; +} + +/* Set keyboard buffer to our sendkey */ +static grub_err_t +grub_sendkey_preboot (int noret __attribute__ ((unused))) +{ + /* For convention: pointer to flags. */ + grub_uint32_t *flags = (grub_uint32_t *) 0x417; + + oldflags = *flags; + + /* Set the sendkey. */ + *((char *) 0x41a) = 0x1e; + *((char *) 0x41c) = keylen + 0x1e; + grub_memcpy ((char *) 0x41e, sendkey, 0x20); + + /* Transform "any ctrl" to "right ctrl" flag. */ + if (*flags & (1 << 8)) + *flags &= ~(1 << 2); + + /* Transform "any alt" to "right alt" flag. */ + if (*flags & (1 << 9)) + *flags &= ~(1 << 3); + + *flags = (*flags & andmask) | ormask; + + /* Transform "right ctrl" to "any ctrl" flag. */ + if (*flags & (1 << 8)) + *flags |= (1 << 2); + + /* Transform "right alt" to "any alt" flag. */ + if (*flags & (1 << 9)) + *flags |= (1 << 3); + + /* Write new LED state */ + if (!noled) + { + int value = 0; + int failed; + /* Try 5 times */ + for (failed = 0; failed < 5; failed++) + { + value = 0; + /* Send command change LEDs */ + grub_outb (0xed, 0x60); + + /* Wait */ + do + value = grub_inb (0x60); + while ((value != 0xfa) && (value != 0xfe)); + + if (value == 0xfa) + { + /* Set new LEDs*/ + grub_outb ((*flags >> 4) & 7, 0x60); + break; + } + } + } + return GRUB_ERR_NONE; +} + +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; + + { + int i; + + keylen = 0; + + for (i = 0; i < argc && keylen < 0x20; i++) + { + int key_code; + + key_code = find_key_code (args[i]); + if (key_code) + { + sendkey[keylen++] = find_ascii_code (args[i]); + sendkey[keylen++] = key_code; + } + } + } + + { + unsigned i; + for (i = 0; i < sizeof (simple_flag_offsets) + / sizeof (simple_flag_offsets[0]); i++) + grub_sendkey_set_simple_flag (simple_flag_offsets[i], + grub_sendkey_parse_op(state[i])); + } + + /* Set noled. */ + noled = (state[sizeof (simple_flag_offsets) + / sizeof (simple_flag_offsets[0])].set); + + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; +static void *preboot_hook; + +GRUB_MOD_INIT (sendkey) +{ + cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0, + "sendkey [KEYSTROKE1] [KEYSTROKE2] ...", + "Emulate a keystroke", options); + + preboot_hook + = grub_loader_register_preboot_hook (grub_sendkey_preboot, + grub_sendkey_postboot, + GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE); +} + +GRUB_MOD_FINI (sendkey) +{ + grub_unregister_extcmd (cmd); + grub_loader_unregister_preboot_hook (preboot_hook); +} diff --git a/commands/ieee1275/suspend.c b/grub-core/commands/ieee1275/suspend.c similarity index 100% rename from commands/ieee1275/suspend.c rename to grub-core/commands/ieee1275/suspend.c diff --git a/commands/iorw.c b/grub-core/commands/iorw.c similarity index 89% rename from commands/iorw.c rename to grub-core/commands/iorw.c index 474c8712e..20d203e92 100644 --- a/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -36,17 +36,16 @@ static const struct grub_arg_option options[] = static grub_err_t -grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; - char buf[sizeof ("XXXXXXXX")]; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); - switch (cmd->cmd->name[sizeof ("in") - 1]) + switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1]) { case 'l': value = grub_inl (addr); @@ -61,10 +60,11 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) break; } - if (cmd->state[0].set) + if (ctxt->state[0].set) { + char buf[sizeof ("XXXXXXXX")]; grub_snprintf (buf, sizeof (buf), "%x", value); - grub_env_set (cmd->state[0].arg, buf); + grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); @@ -117,13 +117,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("inb", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inb", grub_cmd_read, 0, N_("PORT"), N_("Read byte from PORT."), options); cmd_read_word = - grub_register_extcmd ("inw", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inw", grub_cmd_read, 0, N_("PORT"), N_("Read word from PORT."), options); cmd_read_dword = - grub_register_extcmd ("inl", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inl", grub_cmd_read, 0, N_("PORT"), N_("Read dword from PORT."), options); cmd_write_byte = grub_register_command ("outb", grub_cmd_write, diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c new file mode 100644 index 000000000..deb482a85 --- /dev/null +++ b/grub-core/commands/keylayouts.c @@ -0,0 +1,297 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2005,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 + * 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 + +static struct grub_keyboard_layout layout_us = { + .keyboard_map = { + /* Keyboard errors. Handled by driver. */ + /* 0x00 */ 0, 0, 0, 0, + + /* 0x04 */ 'a', 'b', 'c', 'd', + /* 0x08 */ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + /* 0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + /* 0x18 */ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', + /* 0x20 */ '3', '4', '5', '6', '7', '8', '9', '0', + /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* According to usage table 0x31 should be mapped to '/' + but testing with real keyboard shows that 0x32 is remapped to '/'. + Map 0x31 to 0. + */ + /* 0x30 */ ']', 0, '\\', ';', '\'', '`', ',', '.', + /* 0x39 is CapsLock. Handled by driver. */ + /* 0x38 */ '/', 0, GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, + /* 0x3c */ GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, + /* 0x3e */ GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, + /* 0x40 */ GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, + /* 0x42 */ GRUB_TERM_KEY_F9, GRUB_TERM_KEY_F10, + /* 0x44 */ GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, + /* PrtScr and ScrollLock. Not handled yet. */ + /* 0x46 */ 0, 0, + /* 0x48 is Pause. Not handled yet. */ + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT, + /* 0x4a */ GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, + /* 0x4c */ GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, + /* 0x4e */ GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, + /* 0x50 */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, + /* 0x53 is NumLock. Handled by driver. */ + /* 0x52 */ GRUB_TERM_KEY_UP, 0, + /* 0x54 */ '/', '*', + /* 0x56 */ '-', '+', + /* 0x58 */ '\n', GRUB_TERM_KEY_END, + /* 0x5a */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE, + /* 0x5c */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER, + /* 0x5e */ GRUB_TERM_KEY_RIGHT, GRUB_TERM_KEY_HOME, + /* 0x60 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_PPAGE, + /* 0x62 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x64 */ '\\' + }, + .keyboard_map_shift = { + /* Keyboard errors. Handled by driver. */ + /* 0x00 */ 0, 0, 0, 0, + + /* 0x04 */ 'A', 'B', 'C', 'D', + /* 0x08 */ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + /* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + /* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', + /* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')', + /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT, + /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT, + /* 0x2c */ ' ' | GRUB_TERM_SHIFT, '_', '+', '{', + /* According to usage table 0x31 should be mapped to '/' + but testing with real keyboard shows that 0x32 is remapped to '/'. + Map 0x31 to 0. + */ + /* 0x30 */ '}', 0, '|', ':', '"', '~', '<', '>', + /* 0x39 is CapsLock. Handled by driver. */ + /* 0x38 */ '?', 0, + /* 0x3a */ GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT, + /* 0x3b */ GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT, + /* 0x3c */ GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT, + /* 0x3d */ GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT, + /* 0x3e */ GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT, + /* 0x3f */ GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT, + /* 0x40 */ GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT, + /* 0x41 */ GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT, + /* 0x42 */ GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT, + /* 0x43 */ GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT, + /* 0x44 */ GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT, + /* 0x45 */ GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT, + /* PrtScr and ScrollLock. Not handled yet. */ + /* 0x46 */ 0, 0, + /* 0x48 is Pause. Not handled yet. */ + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT | GRUB_TERM_SHIFT, + /* 0x4a */ GRUB_TERM_KEY_HOME | GRUB_TERM_SHIFT, + /* 0x4b */ GRUB_TERM_KEY_PPAGE | GRUB_TERM_SHIFT, + /* 0x4c */ GRUB_TERM_KEY_DC | GRUB_TERM_SHIFT, + /* 0x4d */ GRUB_TERM_KEY_END | GRUB_TERM_SHIFT, + /* 0x4e */ GRUB_TERM_KEY_NPAGE | GRUB_TERM_SHIFT, + /* 0x4f */ GRUB_TERM_KEY_RIGHT | GRUB_TERM_SHIFT, + /* 0x50 */ GRUB_TERM_KEY_LEFT | GRUB_TERM_SHIFT, + /* 0x51 */ GRUB_TERM_KEY_DOWN | GRUB_TERM_SHIFT, + /* 0x53 is NumLock. Handled by driver. */ + /* 0x52 */ GRUB_TERM_KEY_UP | GRUB_TERM_SHIFT, 0, + /* 0x54 */ '/', '*', + /* 0x56 */ '-', '+', + /* 0x58 */ '\n' | GRUB_TERM_SHIFT, '1', '2', '3', '4', '5','6', '7', + /* 0x60 */ '8', '9', '0', '.', '|' + } +}; + +static struct grub_keyboard_layout *grub_current_layout = &layout_us; + +static int +map_key_core (int code, int status, int *alt_gr_consumed) +{ + *alt_gr_consumed = 0; + + if (status & GRUB_TERM_STATUS_RALT) + { + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + { + if (grub_current_layout->keyboard_map_shift_l3[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->keyboard_map_shift_l3[code]; + } + } + else if (grub_current_layout->keyboard_map_l3[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->keyboard_map_l3[code]; + } + } + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + return grub_current_layout->keyboard_map_shift[code]; + else + return grub_current_layout->keyboard_map[code]; +} + +unsigned +grub_term_map_key (grub_keyboard_key_t code, int status) +{ + int alt_gr_consumed = 0; + int key; + + if (code >= 0x59 && code <= 0x63 && (status & GRUB_TERM_STATUS_NUM)) + { + if (status & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)) + status &= ~(GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT); + else + status |= GRUB_TERM_STATUS_RSHIFT; + } + + key = map_key_core (code, status, &alt_gr_consumed); + + if (key == 0 || key == GRUB_TERM_SHIFT) + grub_printf ("Unknown key 0x%x detected\n", code); + + if (status & GRUB_TERM_STATUS_CAPS) + { + if ((key >= 'a') && (key <= 'z')) + key += 'A' - 'a'; + else if ((key >= 'A') && (key <= 'Z')) + key += 'a' - 'A'; + } + + if ((status & GRUB_TERM_STATUS_LALT) || + ((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed)) + key |= GRUB_TERM_ALT; + if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL)) + key |= GRUB_TERM_CTRL; + + return key; +} + +static grub_err_t +grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + char *filename; + grub_file_t file; + grub_uint32_t version; + grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE]; + struct grub_keyboard_layout *newmap = NULL; + unsigned i; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file or layout name required"); + if (argv[0][0] != '(' && argv[0][0] != '/' && argv[0][0] != '+') + { + const char *prefix = grub_env_get ("prefix"); + if (!prefix) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set"); + filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]); + if (!filename) + return grub_errno; + } + else + filename = argv[0]; + + file = grub_file_open (filename); + if (! file) + goto fail; + + if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + if (grub_memcmp (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE) != 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid magic"); + goto fail; + } + + if (grub_file_read (file, &version, sizeof (version)) != sizeof (version)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version"); + goto fail; + } + + newmap = grub_malloc (sizeof (*newmap)); + if (!newmap) + goto fail; + + if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map); i++) + newmap->keyboard_map[i] = grub_le_to_cpu32(newmap->keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift); i++) + newmap->keyboard_map_shift[i] + = grub_le_to_cpu32(newmap->keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_l3); i++) + newmap->keyboard_map_l3[i] + = grub_le_to_cpu32(newmap->keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift_l3); i++) + newmap->keyboard_map_shift_l3[i] + = grub_le_to_cpu32(newmap->keyboard_map_shift_l3[i]); + + grub_current_layout = newmap; + + return GRUB_ERR_NONE; + + fail: + if (filename != argv[0]) + grub_free (filename); + grub_free (newmap); + if (file) + grub_file_close (file); + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(keylayouts) +{ + cmd = grub_register_command ("keymap", grub_cmd_keymap, + 0, N_("Load a keyboard layout.")); +} + +GRUB_MOD_FINI(keylayouts) +{ + grub_unregister_command (cmd); +} diff --git a/commands/keystatus.c b/grub-core/commands/keystatus.c similarity index 77% rename from commands/keystatus.c rename to grub-core/commands/keystatus.c index 838792889..9e1486c9d 100644 --- a/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -31,23 +31,39 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -#define grub_cur_term_input grub_term_get_current_input () +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_t cmd, +grub_cmd_keystatus (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int expect_mods = 0; int mods; if (state[0].set) - expect_mods |= GRUB_TERM_STATUS_SHIFT; + expect_mods |= (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT); if (state[1].set) - expect_mods |= GRUB_TERM_STATUS_CTRL; + expect_mods |= (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL); if (state[2].set) - expect_mods |= GRUB_TERM_STATUS_ALT; + expect_mods |= (GRUB_TERM_STATUS_LALT | GRUB_TERM_STATUS_RALT); grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); @@ -80,8 +96,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(keystatus) { - cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, 0, N_("[--shift] [--ctrl] [--alt]"), N_("Check key modifier status."), options); diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c new file mode 100644 index 000000000..d5441db06 --- /dev/null +++ b/grub-core/commands/legacycfg.c @@ -0,0 +1,810 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000, 2001, 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 +#include +#include +#include +#include +#include +#include +#include + +static grub_err_t +legacy_file (const char *filename) +{ + grub_file_t file; + char *entryname = NULL, *entrysrc = NULL; + 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); + if (! file) + return grub_errno; + + menu = grub_env_get_menu (); + if (! menu) + { + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return grub_errno; + + grub_env_set_menu (menu); + } + + while (1) + { + char *buf = grub_file_getline (file); + char *parsed = NULL; + + if (!buf && grub_errno) + { + grub_file_close (file); + return grub_errno; + } + + if (!buf) + break; + + { + char *oldname = NULL; + char *newsuffix; + + oldname = entryname; + parsed = grub_legacy_parse (buf, &entryname, &newsuffix); + buf = NULL; + if (newsuffix) + { + char *t; + + t = suffix; + suffix = grub_realloc (suffix, grub_strlen (suffix) + + grub_strlen (newsuffix) + 1); + if (!suffix) + { + grub_free (t); + grub_free (entrysrc); + grub_free (parsed); + grub_free (newsuffix); + grub_free (suffix); + return grub_errno; + } + grub_memcpy (suffix + grub_strlen (suffix), newsuffix, + grub_strlen (newsuffix) + 1); + grub_free (newsuffix); + newsuffix = NULL; + } + if (oldname != entryname && oldname) + { + const char **args = grub_malloc (sizeof (args[0])); + if (!args) + { + grub_file_close (file); + return grub_errno; + } + args[0] = oldname; + grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, + entrysrc, 0); + grub_free (args); + entrysrc[0] = 0; + grub_free (oldname); + } + } + + if (parsed && !entryname) + { + grub_normal_parse_line (parsed, getline); + grub_print_error (); + grub_free (parsed); + parsed = NULL; + } + else if (parsed) + { + if (!entrysrc) + entrysrc = parsed; + else + { + char *t; + + t = entrysrc; + entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) + + grub_strlen (parsed) + 1); + if (!entrysrc) + { + grub_free (t); + grub_free (parsed); + grub_free (suffix); + return grub_errno; + } + grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, + grub_strlen (parsed) + 1); + grub_free (parsed); + parsed = NULL; + } + } + } + grub_file_close (file); + + if (entryname) + { + const char **args = grub_malloc (sizeof (args[0])); + if (!args) + { + grub_file_close (file); + return grub_errno; + } + args[0] = entryname; + grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc, 0); + grub_free (args); + } + + grub_normal_parse_line (suffix, getline); + grub_print_error (); + grub_free (suffix); + grub_free (entrysrc); + + if (menu && menu->size) + grub_show_menu (menu, 1); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_legacy_source (struct grub_command *cmd, + int argc, char **args) +{ + int new_env, extractor; + grub_err_t ret; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + extractor = (cmd->name[0] == 'e'); + new_env = (cmd->name[extractor ? sizeof ("extract_legacy_entries_") - 1 + : sizeof ("legacy_") - 1] == 'c'); + + if (new_env) + grub_cls (); + + if (new_env && !extractor) + grub_env_context_open (); + if (extractor) + grub_env_extractor_open (!new_env); + + ret = legacy_file (args[0]); + + if (new_env && !extractor) + grub_env_context_close (); + if (extractor) + grub_env_extractor_close (!new_env); + + return ret; +} + +static enum + { + GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD + } kernel_type; + +static grub_err_t +grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + int i; +#ifdef TODO + int no_mem_option = 0; +#endif + struct grub_command *cmd; + char **cutargs; + int cutargc; + + for (i = 0; i < 2; i++) + { + /* FIXME: really support this. */ + if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0) + { +#ifdef TODO + no_mem_option = 1; +#endif + argc--; + args++; + continue; + } + + /* linux16 handles both zImages and bzImages. */ + if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0 + || grub_strcmp (args[0], "--type=biglinux") == 0)) + { + kernel_type = LINUX; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0) + { + kernel_type = MULTIBOOT; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0) + { + kernel_type = KFREEBSD; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0) + { + kernel_type = KOPENBSD; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0) + { + kernel_type = KNETBSD; + argc--; + args++; + continue; + } + } + + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); + + 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]; + + do + { + /* First try Linux. */ + if (kernel_type == GUESS_IT || kernel_type == LINUX) + { + cmd = grub_command_find ("linux16"); + if (cmd) + { + if (!(cmd->func) (cmd, cutargc, cutargs)) + { + kernel_type = LINUX; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + + /* Then multiboot. */ + if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) + { + cmd = grub_command_find ("multiboot"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = MULTIBOOT; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + + { + int bsd_device = -1; + int bsd_slice = -1; + int bsd_part = -1; + { + grub_device_t dev; + char *hdbiasstr; + int hdbias = 0; + hdbiasstr = grub_env_get ("legacy_hdbias"); + if (hdbiasstr) + { + hdbias = grub_strtoul (hdbiasstr, 0, 0); + grub_errno = GRUB_ERR_NONE; + } + dev = grub_device_open (0); + if (dev && dev->disk + && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID + && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) + { + struct grub_partition *part = dev->disk->partition; + bsd_device = dev->disk->id - 0x80 - hdbias; + if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0 + || grub_strcmp (part->partmap->name, "openbsd") == 0 + || grub_strcmp (part->partmap->name, "bsd") == 0)) + { + bsd_part = part->number; + part = part->parent; + } + if (part && grub_strcmp (part->partmap->name, "msdos") == 0) + bsd_slice = part->number; + } + } + + /* k*BSD didn't really work well with grub-legacy. */ + if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; + if (bsd_device != -1) + { + if (bsd_slice != -1 && bsd_part != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, + bsd_slice, 'a' + bsd_part); + else if (bsd_slice != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, + bsd_slice); + else + grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device); + grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf); + } + else + grub_env_unset ("kFreeBSD.vfs.root.mountfrom"); + cmd = grub_command_find ("kfreebsd"); + if (cmd) + { + if (!(cmd->func) (cmd, cutargc, cutargs)) + { + kernel_type = KFREEBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + { + char **bsdargs; + int bsdargc; + char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; + if (bsd_device == -1) + { + bsdargs = cutargs; + bsdargc = cutargc; + } + else + { + bsdargc = cutargc + 2; + bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); + grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); + bsdargs[argc] = "-r"; + bsdargs[argc + 1] = bsddevname; + grub_snprintf (bsddevname, sizeof (bsddevname), + "wd%d%c", bsd_device, + bsd_part != -1 ? bsd_part + 'a' : 'c'); + } + if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + { + cmd = grub_command_find ("knetbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KNETBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) + { + cmd = grub_command_find ("kopenbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KOPENBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (bsdargs != cutargs) + grub_free (bsdargs); + } + } + } + while (0); + + return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n", + args[0]); +} + +static grub_err_t +grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_command *cmd; + + if (kernel_type == LINUX) + { + cmd = grub_command_find ("initrd16"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + + return cmd->func (cmd, argc, args); + } + if (kernel_type == MULTIBOOT) + { + cmd = grub_command_find ("module"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + + return cmd->func (cmd, argc, args); + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no kernel with module support is loaded in legacy way"); +} + +static grub_err_t +grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_command *cmd; + + if (kernel_type == LINUX) + { + cmd = grub_command_find ("initrd16"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + + return cmd->func (cmd, argc, args); + } + if (kernel_type == MULTIBOOT) + { + char **newargs; + grub_err_t err; + newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); + if (!newargs) + return grub_errno; + grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); + newargs[0] = "--nounzip"; + cmd = grub_command_find ("module"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + + err = cmd->func (cmd, argc + 1, newargs); + grub_free (newargs); + return err; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no kernel with module support is loaded in legacy way"); +} + +static grub_err_t +check_password_deny (const char *user __attribute__ ((unused)), + const char *entered __attribute__ ((unused)), + void *password __attribute__ ((unused))) +{ + return GRUB_ACCESS_DENIED; +} + +#define MD5_HASHLEN 16 + +struct legacy_md5_password +{ + grub_uint8_t *salt; + int saltlen; + grub_uint8_t hash[MD5_HASHLEN]; +}; + +static int +check_password_md5_real (const char *entered, + struct legacy_md5_password *pw) +{ + int enteredlen = grub_strlen (entered); + unsigned char alt_result[MD5_HASHLEN]; + unsigned char *digest; + grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + int i; + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + memcpy (alt_result, digest, MD5_HASHLEN); + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ + for (i = enteredlen; i > 16; i -= 16) + GRUB_MD_MD5->write (ctx, alt_result, 16); + GRUB_MD_MD5->write (ctx, alt_result, i); + + for (i = enteredlen; i > 0; i >>= 1) + GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + + for (i = 0; i < 1000; i++) + { + memcpy (alt_result, digest, 16); + + GRUB_MD_MD5->init (ctx); + if ((i & 1) != 0) + GRUB_MD_MD5->write (ctx, entered, enteredlen); + else + GRUB_MD_MD5->write (ctx, alt_result, 16); + + if (i % 3 != 0) + GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); + + if (i % 7 != 0) + GRUB_MD_MD5->write (ctx, entered, enteredlen); + + if ((i & 1) != 0) + GRUB_MD_MD5->write (ctx, alt_result, 16); + else + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + } + + return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); +} + +static grub_err_t +check_password_md5 (const char *user, + const char *entered, + void *password) +{ + if (!check_password_md5_real (entered, password)) + return GRUB_ACCESS_DENIED; + + grub_auth_authenticate (user); + + return GRUB_ERR_NONE; +} + +static inline int +ib64t (char c) +{ + if (c == '.') + return 0; + if (c == '/') + return 1; + if (c >= '0' && c <= '9') + return c - '0' + 2; + if (c >= 'A' && c <= 'Z') + return c - 'A' + 12; + if (c >= 'a' && c <= 'z') + return c - 'a' + 38; + return -1; +} + +static struct legacy_md5_password * +parse_legacy_md5 (int argc, char **args) +{ + const char *salt, *saltend; + struct legacy_md5_password *pw = NULL; + int i; + const char *p; + + if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) + goto fail; + if (argc == 1) + goto fail; + if (grub_strlen(args[1]) <= 3) + goto fail; + salt = args[1]; + saltend = grub_strchr (salt + 3, '$'); + if (!saltend) + goto fail; + pw = grub_malloc (sizeof (*pw)); + if (!pw) + goto fail; + + p = saltend + 1; + for (i = 0; i < 5; i++) + { + int n; + grub_uint32_t w = 0; + + for (n = 0; n < 4; n++) + { + int ww = ib64t(*p++); + if (ww == -1) + goto fail; + w |= ww << (n * 6); + } + pw->hash[i == 4 ? 5 : 12+i] = w & 0xff; + pw->hash[6+i] = (w >> 8) & 0xff; + pw->hash[i] = (w >> 16) & 0xff; + } + { + int n; + grub_uint32_t w = 0; + for (n = 0; n < 2; n++) + { + int ww = ib64t(*p++); + if (ww == -1) + goto fail; + w |= ww << (6 * n); + } + if (w >= 0x100) + goto fail; + pw->hash[11] = w; + } + + pw->saltlen = saltend - salt; + pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen); + if (!pw->salt) + goto fail; + + return pw; + + fail: + grub_free (pw); + return NULL; +} + +static grub_err_t +grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct legacy_md5_password *pw = NULL; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + if (args[0][0] != '-' || args[0][1] != '-') + return grub_normal_set_password ("legacy", args[0]); + + pw = parse_legacy_md5 (argc, args); + + if (pw) + return grub_auth_register_authentication ("legacy", check_password_md5, pw); + else + /* This is to imitate minor difference between grub-legacy in GRUB2. + If 2 password commands are executed in a row and second one fails + on GRUB2 the password of first one is used, whereas in grub-legacy + authenthication is denied. In case of no password command was executed + early both versions deny any access. */ + return grub_auth_register_authentication ("legacy", check_password_deny, + NULL); +} + +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) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + grub_printf ("Enter password:"); + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) + return GRUB_ACCESS_DENIED; + + 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; +} + +static grub_command_t cmd_source, cmd_configfile; +static grub_command_t cmd_source_extract, cmd_configfile_extract; +static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip; +static grub_command_t cmd_password, cmd_check_password; + +GRUB_MOD_INIT(legacycfg) +{ + cmd_source + = grub_register_command ("legacy_source", + grub_cmd_legacy_source, + N_("FILE"), + N_("Parse legacy config in same context")); + cmd_configfile + = grub_register_command ("legacy_configfile", + grub_cmd_legacy_source, + N_("FILE"), + N_("Parse legacy config in new context")); + cmd_source_extract + = grub_register_command ("extract_legacy_entries_source", + grub_cmd_legacy_source, + N_("FILE"), + N_("Parse legacy config in same context taking onl entries")); + cmd_configfile_extract + = grub_register_command ("extract_legacy_entries_configfile", + grub_cmd_legacy_source, + N_("FILE"), + N_("Parse legacy config in new context taking onl entries")); + + cmd_kernel = grub_register_command ("legacy_kernel", + grub_cmd_legacy_kernel, + N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), + N_("Simulate grub-legacy kernel command")); + + cmd_initrd = grub_register_command ("legacy_initrd", + grub_cmd_legacy_initrd, + N_("FILE [ARG ...]"), + N_("Simulate grub-legacy initrd command")); + cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip", + grub_cmd_legacy_initrdnounzip, + N_("FILE [ARG ...]"), + N_("Simulate grub-legacy modulenounzip command")); + + cmd_password = grub_register_command ("legacy_password", + grub_cmd_legacy_password, + N_("[--md5] PASSWD [FILE]"), + N_("Simulate grub-legacy password command")); + + cmd_check_password = grub_register_command ("legacy_check_password", + grub_cmd_legacy_check_password, + N_("[--md5] PASSWD [FILE]"), + N_("Simulate grub-legacy password command in menuentry mode")); + +} + +GRUB_MOD_FINI(legacycfg) +{ + grub_unregister_command (cmd_source); + grub_unregister_command (cmd_configfile); + grub_unregister_command (cmd_source_extract); + grub_unregister_command (cmd_configfile_extract); + + grub_unregister_command (cmd_kernel); + grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_initrdnounzip); + + grub_unregister_command (cmd_password); + grub_unregister_command (cmd_check_password); +} diff --git a/commands/loadenv.c b/grub-core/commands/loadenv.c similarity index 93% rename from commands/loadenv.c rename to grub-core/commands/loadenv.c index d763b2d5e..38b3a84c6 100644 --- a/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -56,6 +56,7 @@ open_envblk_file (char *filename) 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; @@ -67,6 +68,7 @@ open_envblk_file (char *filename) } } + grub_file_filter_disable_compression (); return grub_file_open (filename); } @@ -111,11 +113,11 @@ read_envblk_file (grub_file_t file) } static grub_err_t -grub_cmd_load_env (grub_extcmd_t cmd, +grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; @@ -143,11 +145,11 @@ grub_cmd_load_env (grub_extcmd_t cmd, } static grub_err_t -grub_cmd_list_env (grub_extcmd_t cmd, +grub_cmd_list_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; @@ -280,9 +282,9 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, } static grub_err_t -grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; struct blocklist *head = 0; @@ -373,20 +375,15 @@ 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, - GRUB_COMMAND_FLAG_BOTH, - N_("[-f FILE]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), N_("Load variables from environment block file."), options); cmd_list = - grub_register_extcmd ("list_env", grub_cmd_list_env, - GRUB_COMMAND_FLAG_BOTH, - N_("[-f FILE]"), + grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"), N_("List variables from environment block file."), options); cmd_save = - grub_register_extcmd ("save_env", grub_cmd_save_env, - GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("save_env", grub_cmd_save_env, 0, N_("[-f FILE] variable_name [...]"), N_("Save variables to environment block file."), options); diff --git a/commands/ls.c b/grub-core/commands/ls.c similarity index 93% rename from commands/ls.c rename to grub-core/commands/ls.c index 9ee0a7a31..481d17db0 100644 --- a/commands/ls.c +++ b/grub-core/commands/ls.c @@ -105,6 +105,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) /* 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) { @@ -211,6 +212,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) struct grub_dirhook_info info; grub_errno = 0; + grub_file_filter_disable_compression (); file = grub_file_open (dirname); if (! file) goto fail; @@ -248,15 +250,17 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) } static grub_err_t -grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; + int i; if (argc == 0) grub_ls_list_devices (state[0].set); else - grub_ls_list_files (args[0], state[0].set, state[2].set, - state[1].set); + for (i = 0; i < argc; i++) + grub_ls_list_files (args[i], state[0].set, state[2].set, + state[1].set); return 0; } @@ -265,8 +269,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(ls) { - cmd = grub_register_extcmd ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH, - N_("[-l|-h|-a] [FILE]"), + cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0, + N_("[-l|-h|-a] [FILE ...]"), N_("List devices and files."), options); } diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c new file mode 100644 index 000000000..64b559665 --- /dev/null +++ b/grub-core/commands/lsacpi.c @@ -0,0 +1,250 @@ +/* acpi.c - Display acpi tables. */ +/* + * 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 +#include + +static void +print_strn (grub_uint8_t *str, grub_size_t len) +{ + for (; *str && len; str++, len--) + grub_printf ("%c", *str); + for (len++; len; len--) + grub_printf (" "); +} + +#define print_field(x) print_strn(x, sizeof (x)) + +static void +disp_acpi_table (struct grub_acpi_table_header *t) +{ + print_field (t->signature); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); + print_field (t->oemid); + print_field (t->oemtable); + grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); + print_field (t->creator_id); + grub_printf (" %08" PRIxGRUB_UINT32_T "\n", t->creator_rev); +} + +static void +disp_madt_table (struct grub_acpi_madt *t) +{ + struct grub_acpi_madt_entry_header *d; + grub_uint32_t len; + + disp_acpi_table (&t->hdr); + grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T " Flags=%08" + PRIxGRUB_UINT32_T "\n", + t->lapic_addr, t->flags); + len = t->hdr.length - sizeof (struct grub_acpi_madt); + 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_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", + dt->bus, dt->source, dt->global_sys_interrupt, + dt->flags); + } + 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 + "\n", + dt->id, dt->global_sys_interrupt_base, + dt->addr); + } + 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", + 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, + dt->cpu_uid_str); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE: + { + struct grub_acpi_madt_entry_platform_int_source *dt = (void *) d; + static const char * const platint_type[] = + {"Nul", "PMI", "INIT", "CPEI"}; + + 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", + dt->sapic_vector, dt->global_sys_int, dt->src_flags); + } + break; + default: + grub_printf (" ??\n"); + } + } +} + +static void +disp_acpi_xsdt_table (struct grub_acpi_table_header *t) +{ + grub_uint32_t len; + grub_uint64_t *desc; + + disp_acpi_table (t); + len = t->length - sizeof (*t); + desc = (grub_uint64_t *) (t + 1); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32)) + { + grub_printf ("Unreachable table\n"); + continue; + } + t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; + + if (t == NULL) + continue; + + if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE, + sizeof (t->signature)) == 0) + disp_madt_table ((struct grub_acpi_madt *) t); + else + disp_acpi_table (t); + } +} + +static void +disp_acpi_rsdt_table (struct grub_acpi_table_header *t) +{ + grub_uint32_t len; + grub_uint32_t *desc; + + disp_acpi_table (t); + len = t->length - sizeof (*t); + desc = (grub_uint32_t *) (t + 1); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; + + if (t == NULL) + continue; + + if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE, + sizeof (t->signature)) == 0) + disp_madt_table ((struct grub_acpi_madt *) t); + else + disp_acpi_table (t); + } +} + +static void +disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) +{ + print_field (rsdp->signature); + 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); +} + +static void +disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) +{ + disp_acpi_rsdpv1 (&rsdp->rsdpv1); + grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, + rsdp->xsdt_addr); +} + +static const struct grub_arg_option options[] = { + {"v1", '1', 0, N_("Show v1 tables only."), 0, ARG_TYPE_NONE}, + {"v2", '2', 0, N_("Show v2 and v3 tablesv only."), 0, ARG_TYPE_NONE} +}; + +static grub_err_t +grub_cmd_lsacpi (struct grub_extcmd_context *ctxt, + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + if (!ctxt->state[1].set) + { + struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 (); + if (!rsdp1) + grub_printf ("No RSDPv1\n"); + else + { + grub_printf ("RSDPv1 signature:"); + disp_acpi_rsdpv1 (rsdp1); + disp_acpi_rsdt_table ((void *) (grub_addr_t) rsdp1->rsdt_addr); + } + } + + if (!ctxt->state[0].set) + { + struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 (); + if (!rsdp2) + grub_printf ("No RSDPv2\n"); + else + { + if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32)) + grub_printf ("Unreachable RSDPv2\n"); + else + { + grub_printf ("RSDPv2 signature:"); + disp_acpi_rsdpv2 (rsdp2); + disp_acpi_xsdt_table ((void *) (grub_addr_t) rsdp2->xsdt_addr); + grub_printf ("\n"); + } + } + } + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(lsapi) +{ + cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, N_("[-1|-2]"), + N_("Show ACPI information."), options); +} + +GRUB_MOD_FINI(lsacpi) +{ + grub_unregister_extcmd (cmd); +} + + diff --git a/commands/lsmmap.c b/grub-core/commands/lsmmap.c similarity index 64% rename from commands/lsmmap.c rename to grub-core/commands/lsmmap.c index 2755df9c4..657f81387 100644 --- a/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -16,24 +16,39 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MACHINE_EMU -#include -#endif #include #include #include #include +#include + +static const char *names[] = + { + [GRUB_MEMORY_AVAILABLE] = "available", + [GRUB_MEMORY_RESERVED] = "reserved", + [GRUB_MEMORY_ACPI] = "ACPI reclamaible", + [GRUB_MEMORY_NVS] = "NVS", + [GRUB_MEMORY_BADRAM] = "BadRAM", + [GRUB_MEMORY_CODE] = "firmware code", + [GRUB_MEMORY_HOLE] = "hole" + }; static grub_err_t grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + 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) { - grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", - (long long) addr, (long long) size, type); + if (type < ARRAY_SIZE (names) && names[type]) + grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n", + (long long) addr, (long long) size, names[type]); + else + grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", + (long long) addr, (long long) size, type); return 0; } #ifndef GRUB_MACHINE_EMU diff --git a/commands/lspci.c b/grub-core/commands/lspci.c similarity index 97% rename from commands/lspci.c rename to grub-core/commands/lspci.c index a69bb35ad..fd2d4eaf2 100644 --- a/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -211,11 +211,11 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) } static grub_err_t -grub_cmd_lspci (grub_extcmd_t cmd, +grub_cmd_lspci (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - iospace = cmd->state[0].set; + iospace = ctxt->state[0].set; grub_pci_iterate (grub_lspci_iter); return GRUB_ERR_NONE; } @@ -224,8 +224,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(lspci) { - cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH, - "[-i]", N_("List PCI devices."), options); + cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, 0, "[-i]", + N_("List PCI devices."), options); } GRUB_MOD_FINI(lspci) diff --git a/commands/memrw.c b/grub-core/commands/memrw.c similarity index 90% rename from commands/memrw.c rename to grub-core/commands/memrw.c index 6a4d43be2..28aac7d81 100644 --- a/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -35,7 +35,7 @@ static const struct grub_arg_option options[] = static grub_err_t -grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; @@ -45,7 +45,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); - switch (cmd->cmd->name[sizeof ("read_") - 1]) + switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1]) { case 'd': value = *((volatile grub_uint32_t *) addr); @@ -60,10 +60,10 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) break; } - if (cmd->state[0].set) + if (ctxt->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); - grub_env_set (cmd->state[0].arg, buf); + grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); @@ -119,13 +119,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("read_byte", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_byte", grub_cmd_read, 0, N_("ADDR"), N_("Read byte from ADDR."), options); cmd_read_word = - grub_register_extcmd ("read_word", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_word", grub_cmd_read, 0, N_("ADDR"), N_("Read word from ADDR."), options); cmd_read_dword = - grub_register_extcmd ("read_dword", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_dword", grub_cmd_read, 0, N_("ADDR"), N_("Read dword from ADDR."), options); cmd_write_byte = grub_register_command ("write_byte", grub_cmd_write, diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c new file mode 100644 index 000000000..9718d1eab --- /dev/null +++ b/grub-core/commands/menuentry.c @@ -0,0 +1,320 @@ +/* menuentry.c - menuentry command */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +static const struct grub_arg_option options[] = + { + {"class", 1, GRUB_ARG_OPTION_REPEATABLE, + N_("Menu entry type."), "STRING", ARG_TYPE_STRING}, + {"users", 2, 0, + N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING}, + {"hotkey", 3, 0, + N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING}, + {"source", 4, 0, + N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +static struct +{ + char *name; + int key; +} hotkey_aliases[] = + { + {"backspace", '\b'}, + {"tab", '\t'}, + {"delete", GRUB_TERM_KEY_DC}, + {"insert", GRUB_TERM_KEY_INSERT}, + {"f1", GRUB_TERM_KEY_F1}, + {"f2", GRUB_TERM_KEY_F2}, + {"f3", GRUB_TERM_KEY_F3}, + {"f4", GRUB_TERM_KEY_F4}, + {"f5", GRUB_TERM_KEY_F5}, + {"f6", GRUB_TERM_KEY_F6}, + {"f7", GRUB_TERM_KEY_F7}, + {"f8", GRUB_TERM_KEY_F8}, + {"f9", GRUB_TERM_KEY_F9}, + {"f10", GRUB_TERM_KEY_F10}, + {"f11", GRUB_TERM_KEY_F11}, + {"f12", GRUB_TERM_KEY_F12}, + }; + +/* Add a menu entry to the current menu context (as given by the environment + variable data slot `menu'). As the configuration file is read, the script + parser calls this when a menu entry is to be created. */ +grub_err_t +grub_normal_add_menu_entry (int argc, const char **args, char **classes, + const char *users, const char *hotkey, + const char *prefix, const char *sourcecode, + int submenu) +{ + int menu_hotkey = 0; + char **menu_args = NULL; + char *menu_users = NULL; + char *menu_title = NULL; + char *menu_sourcecode = NULL; + struct grub_menu_entry_class *menu_classes = NULL; + + grub_menu_t menu; + grub_menu_entry_t *last; + + menu = grub_env_get_menu (); + if (! menu) + return grub_error (GRUB_ERR_MENU, "no menu context"); + + last = &menu->entry_list; + + menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode); + if (! menu_sourcecode) + return grub_errno; + + if (classes) + { + int i; + for (i = 0; classes[i]; i++); /* count # of menuentry classes */ + menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class) * i); + if (! menu_classes) + goto fail; + + for (i = 0; classes[i]; i++) + { + menu_classes[i].name = grub_strdup (classes[i]); + if (! menu_classes[i].name) + goto fail; + menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL; + } + } + + if (users) + { + menu_users = grub_strdup (users); + if (! menu_users) + goto fail; + } + + if (hotkey) + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++) + if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0) + { + menu_hotkey = hotkey_aliases[i].key; + break; + } + if (i == ARRAY_SIZE (hotkey_aliases)) + menu_hotkey = hotkey[0]; + } + + if (! argc) + { + grub_error (GRUB_ERR_MENU, "menuentry is missing title"); + goto fail; + } + + menu_title = grub_strdup (args[0]); + if (! menu_title) + goto fail; + + /* Save argc, args to pass as parameters to block arg later. */ + menu_args = grub_malloc (sizeof (char*) * (argc + 1)); + if (! menu_args) + goto fail; + + { + int i; + for (i = 0; i < argc; i++) + { + menu_args[i] = grub_strdup (args[i]); + if (! menu_args[i]) + goto fail; + } + menu_args[argc] = NULL; + } + + /* Add the menu entry at the end of the list. */ + while (*last) + last = &(*last)->next; + + *last = grub_zalloc (sizeof (**last)); + if (! *last) + goto fail; + + (*last)->title = menu_title; + (*last)->hotkey = menu_hotkey; + (*last)->classes = menu_classes; + if (menu_users) + (*last)->restricted = 1; + (*last)->users = menu_users; + (*last)->argc = argc; + (*last)->args = menu_args; + (*last)->sourcecode = menu_sourcecode; + (*last)->submenu = submenu; + + menu->size++; + return GRUB_ERR_NONE; + + fail: + + grub_free (menu_sourcecode); + { + int i; + for (i = 0; menu_classes && menu_classes[i].name; i++) + grub_free (menu_classes[i].name); + grub_free (menu_classes); + } + + { + int i; + for (i = 0; menu_args && menu_args[i]; i++) + grub_free (menu_args[i]); + grub_free (menu_args); + } + + grub_free (menu_users); + grub_free (menu_title); + return grub_errno; +} + +static char * +setparams_prefix (int argc, char **args) +{ + int i; + int j; + char *p; + char *result; + grub_size_t len = 10; + static const char *escape_characters = "\"\\"; + + auto char *strescpy (char *, const char *, const char *); + char * strescpy (char *d, const char *s, const char *escapes) + { + while (*s) + { + if (grub_strchr (escapes, *s)) + *d++ = '\\'; + *d++ = *s++; + } + *d = '\0'; + return d; + } + + /* Count resulting string length */ + for (i = 0; i < argc; i++) + { + len += 3; /* 3 = 1 space + 2 quotes */ + p = args[i]; + while (*p) + len += grub_strchr (escape_characters, *p++) ? 2 : 1; + } + + result = grub_malloc (len + 2); + if (! result) + return 0; + + grub_strcpy (result, "setparams"); + i = 9; + + for (j = 0; j < argc; j++) + { + result[i++] = ' '; + result[i++] = '"'; + i = strescpy (result + i, args[j], escape_characters) - result; + result[i++] = '"'; + } + result[i++] = '\n'; + result[i] = '\0'; + return result; +} + +static grub_err_t +grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) +{ + char ch; + char *src; + char *prefix; + unsigned len; + grub_err_t r; + + if (! argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments"); + + if (ctxt->state[3].set && ctxt->script) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions"); + + if (! ctxt->state[3].set && ! ctxt->script) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition"); + + if (! ctxt->script) + return grub_normal_add_menu_entry (argc, (const char **) args, + ctxt->state[0].args, ctxt->state[1].arg, + ctxt->state[2].arg, 0, + ctxt->state[3].arg, + ctxt->extcmd->cmd->name[0] == 's'); + + src = args[argc - 1]; + args[argc - 1] = NULL; + + len = grub_strlen(src); + ch = src[len - 1]; + src[len - 1] = '\0'; + + prefix = setparams_prefix (argc - 1, args); + if (! prefix) + return grub_errno; + + r = grub_normal_add_menu_entry (argc - 1, (const char **) args, + ctxt->state[0].args, ctxt->state[1].arg, + ctxt->state[2].arg, prefix, src + 1, + ctxt->extcmd->cmd->name[0] == 's'); + + src[len - 1] = ch; + args[argc - 1] = src; + grub_free (prefix); + return r; +} + +static grub_extcmd_t cmd, cmd_sub; + +void +grub_menu_init (void) +{ + cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_FLAG_EXTRACTOR, + N_("BLOCK"), N_("Define a menuentry."), options); + cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_FLAG_EXTRACTOR, + N_("BLOCK"), N_("Define a submenu."), + options); +} + +void +grub_menu_fini (void) +{ + grub_unregister_extcmd (cmd); + grub_unregister_extcmd (cmd_sub); +} diff --git a/commands/minicmd.c b/grub-core/commands/minicmd.c similarity index 64% rename from commands/minicmd.c rename to grub-core/commands/minicmd.c index d71174598..5cf109fde 100644 --- a/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -108,146 +108,6 @@ grub_rescue_cmd_info (void) } #endif -/* root [DEVICE] */ -static grub_err_t -grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_device_t dev; - grub_fs_t fs; - - if (argc > 0) - { - char *device_name = grub_file_get_device_name (argv[0]); - if (! device_name) - return grub_errno; - - grub_env_set ("root", device_name); - grub_free (device_name); - } - - dev = grub_device_open (0); - if (! dev) - return grub_errno; - - fs = grub_fs_probe (dev); - if (grub_errno == GRUB_ERR_UNKNOWN_FS) - grub_errno = GRUB_ERR_NONE; - - grub_printf ("(%s): Filesystem is %s.\n", - grub_env_get ("root"), fs ? fs->name : "unknown"); - - grub_device_close (dev); - - return 0; -} - -#if 0 -static void -grub_rescue_cmd_testload (int argc, char *argv[]) -{ - grub_file_t file; - char *buf; - grub_ssize_t size; - grub_ssize_t pos; - auto void read_func (unsigned long sector, unsigned offset, unsigned len); - - void read_func (unsigned long sector __attribute__ ((unused)), - unsigned offset __attribute__ ((unused)), - unsigned len __attribute__ ((unused))) - { - grub_putchar ('.'); - grub_refresh (); - } - - if (argc < 1) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); - return; - } - - file = grub_file_open (argv[0]); - if (! file) - return; - - size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1); - if (size == 0) - { - grub_file_close (file); - return; - } - - buf = grub_malloc (size); - if (! buf) - goto fail; - - grub_printf ("Reading %s sequentially", argv[0]); - file->read_hook = read_func; - if (grub_file_read (file, buf, size) != size) - goto fail; - grub_printf (" Done.\n"); - - /* Read sequentially again. */ - grub_printf ("Reading %s sequentially again", argv[0]); - if (grub_file_seek (file, 0) < 0) - goto fail; - - for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE) - { - char sector[GRUB_DISK_SECTOR_SIZE]; - - if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - goto fail; - - if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0) - { - grub_printf ("\nDiffers in %d\n", pos); - goto fail; - } - } - grub_printf (" Done.\n"); - - /* Read backwards and compare. */ - grub_printf ("Reading %s backwards", argv[0]); - pos = size; - while (pos > 0) - { - char sector[GRUB_DISK_SECTOR_SIZE]; - - pos -= GRUB_DISK_SECTOR_SIZE; - - if (grub_file_seek (file, pos) < 0) - goto fail; - - if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - goto fail; - - if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0) - { - int i; - - grub_printf ("\nDiffers in %d\n", pos); - - for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++) - grub_putchar (buf[pos + i]); - - if (i) - grub_refresh (); - - goto fail; - } - } - grub_printf (" Done.\n"); - - fail: - - grub_file_close (file); - grub_free (buf); -} -#endif - /* dump ADDRESS [SIZE] */ static grub_err_t grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), @@ -332,7 +192,7 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), return 0; } -static grub_command_t cmd_cat, cmd_help, cmd_root; +static grub_command_t cmd_cat, cmd_help; static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit; GRUB_MOD_INIT(minicmd) @@ -343,9 +203,6 @@ GRUB_MOD_INIT(minicmd) cmd_help = grub_register_command ("help", grub_mini_cmd_help, 0, N_("Show this message.")); - cmd_root = - grub_register_command ("root", grub_mini_cmd_root, - N_("[DEVICE]"), N_("Set the root device.")); cmd_dump = grub_register_command ("dump", grub_mini_cmd_dump, N_("ADDR"), N_("Dump memory.")); @@ -364,7 +221,6 @@ GRUB_MOD_FINI(minicmd) { grub_unregister_command (cmd_cat); grub_unregister_command (cmd_help); - grub_unregister_command (cmd_root); grub_unregister_command (cmd_dump); grub_unregister_command (cmd_rmmod); grub_unregister_command (cmd_lsmod); diff --git a/commands/mips/yeeloong/lsspd.c b/grub-core/commands/mips/yeeloong/lsspd.c similarity index 100% rename from commands/mips/yeeloong/lsspd.c rename to grub-core/commands/mips/yeeloong/lsspd.c diff --git a/commands/parttool.c b/grub-core/commands/parttool.c similarity index 99% rename from commands/parttool.c rename to grub-core/commands/parttool.c index 528cf43d7..31e768553 100644 --- a/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -175,7 +175,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"); @@ -233,7 +233,6 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), /* Ignore errors. */ grub_errno = GRUB_ERR_NONE; } -#endif if (argc == 1) return show_help (); @@ -276,7 +275,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), if (! parsed[j]) { for (curarg = ptool->args; curarg->name; curarg++) - if (grub_strncmp (curarg->name, args[i], + if (grub_strncmp (curarg->name, args[j], grub_strlen (curarg->name)) == 0 && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL && (args[j][grub_strlen (curarg->name)] == '+' diff --git a/commands/password.c b/grub-core/commands/password.c similarity index 87% rename from commands/password.c rename to grub-core/commands/password.c index 04285254e..db5951cbb 100644 --- a/commands/password.c +++ b/grub-core/commands/password.c @@ -40,26 +40,22 @@ check_password (const char *user, const char *entered, return GRUB_ERR_NONE; } -static grub_err_t -grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) +grub_err_t +grub_normal_set_password (const char *user, const char *password) { grub_err_t err; char *pass; int copylen; - if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); - pass = grub_zalloc (GRUB_AUTH_MAX_PASSLEN); if (!pass) return grub_errno; - copylen = grub_strlen (args[1]); + copylen = grub_strlen (password); if (copylen >= GRUB_AUTH_MAX_PASSLEN) copylen = GRUB_AUTH_MAX_PASSLEN - 1; - grub_memcpy (pass, args[1], copylen); + grub_memcpy (pass, password, copylen); - err = grub_auth_register_authentication (args[0], check_password, pass); + err = grub_auth_register_authentication (user, check_password, pass); if (err) { grub_free (pass); @@ -69,6 +65,15 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); + return grub_normal_set_password (args[0], args[1]); +} + static grub_command_t cmd; GRUB_MOD_INIT(password) diff --git a/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c similarity index 100% rename from commands/password_pbkdf2.c rename to grub-core/commands/password_pbkdf2.c diff --git a/commands/probe.c b/grub-core/commands/probe.c similarity index 95% rename from commands/probe.c rename to grub-core/commands/probe.c index c2cc599e9..abe84895d 100644 --- a/commands/probe.c +++ b/grub-core/commands/probe.c @@ -45,9 +45,9 @@ static const struct grub_arg_option options[] = }; static grub_err_t -grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_device_t dev; grub_fs_t fs; char *ptr; @@ -150,8 +150,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (probe) { - cmd = grub_register_extcmd ("probe", grub_cmd_probe, GRUB_COMMAND_FLAG_BOTH, - N_("[DEVICE]"), + cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("[DEVICE]"), N_("Retrieve device info."), options); } diff --git a/commands/read.c b/grub-core/commands/read.c similarity index 100% rename from commands/read.c rename to grub-core/commands/read.c diff --git a/commands/reboot.c b/grub-core/commands/reboot.c similarity index 100% rename from commands/reboot.c rename to grub-core/commands/reboot.c diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c new file mode 100644 index 000000000..f27a147af --- /dev/null +++ b/grub-core/commands/regexp.c @@ -0,0 +1,150 @@ +/* regexp.c -- The regexp command. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,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 +#include +#include +#include +#include +#include +#include +#include + +static const struct grub_arg_option options[] = + { + { "set", 's', GRUB_ARG_OPTION_REPEATABLE, + N_("Variable names to update with matches."), + N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING }, + { 0, 0, 0, 0, 0, 0 } + }; + +static grub_err_t +set_matches (char **varnames, char *str, grub_size_t nmatches, + regmatch_t *matches) +{ + int i; + char ch; + char *p; + char *q; + grub_err_t err; + unsigned long j; + + auto void setvar (char *v, regmatch_t *m); + void setvar (char *v, regmatch_t *m) + { + 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++) + { + if (! (p = grub_strchr (varnames[i], ':'))) + { + /* varname w/o index defaults to 1 */ + if (nmatches < 2 || matches[1].rm_so == -1) + grub_env_unset (varnames[i]); + else + setvar (varnames[i], &matches[1]); + } + else + { + j = grub_strtoul (varnames[i], &q, 10); + if (q != p) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid variable name format %s", varnames[i]); + + if (nmatches <= j || matches[j].rm_so == -1) + grub_env_unset (p + 1); + else + setvar (p + 1, &matches[j]); + } + + if (err != GRUB_ERR_NONE) + return err; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args) +{ + int argn = 0; + regex_t regex; + int ret; + grub_size_t s; + char *comperr; + grub_err_t err; + regmatch_t *matches = 0; + + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected"); + + ret = regcomp (®ex, args[0], REG_EXTENDED); + if (ret) + goto fail; + + matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1)); + if (! matches) + goto fail; + + ret = regexec (®ex, args[1], regex.re_nsub + 1, matches, 0); + if (!ret) + { + err = set_matches (ctxt->state[0].args, args[1], + regex.re_nsub + 1, matches); + regfree (®ex); + grub_free (matches); + return err; + } + + fail: + grub_free (matches); + s = regerror (ret, ®ex, 0, 0); + comperr = grub_malloc (s); + if (!comperr) + { + regfree (®ex); + return grub_errno; + } + regerror (ret, ®ex, comperr, s); + err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr); + regfree (®ex); + grub_free (comperr); + return err; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(regexp) +{ + cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, 0, N_("REGEXP STRING"), + N_("Test if REGEXP matches STRING."), options); + + /* Setup GRUB script wildcard translator. */ + grub_wildcard_translator = &grub_filename_translator; +} + +GRUB_MOD_FINI(regexp) +{ + grub_unregister_extcmd (cmd); + grub_wildcard_translator = 0; +} diff --git a/commands/search.c b/grub-core/commands/search.c similarity index 69% rename from commands/search.c rename to grub-core/commands/search.c index 71267b117..f265f86d6 100644 --- a/commands/search.c +++ b/grub-core/commands/search.c @@ -28,9 +28,12 @@ #include #include #include +#include +#include void -FUNC_NAME (const char *key, const char *var, int no_floppy) +FUNC_NAME (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints) { int count = 0; grub_fs_autoload_hook_t saved_autoload; @@ -54,6 +57,7 @@ FUNC_NAME (const char *key, const char *var, int no_floppy) if (! buf) return 1; + grub_file_filter_disable_compression (); file = grub_file_open (buf); if (file) { @@ -113,22 +117,86 @@ FUNC_NAME (const char *key, const char *var, int no_floppy) return (found && var); } + auto int part_hook (grub_disk_t disk, const grub_partition_t partition); + int part_hook (grub_disk_t disk, const grub_partition_t partition) + { + char *partition_name, *devname; + int ret; + + partition_name = grub_partition_get_name (partition); + if (! partition_name) + return 1; + + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 1; + ret = iterate_device (devname); + grub_free (devname); + + return ret; + } + + auto void try (void); + void try (void) + { + unsigned i; + 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) + { + *end = ','; + continue; + } + if (!dev->disk) + { + grub_device_close (dev); + *end = ','; + continue; + } + ret = grub_partition_iterate (dev->disk, part_hook); + *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; - grub_device_iterate (iterate_device); + try (); /* Restore autoload hook. */ grub_fs_autoload_hook = saved_autoload; /* Retry with autoload if nothing found. */ if (grub_errno == GRUB_ERR_NONE && count == 0) - grub_device_iterate (iterate_device); + try (); } else - grub_device_iterate (iterate_device); + try (); if (grub_errno == GRUB_ERR_NONE && count == 0) grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); @@ -141,7 +209,8 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc, if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); - FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0); + FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2), + argc > 2 ? argc - 2 : 0); return grub_errno; } @@ -158,7 +227,7 @@ GRUB_MOD_INIT(search_label) { cmd = grub_register_command (COMMAND_NAME, grub_cmd_do_search, - N_("NAME [VARIABLE]"), + N_("NAME [VARIABLE] [HINTS]"), HELP_MESSAGE); } diff --git a/commands/search_file.c b/grub-core/commands/search_file.c similarity index 100% rename from commands/search_file.c rename to grub-core/commands/search_file.c diff --git a/commands/search_label.c b/grub-core/commands/search_label.c similarity index 100% rename from commands/search_label.c rename to grub-core/commands/search_label.c diff --git a/commands/search_uuid.c b/grub-core/commands/search_uuid.c similarity index 100% rename from commands/search_uuid.c rename to grub-core/commands/search_uuid.c diff --git a/commands/search_wrap.c b/grub-core/commands/search_wrap.c similarity index 79% rename from commands/search_wrap.c rename to grub-core/commands/search_wrap.c index 2891d85d7..80741d7ab 100644 --- a/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -37,6 +37,9 @@ static const struct grub_arg_option options[] = {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING}, {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, + {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -47,13 +50,19 @@ enum options SEARCH_FS_UUID, SEARCH_SET, SEARCH_NO_FLOPPY, + SEARCH_HINT }; static grub_err_t -grub_cmd_search (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; const char *var = 0; + int nhints = 0; + + if (state[SEARCH_HINT].set) + while (state[SEARCH_HINT].args[nhints]) + nhints++; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); @@ -62,11 +71,14 @@ grub_cmd_search (grub_extcmd_t cmd, int argc, char **args) var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root"; if (state[SEARCH_LABEL].set) - grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set, + state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FS_UUID].set) - grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set, + state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FILE].set) - grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set, + state[SEARCH_HINT].args, nhints); else return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); @@ -78,9 +90,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(search) { cmd = - grub_register_extcmd ("search", grub_cmd_search, - GRUB_COMMAND_FLAG_BOTH, - N_("search [-f|-l|-u|-s|-n] NAME"), + grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR, + N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" + " NAME"), N_("Search devices by file, filesystem label" " or filesystem UUID." " If --set is specified, the first device found is" diff --git a/commands/setpci.c b/grub-core/commands/setpci.c similarity index 96% rename from commands/setpci.c rename to grub-core/commands/setpci.c index aa09f5bbb..7b194ed17 100644 --- a/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -155,7 +155,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) } static grub_err_t -grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) { const char *ptr; unsigned i; @@ -163,14 +163,14 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) pciid_check_value = 0; pciid_check_mask = 0; - if (cmd->state[0].set) + if (ctxt->state[0].set) { - ptr = cmd->state[0].arg; + ptr = ctxt->state[0].arg; pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; - ptr = cmd->state[0].arg; + ptr = ctxt->state[0].arg; } else pciid_check_mask |= 0xffff; @@ -191,11 +191,11 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) check_bus = check_device = check_function = 0; - if (cmd->state[1].set) + if (ctxt->state[1].set) { const char *optr; - ptr = cmd->state[1].arg; + ptr = ctxt->state[1].arg; optr = ptr; bus = grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno == GRUB_ERR_BAD_NUMBER) @@ -229,8 +229,8 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) } } - if (cmd->state[2].set) - varname = cmd->state[2].arg; + if (ctxt->state[2].set) + varname = ctxt->state[2].arg; else varname = NULL; @@ -329,7 +329,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(setpci) { - cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0, N_("[-s POSITION] [-d DEVICE] [-v VAR] " "[REGISTER][=VALUE[:MASK]]"), N_("Manipulate PCI devices."), options); diff --git a/commands/sleep.c b/grub-core/commands/sleep.c similarity index 89% rename from commands/sleep.c rename to grub-core/commands/sleep.c index ead279506..da642fcd9 100644 --- a/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -52,17 +52,16 @@ grub_interruptible_millisleep (grub_uint32_t ms) start = grub_get_time_ms (); while (grub_get_time_ms () - start < ms) - if (grub_checkkey () >= 0 && - GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC) + if (grub_checkkey () >= 0 && grub_getkey () == GRUB_TERM_ESC) return 1; return 0; } static grub_err_t -grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int n; if (argc != 1) @@ -101,7 +100,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(sleep) { - cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, 0, N_("NUMBER_OF_SECONDS"), N_("Wait for a specified number of seconds."), options); diff --git a/commands/terminal.c b/grub-core/commands/terminal.c similarity index 92% rename from commands/terminal.c rename to grub-core/commands/terminal.c index d34602a1b..c8b1b6315 100644 --- a/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -59,11 +59,17 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, for (aut = autoloads; aut; aut = aut->next) { for (term = *disabled; term; term = term->next) - if (grub_strcmp (term->name, aut->name) == 0) + if (grub_strcmp (term->name, aut->name) == 0 + || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' + && grub_memcmp (term->name, aut->name, + grub_strlen (aut->name) - 1) == 0)) break; if (!term) for (term = *enabled; term; term = term->next) - if (grub_strcmp (term->name, aut->name) == 0) + if (grub_strcmp (term->name, aut->name) == 0 + || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' + && grub_memcmp (term->name, aut->name, + grub_strlen (aut->name) - 1) == 0)) break; if (!term) grub_printf ("%s ", aut->name); @@ -98,7 +104,10 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", args[i]); for (aut = autoloads; aut; aut = aut->next) - if (grub_strcmp (args[i], aut->name) == 0) + if (grub_strcmp (args[i], aut->name) == 0 + || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' + && grub_memcmp (args[i], aut->name, + grub_strlen (aut->name) - 1) == 0)) { grub_dl_t mod; mod = grub_dl_load (aut->modname); diff --git a/commands/test.c b/grub-core/commands/test.c similarity index 98% rename from commands/test.c rename to grub-core/commands/test.c index 6995165cf..e981c945a 100644 --- a/commands/test.c +++ b/grub-core/commands/test.c @@ -334,6 +334,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn], "-s") == 0) { grub_file_t file; + grub_file_filter_disable_compression (); file = grub_file_open (args[*argn + 1]); update_val (file && (grub_file_size (file) != 0)); if (file) @@ -422,8 +423,10 @@ GRUB_MOD_INIT(test) { cmd_1 = grub_register_command ("[", grub_cmd_test, N_("EXPRESSION ]"), N_("Evaluate an expression.")); + cmd_1->flags |= GRUB_COMMAND_FLAG_EXTRACTOR; cmd_2 = grub_register_command ("test", grub_cmd_test, N_("EXPRESSION"), N_("Evaluate an expression.")); + cmd_2->flags |= GRUB_COMMAND_FLAG_EXTRACTOR; } GRUB_MOD_FINI(test) diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c new file mode 100644 index 000000000..86b8a9253 --- /dev/null +++ b/grub-core/commands/testload.c @@ -0,0 +1,155 @@ +/* testload.c - load the same file in multiple ways */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007,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 +#include +#include + +static grub_err_t +grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file; + 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, "no file specified"); + + file = grub_file_open (argv[0]); + if (! file) + return grub_errno; + + size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1); + if (size == 0) + { + grub_file_close (file); + return GRUB_ERR_NONE; + } + + buf = grub_malloc (size); + if (! buf) + goto fail; + + grub_printf ("Reading %s sequentially", argv[0]); + file->read_hook = read_func; + if (grub_file_read (file, buf, size) != (grub_ssize_t) size) + goto fail; + grub_printf (" Done.\n"); + + /* Read sequentially again. */ + grub_printf ("Reading %s sequentially again", argv[0]); + grub_file_seek (file, 0); + + for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE) + { + char sector[GRUB_DISK_SECTOR_SIZE]; + + if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE) + != GRUB_DISK_SECTOR_SIZE) + goto fail; + + if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0) + { + grub_printf ("\nDiffers in %lld\n", (unsigned long long) pos); + goto fail; + } + } + grub_printf (" Done.\n"); + + /* Read backwards and compare. */ + grub_printf ("Reading %s backwards", argv[0]); + pos = size; + while (pos > 0) + { + char sector[GRUB_DISK_SECTOR_SIZE]; + + pos -= GRUB_DISK_SECTOR_SIZE; + + grub_file_seek (file, pos); + + if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE) + != GRUB_DISK_SECTOR_SIZE) + goto fail; + + if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0) + { + int i; + + grub_printf ("\nDiffers in %lld\n", (unsigned long long) pos); + + for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++) + { + grub_printf ("%02x ", buf[pos + i]); + if ((i & 15) == 15) + grub_printf ("\n"); + } + + if (i) + grub_refresh (); + + goto fail; + } + } + grub_printf (" Done.\n"); + + return GRUB_ERR_NONE; + + fail: + + grub_file_close (file); + grub_free (buf); + + if (!grub_errno) + grub_error (GRUB_ERR_IO, "bad read"); + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(testload) +{ + cmd = + grub_register_command ("testload", grub_cmd_testload, + N_("FILE"), + N_("Load the same file in multiple ways.")); +} + +GRUB_MOD_FINI(testload) +{ + grub_unregister_command (cmd); +} diff --git a/commands/true.c b/grub-core/commands/true.c similarity index 100% rename from commands/true.c rename to grub-core/commands/true.c diff --git a/commands/usbtest.c b/grub-core/commands/usbtest.c similarity index 90% rename from commands/usbtest.c rename to grub-core/commands/usbtest.c index 213288b52..7f00c8856 100644 --- a/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -29,11 +29,11 @@ static const char *usb_classes[] = { - "", + "Unknown", "Audio", "Communication Interface", "HID", - "", + "Unknown", "Physical", "Image", "Printer", @@ -138,10 +138,10 @@ usb_iterate (grub_usb_device_t dev) usb_print_str ("Vendor", dev, descdev->strvendor); usb_print_str ("Serial", dev, descdev->strserial); - if (descdev->class > 0 && descdev->class <= 0x0E) - grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n", - descdev->class, usb_classes[descdev->class], - descdev->subclass, descdev->protocol); + grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n", + descdev->class, descdev->class < ARRAY_SIZE (usb_classes) + ? usb_classes[descdev->class] : "Unknown", + descdev->subclass, descdev->protocol); grub_printf ("USB version %d.%d, VendorID: 0x%02x, ProductID: 0x%02x, #conf: %d\n", descdev->usbrel >> 8, (descdev->usbrel >> 4) & 0x0F, descdev->vendorid, descdev->prodid, descdev->configcnt); @@ -164,10 +164,10 @@ usb_iterate (grub_usb_device_t dev) grub_printf ("Interface #%d: #Endpoints: %d ", i, interf->endpointcnt); - if (interf->class > 0 && interf->class <= 0x0E) - grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n", - interf->class, usb_classes[interf->class], - interf->subclass, interf->protocol); + grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n", + interf->class, interf->class < ARRAY_SIZE (usb_classes) + ? usb_classes[interf->class] : "Unknown", + interf->subclass, interf->protocol); usb_print_str ("Interface", dev, interf->strif); diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c new file mode 100644 index 000000000..10f77915b --- /dev/null +++ b/grub-core/commands/videoinfo.c @@ -0,0 +1,184 @@ +/* videoinfo.c - command to list video modes. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,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 + +static unsigned height, width, depth; + +static int +hook (const struct grub_video_mode_info *info) +{ + if (height && width && (info->width != width || info->height != height)) + return 0; + + if (depth && info->bpp != depth) + return 0; + + if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) + grub_printf (" "); + else + grub_printf (" 0x%03x ", info->mode_number); + grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); + + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) + grub_printf ("Text-only "); + /* Show mask and position details for direct color modes. */ + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) + grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", + info->red_mask_size, + info->green_mask_size, + info->blue_mask_size, + info->reserved_mask_size, + info->red_field_pos, + info->green_field_pos, + info->blue_field_pos, + info->reserved_field_pos); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + grub_printf ("Packed "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) + grub_printf ("YUV "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) + grub_printf ("Planar "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES) + grub_printf ("Hercules "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA) + grub_printf ("CGA "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4) + grub_printf ("Non-chain 4 "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) + grub_printf ("Monochrome "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN) + grub_printf ("Unknown "); + + grub_printf ("\n"); + + return 0; +} + +static grub_err_t +grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_video_adapter_t adapter; + grub_video_driver_id_t id; + + height = width = depth = 0; + if (argc) + { + char *ptr; + ptr = args[0]; + width = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr != 'x') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid mode specification"); + ptr++; + height = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr == 'x') + { + ptr++; + depth = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + } + } + +#ifdef GRUB_MACHINE_PCBIOS + if (grub_strcmp (cmd->name, "vbeinfo") == 0) + grub_dl_load ("vbe"); +#endif + + id = grub_video_get_driver_id (); + + grub_printf ("List of supported video modes:\n"); + grub_printf ("Legend: P=Packed pixel, D=Direct color, " + "mask/pos=R/G/B/reserved\n"); + + FOR_VIDEO_ADAPTERS (adapter) + { + grub_printf ("Adapter '%s':\n", adapter->name); + + if (!adapter->iterate) + { + grub_printf (" No info available\n"); + continue; + } + + if (adapter->id != id) + { + if (adapter->init ()) + { + grub_printf (" Failed\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } + } + + if (adapter->print_adapter_specific_info) + adapter->print_adapter_specific_info (); + + adapter->iterate (hook); + + if (adapter->id != id) + { + if (adapter->fini ()) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + } + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; +#ifdef GRUB_MACHINE_PCBIOS +static grub_command_t cmd_vbe; +#endif + +GRUB_MOD_INIT(videoinfo) +{ + cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]", + N_("List available video modes. If " + "resolution is given show only modes" + " matching it.")); +#ifdef GRUB_MACHINE_PCBIOS + cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]", + N_("List available video modes. If " + "resolution is given show only modes" + " matching it.")); +#endif +} + +GRUB_MOD_FINI(videoinfo) +{ + grub_unregister_command (cmd); +#ifdef GRUB_MACHINE_PCBIOS + grub_unregister_command (cmd_vbe); +#endif +} + diff --git a/commands/videotest.c b/grub-core/commands/videotest.c similarity index 90% rename from commands/videotest.c rename to grub-core/commands/videotest.c index c544d1839..435ac2937 100644 --- a/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -26,11 +26,11 @@ #include #include #include +#include static grub_err_t grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) + int argc, char **args) { grub_err_t err; grub_video_color_t color; @@ -41,8 +41,20 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), int i; struct grub_video_render_target *text_layer; grub_video_color_t palette[16]; + const char *mode = NULL; - err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); +#ifdef GRUB_MACHINE_PCBIOS + if (grub_strcmp (cmd->name, "vbetest") == 0) + grub_dl_load ("vbe"); +#endif + + mode = grub_env_get ("gfxmode"); + if (argc) + mode = args[0]; + if (!mode) + mode = "auto"; + + err = grub_video_set_mode (mode, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); if (err) return err; @@ -180,14 +192,25 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), } static grub_command_t cmd; +#ifdef GRUB_MACHINE_PCBIOS +static grub_command_t cmd_vbe; +#endif GRUB_MOD_INIT(videotest) { cmd = grub_register_command ("videotest", grub_cmd_videotest, + "[WxH]", + N_("Test video subsystem in mode WxH.")); +#ifdef GRUB_MACHINE_PCBIOS + cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest, 0, N_("Test video subsystem.")); +#endif } GRUB_MOD_FINI(videotest) { grub_unregister_command (cmd); +#ifdef GRUB_MACHINE_PCBIOS + grub_unregister_command (cmd_vbe); +#endif } diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c new file mode 100644 index 000000000..6eab333b3 --- /dev/null +++ b/grub-core/commands/wildcard.c @@ -0,0 +1,498 @@ +/* wildcard.c - Wildcard character expansion for GRUB script. */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include + +static inline int isregexop (char ch); +static char ** merge (char **lhs, char **rhs); +static char *make_dir (const char *prefix, const char *start, const char *end); +static int make_regex (const char *regex_start, const char *regex_end, + regex_t *regexp); +static void split_path (const char *path, const char **suffix_end, const char **regex_end); +static char ** match_devices (const regex_t *regexp, int noparts); +static char ** match_files (const char *prefix, const char *suffix_start, + const char *suffix_end, const regex_t *regexp); + +static char* wildcard_escape (const char *s); +static char* wildcard_unescape (const char *s); +static grub_err_t wildcard_expand (const char *s, char ***strs); + +struct grub_script_wildcard_translator grub_filename_translator = { + .expand = wildcard_expand, + .escape = wildcard_escape, + .unescape = wildcard_unescape +}; + +static char ** +merge (char **dest, char **ps) +{ + int i; + int j; + char **p; + + if (! dest) + return ps; + + if (! ps) + return dest; + + for (i = 0; dest[i]; i++) + ; + for (j = 0; ps[j]; j++) + ; + + p = grub_realloc (dest, sizeof (char*) * (i + j + 1)); + if (! p) + { + grub_free (dest); + grub_free (ps); + return 0; + } + + dest = p; + for (j = 0; ps[j]; j++) + dest[i++] = ps[j]; + dest[i] = 0; + + grub_free (ps); + return dest; +} + +static inline int +isregexop (char ch) +{ + return grub_strchr ("*.\\", ch) ? 1 : 0; +} + +static char * +make_dir (const char *prefix, const char *start, const char *end) +{ + char ch; + unsigned i; + unsigned n; + char *result; + + i = grub_strlen (prefix); + n = i + end - start; + + result = grub_malloc (n + 1); + if (! result) + return 0; + + grub_strcpy (result, prefix); + while (start < end && (ch = *start++)) + if (ch == '\\' && isregexop (*start)) + result[i++] = *start++; + else + result[i++] = ch; + + result[i] = '\0'; + return result; +} + +static int +make_regex (const char *start, const char *end, regex_t *regexp) +{ + char ch; + int i = 0; + unsigned len = end - start; + char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */ + + if (! buffer) + return 1; + + buffer[i++] = '^'; + while (start < end) + { + /* XXX Only * expansion for now. */ + switch ((ch = *start++)) + { + case '\\': + buffer[i++] = ch; + if (*start != '\0') + buffer[i++] = *start++; + break; + + case '.': + case '(': + case ')': + buffer[i++] = '\\'; + buffer[i++] = ch; + break; + + case '*': + buffer[i++] = '.'; + buffer[i++] = '*'; + break; + + default: + buffer[i++] = ch; + } + } + buffer[i++] = '$'; + buffer[i] = '\0'; + grub_dprintf ("expand", "Regexp is %s\n", buffer); + + if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK)) + { + grub_free (buffer); + return 1; + } + + grub_free (buffer); + return 0; +} + +/* Split `str' into two parts: (1) dirname that is regexop free (2) + dirname that has a regexop. */ +static void +split_path (const char *str, const char **noregexop, const char **regexop) +{ + char ch = 0; + int regex = 0; + + const char *end; + const char *split; /* points till the end of dirnaname that doesn't + need expansion. */ + + split = end = str; + while ((ch = *end)) + { + if (ch == '\\' && end[1]) + end++; + + else if (isregexop (ch)) + regex = 1; + + else if (ch == '/' && ! regex) + split = end + 1; /* forward to next regexop-free dirname */ + + else if (ch == '/' && regex) + break; /* stop at the first dirname with a regexop */ + + end++; + } + + *regexop = end; + if (! regex) + *noregexop = end; + else + *noregexop = split; +} + +static char ** +match_devices (const regex_t *regexp, int noparts) +{ + int i; + int ndev; + char **devs; + + auto int match (const char *name); + int match (const char *name) + { + char **t; + char *buffer; + + /* skip partitions if asked to. */ + if (noparts && grub_strchr(name, ',')) + return 0; + + buffer = grub_xasprintf ("(%s)", name); + if (! buffer) + return 1; + + grub_dprintf ("expand", "matching: %s\n", buffer); + if (regexec (regexp, buffer, 0, 0, 0)) + { + grub_dprintf ("expand", "not matched\n"); + grub_free (buffer); + return 0; + } + + t = grub_realloc (devs, sizeof (char*) * (ndev + 2)); + if (! t) + return 1; + + devs = t; + devs[ndev++] = buffer; + devs[ndev] = 0; + return 0; + } + + ndev = 0; + devs = 0; + + if (grub_device_iterate (match)) + goto fail; + + return devs; + + fail: + + for (i = 0; devs && devs[i]; i++) + grub_free (devs[i]); + + if (devs) + grub_free (devs); + + return 0; +} + +static char ** +match_files (const char *prefix, const char *suffix, const char *end, + const regex_t *regexp) +{ + int i; + int error; + 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; + + buffer = grub_xasprintf ("%s%s", dir, name); + if (! buffer) + return 1; + + t = grub_realloc (files, sizeof (char*) * (nfile + 2)); + if (! t) + { + grub_free (buffer); + return 1; + } + + files = t; + files[nfile++] = buffer; + files[nfile] = 0; + return 0; + } + + nfile = 0; + files = 0; + dev = 0; + device_name = 0; + grub_error_push (); + + dir = make_dir (prefix, suffix, end); + if (! dir) + goto fail; + + 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; + + path = grub_strchr (dir, ')'); + if (! path) + goto fail; + path++; + + 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: + + if (dir) + grub_free (dir); + + for (i = 0; files && files[i]; i++) + grub_free (files[i]); + + if (files) + grub_free (files); + + if (dev) + grub_device_close (dev); + + if (device_name) + grub_free (device_name); + + grub_error_pop (); + return 0; +} + +static char* +wildcard_escape (const char *s) +{ + int i; + int len; + char ch; + char *p; + + len = grub_strlen (s); + p = grub_malloc (len * 2 + 1); + if (! p) + return NULL; + + i = 0; + while ((ch = *s++)) + { + if (isregexop (ch)) + p[i++] = '\\'; + p[i++] = ch; + } + p[i] = '\0'; + return p; +} + +static char* +wildcard_unescape (const char *s) +{ + int i; + int len; + char ch; + char *p; + + len = grub_strlen (s); + p = grub_malloc (len + 1); + if (! p) + return NULL; + + i = 0; + while ((ch = *s++)) + { + if (ch == '\\' && isregexop (*s)) + p[i++] = *s++; + else + p[i++] = ch; + } + p[i] = '\0'; + return p; +} + +static grub_err_t +wildcard_expand (const char *s, char ***strs) +{ + const char *start; + const char *regexop; + const char *noregexop; + char **paths = 0; + + unsigned i; + regex_t regexp; + + start = s; + while (*start) + { + split_path (start, &noregexop, ®exop); + if (noregexop >= regexop) /* no more wildcards */ + break; + + if (make_regex (noregexop, regexop, ®exp)) + goto fail; + + if (paths == 0) + { + if (start == noregexop) /* device part has regexop */ + paths = match_devices (®exp, *start != '('); + + else if (*start == '(') /* device part explicit wo regexop */ + paths = match_files ("", start, noregexop, ®exp); + + else if (*start == '/') /* no device part */ + { + char **r; + unsigned n; + char *root; + char *prefix; + + root = grub_env_get ("root"); + if (! root) + goto fail; + + prefix = grub_xasprintf ("(%s)", root); + if (! prefix) + goto fail; + + paths = match_files (prefix, start, noregexop, ®exp); + grub_free (prefix); + } + } + else + { + char **r = 0; + + for (i = 0; paths[i]; i++) + { + char **p; + + p = match_files (paths[i], start, noregexop, ®exp); + if (! p) + continue; + + r = merge (r, p); + if (! r) + goto fail; + } + paths = r; + } + + regfree (®exp); + if (! paths) + goto done; + + start = regexop; + } + + done: + + *strs = paths; + return 0; + + fail: + + for (i = 0; paths && paths[i]; i++) + grub_free (paths[i]); + grub_free (paths); + regfree (®exp); + return grub_errno; +} diff --git a/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c similarity index 100% rename from commands/xnu_uuid.c rename to grub-core/commands/xnu_uuid.c diff --git a/disk/ata.c b/grub-core/disk/ata.c similarity index 99% rename from disk/ata.c rename to grub-core/disk/ata.c index cfd58a6d5..fe677e2a0 100644 --- a/disk/ata.c +++ b/grub-core/disk/ata.c @@ -723,7 +723,6 @@ grub_ata_open (const char *name, grub_disk_t disk) disk->id = (unsigned long) dev; - disk->has_partitions = 1; disk->data = dev; return 0; diff --git a/disk/ata_pthru.c b/grub-core/disk/ata_pthru.c similarity index 100% rename from disk/ata_pthru.c rename to grub-core/disk/ata_pthru.c diff --git a/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c similarity index 100% rename from disk/dmraid_nvidia.c rename to grub-core/disk/dmraid_nvidia.c diff --git a/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c similarity index 98% rename from disk/efi/efidisk.c rename to grub-core/disk/efi/efidisk.c index f9c6f3153..08094fa5c 100644 --- a/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -514,16 +514,12 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) switch (name[0]) { case 'f': - disk->has_partitions = 0; d = get_device (fd_devices, num); break; case 'c': - /* FIXME: a CDROM should have partitions, but not implemented yet. */ - disk->has_partitions = 0; d = get_device (cd_devices, num); break; case 'h': - disk->has_partitions = 1; d = get_device (hd_devices, num); break; default: @@ -731,7 +727,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) { /* This is a hard disk partition. */ grub_disk_t parent = 0; - char *partition_name = 0; + grub_partition_t tpart = NULL; char *device_name; grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_hard_drive_device_path_t hd; @@ -770,7 +766,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (grub_partition_get_start (part) == hd.partition_start && grub_partition_get_len (part) == hd.partition_size) { - partition_name = grub_partition_get_name (part); + tpart = part; return 1; } @@ -799,14 +795,17 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) grub_memcpy (&hd, ldp, sizeof (hd)); grub_partition_iterate (parent, find_partition); - if (! partition_name) + if (! tpart) { grub_disk_close (parent); return 0; } - device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); - grub_free (partition_name); + { + char *partition_name = grub_partition_get_name (tpart); + device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); + grub_free (partition_name); + } grub_disk_close (parent); return device_name; diff --git a/disk/host.c b/grub-core/disk/host.c similarity index 98% rename from disk/host.c rename to grub-core/disk/host.c index c4f3e7150..c51966293 100644 --- a/disk/host.c +++ b/grub-core/disk/host.c @@ -43,7 +43,6 @@ grub_host_open (const char *name, grub_disk_t disk) disk->total_sectors = 0; disk->id = (unsigned long) "host"; - disk->has_partitions = 0; disk->data = 0; return GRUB_ERR_NONE; diff --git a/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c similarity index 64% rename from disk/i386/pc/biosdisk.c rename to grub-core/disk/i386/pc/biosdisk.c index f82f91ff0..3f9015fb9 100644 --- a/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -17,8 +17,9 @@ */ #include -#include #include +#include +#include #include #include #include @@ -28,12 +29,228 @@ #include static int cd_drive = 0; +static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap); + +static int grub_biosdisk_get_num_floppies (void) +{ + struct grub_bios_int_registers regs; + int drive; + + /* reset the disk system first */ + regs.eax = 0; + regs.edx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + grub_bios_interrupt (0x13, ®s); + + for (drive = 0; drive < 2; drive++) + { + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT | GRUB_CPU_INT_FLAGS_CARRY; + regs.edx = drive; + + /* call GET DISK TYPE */ + regs.eax = 0x1500; + grub_bios_interrupt (0x13, ®s); + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + break; + + /* check if this drive exists */ + if (!(regs.eax & 0x300)) + break; + } + + return drive; +} + +/* + * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP + * is passed for disk address packet. If an error occurs, return + * non-zero, otherwise zero. + */ + +static int +grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) +{ + struct grub_bios_int_registers regs; + regs.eax = ah << 8; + /* compute the address of disk_address_packet */ + regs.ds = (((grub_addr_t) dap) & 0xffff0000) >> 4; + regs.esi = (((grub_addr_t) dap) & 0xffff); + regs.edx = drive; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + grub_bios_interrupt (0x13, ®s); + return (regs.eax >> 8) & 0xff; +} + +/* + * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write + * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, + * return non-zero, otherwise zero. + */ +static int +grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, + int soff, int nsec, int segment) +{ + int ret, i; + + /* Try 3 times. */ + for (i = 0; i < 3; i++) + { + struct grub_bios_int_registers regs; + + /* set up CHS information */ + /* set %ch to low eight bits of cylinder */ + regs.ecx = (coff << 8) & 0xff00; + /* set bits 6-7 of %cl to high two bits of cylinder */ + regs.ecx |= (coff >> 2) & 0xc0; + /* set bits 0-5 of %cl to sector */ + regs.ecx |= soff & 0x3f; + + /* set %dh to head and %dl to drive */ + regs.edx = (drive & 0xff) | ((hoff << 8) & 0xff00); + /* set %ah to AH */ + regs.eax = (ah << 8) & 0xff00; + /* set %al to NSEC */ + regs.eax |= nsec & 0xff; + + regs.ebx = 0; + regs.es = segment; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + grub_bios_interrupt (0x13, ®s); + /* check if successful */ + if (!(regs.flags & GRUB_CPU_INT_FLAGS_CARRY)) + return 0; + + /* save return value */ + ret = regs.eax >> 8; + + /* if fail, reset the disk system */ + regs.eax = 0; + regs.edx = (drive & 0xff); + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x13, ®s); + } + return ret; +} + +/* + * Check if LBA is supported for DRIVE. If it is supported, then return + * the major version of extensions, otherwise zero. + */ +static int +grub_biosdisk_check_int13_extensions (int drive) +{ + struct grub_bios_int_registers regs; + + regs.edx = drive & 0xff; + regs.eax = 0x4100; + regs.ebx = 0x55aa; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x13, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + + if ((regs.ebx & 0xffff) != 0xaa55) + return 0; + + /* check if AH=0x42 is supported */ + if (!(regs.ecx & 1)) + return 0; + + return (regs.eax >> 8) & 0xff; +} + +/* + * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an + * error occurs, then return non-zero, otherwise zero. + */ +static int +grub_biosdisk_get_diskinfo_standard (int drive, + unsigned long *cylinders, + unsigned long *heads, + unsigned long *sectors) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x0800; + regs.edx = drive & 0xff; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x13, ®s); + + /* Check if unsuccessful. Ignore return value if carry isn't set to + workaround some buggy BIOSes. */ + if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0)) + return (regs.eax & 0xff00) >> 8; + + /* bogus BIOSes may not return an error number */ + /* 0 sectors means no disk */ + if (!(regs.ecx & 0x3f)) + /* XXX 0x60 is one of the unused error numbers */ + return 0x60; + + /* the number of heads is counted from zero */ + *heads = ((regs.edx >> 8) & 0xff) + 1; + *cylinders = (((regs.ecx >> 8) & 0xff) | ((regs.ecx << 2) & 0x0300)) + 1; + *sectors = regs.ecx & 0x3f; + return 0; +} + +static int +grub_biosdisk_get_diskinfo_real (int drive, void *drp, grub_uint16_t ax) +{ + struct grub_bios_int_registers regs; + + regs.eax = ax; + + /* compute the address of drive parameters */ + regs.esi = ((grub_addr_t) drp) & 0xf; + regs.ds = ((grub_addr_t) drp) >> 4; + regs.edx = drive & 0xff; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x13, ®s); + + /* Check if unsuccessful. Ignore return value if carry isn't set to + workaround some buggy BIOSes. */ + if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0)) + return (regs.eax & 0xff00) >> 8; + + return 0; +} + +/* + * Return the cdrom information of DRIVE in CDRP. If an error occurs, + * then return non-zero, otherwise zero. + */ +static int +grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp) +{ + return grub_biosdisk_get_diskinfo_real (drive, cdrp, 0x4b01); +} + +/* + * Return the geometry of DRIVE in a drive parameters, DRP. If an error + * occurs, then return non-zero, otherwise zero. + */ +static int +grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp) +{ + return grub_biosdisk_get_diskinfo_real (drive, drp, 0x4800); +} static int grub_biosdisk_get_drive (const char *name) { unsigned long drive; + if (name[0] == 'c' && name[1] == 'd' && name[2] == 0 && cd_drive) + return cd_drive; + if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd') goto fail; @@ -56,6 +273,9 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) { char name[10]; + if (cd_drive && drive == cd_drive) + return hook ("cd"); + grub_snprintf (name, sizeof (name), (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); return hook (name); @@ -107,7 +327,6 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) if (drive < 0) return grub_errno; - disk->has_partitions = ((drive & 0x80) && (drive != cd_drive)); disk->id = drive; data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data)); @@ -123,7 +342,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) /* TODO: get the correct size. */ total_sectors = GRUB_DISK_SIZE_UNKNOWN; } - else if (drive & 0x80) + else { /* HDD */ int version; diff --git a/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c similarity index 99% rename from disk/ieee1275/nand.c rename to grub-core/disk/ieee1275/nand.c index df2ee81f3..a2c717cdb 100644 --- a/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -113,7 +113,6 @@ grub_nand_open (const char *name, grub_disk_t disk) disk->id = dev_ihandle; - disk->has_partitions = 0; disk->data = data; return 0; diff --git a/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c similarity index 53% rename from disk/ieee1275/ofdisk.c rename to grub-core/disk/ieee1275/ofdisk.c index d0d9e894f..85c34609e 100644 --- a/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -23,9 +23,15 @@ #include #include +static char *last_devpath; +static grub_ieee1275_ihandle_t last_ihandle; + struct ofdisk_hash_ent { char *devpath; + /* Pointer to shortest available name on nodes representing canonical names, + otherwise NULL. */ + const char *shortest; struct ofdisk_hash_ent *next; }; @@ -59,60 +65,125 @@ static struct ofdisk_hash_ent * ofdisk_hash_add (char *devpath) { struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)]; - struct ofdisk_hash_ent *p = grub_malloc(sizeof (*p)); + struct ofdisk_hash_ent *p, *pcan; + char *curcan; - if (p) + p = grub_malloc(sizeof (*p)); + if (!p) + return NULL; + + p->devpath = devpath; + p->next = *head; + p->shortest = 0; + *head = p; + + curcan = grub_ieee1275_canonicalise_devname (devpath); + if (!curcan) { - p->devpath = devpath; - p->next = *head; - *head = p; + grub_errno = GRUB_ERR_NONE; + return p; } + + pcan = ofdisk_hash_find (curcan); + if (!pcan) + pcan = ofdisk_hash_add (curcan); + else + grub_free (curcan); + + if (!pcan) + grub_errno = GRUB_ERR_NONE; + else + { + if (!pcan->shortest + || grub_strlen (pcan->shortest) > grub_strlen (devpath)) + pcan->shortest = devpath; + } + return p; } -static int -grub_ofdisk_iterate (int (*hook) (const char *name)) +static void +scan (void) { auto int dev_iterate (struct grub_ieee1275_devalias *alias); int dev_iterate (struct grub_ieee1275_devalias *alias) { - int ret = 0; + struct ofdisk_hash_ent *op; + + grub_dprintf ("disk", "device name = %s type = %s\n", alias->name, + alias->type); + + if (grub_strcmp (alias->type, "block") != 0) + return 0; grub_dprintf ("disk", "disk name = %s\n", alias->name); - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + op = ofdisk_hash_find (alias->path); + if (!op) { - grub_ieee1275_phandle_t dev; - char tmp[8]; - - if (grub_ieee1275_finddevice (alias->path, &dev)) + char *name = grub_strdup (alias->name); + if (!name) { - grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path); - return 0; - } - - if (grub_ieee1275_get_property (dev, "iconname", tmp, - sizeof tmp, 0)) - { - grub_dprintf ("disk", "get iconname failed\n"); - return 0; - } - - if (grub_strcmp (tmp, "sdmmc")) - { - grub_dprintf ("disk", "device is not an SD card\n"); + grub_errno = GRUB_ERR_NONE; return 0; } + op = ofdisk_hash_add (name); } - - if (! grub_strcmp (alias->type, "block") && - grub_strncmp (alias->name, "cdrom", 5)) - ret = hook (alias->name); - return ret; + return 0; } - return grub_devalias_iterate (dev_iterate); + grub_devalias_iterate (dev_iterate); + grub_ieee1275_devices_iterate (dev_iterate); +} + +static int +grub_ofdisk_iterate (int (*hook) (const char *name)) +{ + unsigned i; + scan (); + + for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++) + { + static struct ofdisk_hash_ent *ent; + for (ent = ofdisk_hash[i]; ent; ent = ent->next) + { + if (!ent->shortest) + continue; + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + { + grub_ieee1275_phandle_t dev; + char tmp[8]; + + if (grub_ieee1275_finddevice (ent->devpath, &dev)) + { + grub_dprintf ("disk", "finddevice (%s) failed\n", + ent->devpath); + continue; + } + + if (grub_ieee1275_get_property (dev, "iconname", tmp, + sizeof tmp, 0)) + { + grub_dprintf ("disk", "get iconname failed\n"); + continue; + } + + if (grub_strcmp (tmp, "sdmmc") != 0) + { + grub_dprintf ("disk", "device is not an SD card\n"); + continue; + } + } + + if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) + continue; + + if (hook (ent->shortest)) + return 1; + } + } + return 0; } static char * @@ -137,11 +208,6 @@ compute_dev_path (const char *name) *p++ = c; } - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) - { - *p++ = ':'; - *p++ = '0'; - } *p++ = '\0'; return devpath; @@ -151,8 +217,6 @@ static grub_err_t grub_ofdisk_open (const char *name, grub_disk_t disk) { grub_ieee1275_phandle_t dev; - grub_ieee1275_ihandle_t dev_ihandle = 0; - struct ofdisk_hash_ent *op; char *devpath; /* XXX: This should be large enough for any possible case. */ char prop[64]; @@ -162,69 +226,50 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) if (! devpath) return grub_errno; - op = ofdisk_hash_find (devpath); - if (!op) - op = ofdisk_hash_add (devpath); + grub_dprintf ("disk", "Opening `%s'.\n", devpath); - grub_free (devpath); - if (!op) - return grub_errno; - - grub_dprintf ("disk", "Opening `%s'.\n", op->devpath); - - if (grub_ieee1275_finddevice (op->devpath, &dev)) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); - goto fail; - } + if (grub_ieee1275_finddevice (devpath, &dev)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop), &actual)) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); - goto fail; - } + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); if (grub_strcmp (prop, "block")) - { - grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); - goto fail; - } - - grub_ieee1275_open (op->devpath, &dev_ihandle); - if (! dev_ihandle) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - goto fail; - } - - grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath, - (void *) (unsigned long) dev_ihandle); + return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it is possible to use seek for this. */ disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; - disk->id = (unsigned long) op; + { + struct ofdisk_hash_ent *op; + op = ofdisk_hash_find (devpath); + if (!op) + op = ofdisk_hash_add (devpath); + else + grub_free (devpath); + if (!op) + return grub_errno; + disk->id = (unsigned long) op; + disk->data = op->devpath; + } - /* XXX: Read this, somehow. */ - disk->has_partitions = 1; - disk->data = (void *) (unsigned long) dev_ihandle; return 0; - - fail: - if (dev_ihandle) - grub_ieee1275_close (dev_ihandle); - return grub_errno; } static void grub_ofdisk_close (grub_disk_t disk) { - grub_dprintf ("disk", "Closing handle %p.\n", - (void *) disk->data); - grub_ieee1275_close ((grub_ieee1275_ihandle_t) (unsigned long) disk->data); + if (disk->data == last_devpath) + { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + } + disk->data = 0; } static grub_err_t @@ -234,16 +279,40 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_ssize_t status, actual; unsigned long long pos; + if (disk->data != last_devpath) + { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) + { + char name2[grub_strlen (disk->data) + 3]; + char *p; + + grub_strcpy (name2, disk->data); + p = name2 + grub_strlen (name2); + *p++ = ':'; + *p++ = '0'; + *p = 0; + grub_ieee1275_open (name2, &last_ihandle); + } + else + grub_ieee1275_open (disk->data, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = disk->data; + } + pos = sector * 512UL; - grub_ieee1275_seek ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - pos, &status); + grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); - grub_ieee1275_read ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - buf, size * 512UL, &actual); + grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual); if (actual != (grub_ssize_t) (size * 512UL)) return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu", (long long) sector); @@ -281,5 +350,10 @@ grub_ofdisk_init (void) void grub_ofdisk_fini (void) { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + grub_disk_dev_unregister (&grub_ofdisk_dev); } diff --git a/disk/loopback.c b/grub-core/disk/loopback.c similarity index 89% rename from disk/loopback.c rename to grub-core/disk/loopback.c index 509e9e33f..ae4cb9a9c 100644 --- a/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -29,7 +29,6 @@ struct grub_loopback { char *devname; grub_file_t file; - int has_partitions; struct grub_loopback *next; }; @@ -38,7 +37,6 @@ static struct grub_loopback *loopback_list; static const struct grub_arg_option options[] = { {"delete", 'd', 0, N_("Delete the loopback device entry."), 0, 0}, - {"partitions", 'p', 0, N_("Simulate a hard drive with partitions."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -71,9 +69,9 @@ delete_loopback (const char *name) /* The command to add and remove loopback devices. */ static grub_err_t -grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; struct grub_loopback *newdev; grub_err_t ret; @@ -106,9 +104,6 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args) grub_file_close (newdev->file); newdev->file = file; - /* Set has_partitions when `--partitions' was used. */ - newdev->has_partitions = state[1].set; - return 0; } @@ -126,9 +121,6 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args) newdev->file = file; - /* Set has_partitions when `--partitions' was used. */ - newdev->has_partitions = state[1].set; - /* Add the new entry to the list. */ newdev->next = loopback_list; loopback_list = newdev; @@ -167,11 +159,13 @@ grub_loopback_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); /* Use the filesize for the disk size, round up to a complete sector. */ - disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1) - / GRUB_DISK_SECTOR_SIZE); + if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN) + disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1) + / GRUB_DISK_SECTOR_SIZE); + else + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; disk->id = (unsigned long) dev; - disk->has_partitions = dev->has_partitions; disk->data = dev->file; return 0; @@ -227,8 +221,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(loopback) { - cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0, N_("[-d|-p] DEVICENAME FILE."), N_("Make a device of a file."), options); grub_disk_dev_register (&grub_loopback_dev); diff --git a/disk/lvm.c b/grub-core/disk/lvm.c similarity index 89% rename from disk/lvm.c rename to grub-core/disk/lvm.c index 71860e853..39fa84d91 100644 --- a/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -150,7 +150,6 @@ grub_lvm_open (const char *name, grub_disk_t disk) if (! lv) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name); - disk->has_partitions = 0; disk->id = lv->number; disk->data = lv; disk->total_sectors = lv->size; @@ -260,7 +259,7 @@ grub_lvm_scan_device (const char *name) { grub_err_t err; grub_disk_t disk; - grub_uint64_t da_offset, da_size, mda_offset, mda_size; + grub_uint64_t mda_offset, mda_size; char buf[GRUB_LVM_LABEL_SIZE]; char vg_id[GRUB_LVM_ID_STRLEN+1]; char pv_id[GRUB_LVM_ID_STRLEN+1]; @@ -274,9 +273,17 @@ grub_lvm_scan_device (const char *name) struct grub_lvm_vg *vg; struct grub_lvm_pv *pv; +#ifdef GRUB_UTIL + grub_util_info ("scanning %s for LVM", name); +#endif + disk = grub_disk_open (name); if (!disk) - return 0; + { + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; + return 0; + } /* Search for label. */ for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++) @@ -294,7 +301,12 @@ grub_lvm_scan_device (const char *name) /* Return if we didn't find a label. */ if (i == GRUB_LVM_LABEL_SCAN_SECTORS) - goto fail; + { +#ifdef GRUB_UTIL + grub_util_info ("no LVM signature found\n"); +#endif + goto fail; + } pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl)); @@ -307,8 +319,6 @@ grub_lvm_scan_device (const char *name) pv_id[j] = '\0'; dlocn = pvh->disk_areas_xl; - da_offset = grub_le_to_cpu64 (dlocn->offset); - da_size = grub_le_to_cpu64 (dlocn->size); dlocn++; /* Is it possible to have multiple data/metadata areas? I haven't @@ -318,6 +328,9 @@ grub_lvm_scan_device (const char *name) grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "we don't support multiple LVM data areas"); +#ifdef GRUB_UTIL + grub_util_info ("we don't support multiple LVM data areas\n"); +#endif goto fail; } @@ -344,6 +357,9 @@ grub_lvm_scan_device (const char *name) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unknown LVM metadata header"); +#ifdef GRUB_UTIL + grub_util_info ("unknown LVM metadata header\n"); +#endif goto fail2; } @@ -364,7 +380,12 @@ grub_lvm_scan_device (const char *name) q++; if (q == metadatabuf + mda_size) - goto fail2; + { +#ifdef GRUB_UTIL + grub_util_info ("error parsing metadata\n"); +#endif + goto fail2; + } vgname_len = q - p; vgname = grub_malloc (vgname_len + 1); @@ -376,7 +397,12 @@ grub_lvm_scan_device (const char *name) p = grub_strstr (q, "id = \""); if (p == NULL) - goto fail3; + { +#ifdef GRUB_UTIL + grub_util_info ("couldn't find ID\n"); +#endif + goto fail3; + } p += sizeof ("id = \"") - 1; grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN); vg_id[GRUB_LVM_ID_STRLEN] = '\0'; @@ -399,7 +425,12 @@ grub_lvm_scan_device (const char *name) vg->extent_size = grub_lvm_getvalue (&p, "extent_size = "); if (p == NULL) - goto fail4; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown extent size\n"); +#endif + goto fail4; + } vg->lvs = NULL; vg->pvs = NULL; @@ -439,11 +470,21 @@ grub_lvm_scan_device (const char *name) pv->start = grub_lvm_getvalue (&p, "pe_start = "); if (p == NULL) - goto pvs_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown pe_start\n"); +#endif + goto pvs_fail; + } p = grub_strchr (p, '}'); if (p == NULL) - goto pvs_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("error parsing pe_start\n"); +#endif + goto pvs_fail; + } p++; pv->disk = NULL; @@ -500,7 +541,12 @@ grub_lvm_scan_device (const char *name) lv->segment_count = grub_lvm_getvalue (&p, "segment_count = "); if (p == NULL) - goto lvs_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown segment_count\n"); +#endif + goto lvs_fail; + } lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count); seg = lv->segments; @@ -510,14 +556,29 @@ grub_lvm_scan_device (const char *name) p = grub_strstr (p, "segment"); if (p == NULL) - goto lvs_segment_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown segment\n"); +#endif + goto lvs_segment_fail; + } seg->start_extent = grub_lvm_getvalue (&p, "start_extent = "); if (p == NULL) - goto lvs_segment_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown start_extent\n"); +#endif + goto lvs_segment_fail; + } seg->extent_count = grub_lvm_getvalue (&p, "extent_count = "); if (p == NULL) - goto lvs_segment_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown extent_count\n"); +#endif + goto lvs_segment_fail; + } if (grub_lvm_checkvalue (&p, "type = ", "snapshot")) { @@ -528,7 +589,12 @@ grub_lvm_scan_device (const char *name) seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = "); if (p == NULL) - goto lvs_segment_fail; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown stripe_count\n"); +#endif + goto lvs_segment_fail; + } lv->size += seg->extent_count * vg->extent_size; @@ -541,7 +607,12 @@ grub_lvm_scan_device (const char *name) p = grub_strstr (p, "stripes = ["); if (p == NULL) - goto lvs_segment_fail2; + { +#ifdef GRUB_UTIL + grub_util_info ("unknown stripes\n"); +#endif + goto lvs_segment_fail2; + } p += sizeof("stripes = [") - 1; for (j = 0; j < seg->stripe_count; j++) @@ -655,6 +726,8 @@ grub_lvm_scan_device (const char *name) grub_free (metadatabuf); fail: grub_disk_close (disk); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; return 0; } @@ -689,5 +762,6 @@ GRUB_MOD_INIT(lvm) GRUB_MOD_FINI(lvm) { grub_disk_dev_unregister (&grub_lvm_dev); + vg_list = NULL; /* FIXME: free the lvm list. */ } diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c new file mode 100644 index 000000000..dd60df695 --- /dev/null +++ b/grub-core/disk/mdraid1x_linux.c @@ -0,0 +1,233 @@ +/* mdraid_linux.c - module to handle Linux Software RAID. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + +/* Linux RAID on disk structures and constants, + copied from include/linux/raid/md_p.h. */ + +#define SB_MAGIC 0xa92b4efc + +/* + * The version-1 superblock : + * All numeric fields are little-endian. + * + * Total size: 256 bytes plus 2 per device. + * 1K allows 384 devices. + */ + +struct grub_raid_super_1x +{ + /* Constant array information - 128 bytes. */ + grub_uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */ + grub_uint32_t major_version; /* 1. */ + grub_uint32_t feature_map; /* Bit 0 set if 'bitmap_offset' is meaningful. */ + grub_uint32_t pad0; /* Always set to 0 when writing. */ + + grub_uint8_t set_uuid[16]; /* User-space generated. */ + char set_name[32]; /* Set and interpreted by user-space. */ + + grub_uint64_t ctime; /* Lo 40 bits are seconds, top 24 are microseconds or 0. */ + grub_uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5. */ + grub_uint32_t layout; /* only for raid5 and raid10 currently. */ + grub_uint64_t size; /* Used size of component devices, in 512byte sectors. */ + + grub_uint32_t chunksize; /* In 512byte sectors. */ + grub_uint32_t raid_disks; + grub_uint32_t bitmap_offset; /* Sectors after start of superblock that bitmap starts + * NOTE: signed, so bitmap can be before superblock + * only meaningful of feature_map[0] is set. + */ + + /* These are only valid with feature bit '4'. */ + grub_uint32_t new_level; /* New level we are reshaping to. */ + grub_uint64_t reshape_position; /* Next address in array-space for reshape. */ + grub_uint32_t delta_disks; /* Change in number of raid_disks. */ + grub_uint32_t new_layout; /* New layout. */ + grub_uint32_t new_chunk; /* New chunk size (512byte sectors). */ + grub_uint8_t pad1[128 - 124]; /* Set to 0 when written. */ + + /* Constant this-device information - 64 bytes. */ + grub_uint64_t data_offset; /* Sector start of data, often 0. */ + grub_uint64_t data_size; /* Sectors in this device that can be used for data. */ + grub_uint64_t super_offset; /* Sector start of this superblock. */ + grub_uint64_t recovery_offset; /* Sectors before this offset (from data_offset) have been recovered. */ + grub_uint32_t dev_number; /* Permanent identifier of this device - not role in raid. */ + grub_uint32_t cnt_corrected_read; /* Number of read errors that were corrected by re-writing. */ + grub_uint8_t device_uuid[16]; /* User-space setable, ignored by kernel. */ + grub_uint8_t devflags; /* Per-device flags. Only one defined... */ + grub_uint8_t pad2[64 - 57]; /* Set to 0 when writing. */ + + /* Array state information - 64 bytes. */ + grub_uint64_t utime; /* 40 bits second, 24 btes microseconds. */ + grub_uint64_t events; /* Incremented when superblock updated. */ + grub_uint64_t resync_offset; /* Data before this offset (from data_offset) known to be in sync. */ + grub_uint32_t sb_csum; /* Checksum upto devs[max_dev]. */ + grub_uint32_t max_dev; /* Size of devs[] array to consider. */ + grub_uint8_t pad3[64 - 32]; /* Set to 0 when writing. */ + + /* Device state information. Indexed by dev_number. + * 2 bytes per device. + * Note there are no per-device state flags. State information is rolled + * into the 'roles' value. If a device is spare or faulty, then it doesn't + * have a meaningful role. + */ + grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */ +}; +/* Could be __attribute__ ((packed)), but since all members in this struct + are already appropriately aligned, we can omit this and avoid suboptimal + assembly in some cases. */ + +#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */ + +static grub_err_t +grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, + grub_disk_addr_t *start_sector) +{ + grub_disk_addr_t sector; + grub_uint64_t size; + struct grub_raid_super_1x sb; + grub_uint8_t minor_version; + + /* The sector where the mdraid 0.90 superblock is stored, if available. */ + size = grub_disk_get_size (disk); + + /* Check for an 1.x superblock. + * It's always aligned to a 4K boundary + * and depending on the minor version it can be: + * 0: At least 8K, but less than 12K, from end of device + * 1: At start of device + * 2: 4K from start of device. + */ + + for (minor_version = 0; minor_version < 3; ++minor_version) + { + switch (minor_version) + { + case 0: + sector = (size - 8 * 2) & ~(4 * 2 - 1); + break; + case 1: + sector = 0; + break; + case 2: + sector = 4 * 2; + break; + } + + if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x), + &sb)) + return grub_errno; + + if (sb.magic != SB_MAGIC) + continue; + + { + grub_uint64_t sb_size; + struct grub_raid_super_1x *real_sb; + + if (sb.major_version != 1) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Unsupported RAID version: %d", + sb.major_version); + + /* Multipath. */ + if ((int) sb.level == -4) + sb.level = 1; + + if (sb.level != 0 && sb.level != 1 && sb.level != 4 && + sb.level != 5 && sb.level != 6 && sb.level != 10) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Unsupported RAID level: %d", sb.level); + + /* 1.x superblocks don't have a fixed size on disk. So we have to + read it again now that we now the max device count. */ + sb_size = sizeof (struct grub_raid_super_1x) + + 2 * grub_le_to_cpu32 (sb.max_dev); + real_sb = grub_malloc (sb_size); + if (! real_sb) + return grub_errno; + + if (grub_disk_read (disk, sector, 0, sb_size, real_sb)) + { + grub_free (real_sb); + return grub_errno; + } + + array->name = grub_strdup (real_sb->set_name); + if (! array->name) + { + grub_free (real_sb); + return grub_errno; + } + + array->number = 0; + array->level = grub_le_to_cpu32 (real_sb->level); + array->layout = grub_le_to_cpu32 (real_sb->layout); + array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); + array->disk_size = grub_le_to_cpu64 (real_sb->size); + array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); + + if (grub_le_to_cpu32 (real_sb->dev_number) >= + grub_le_to_cpu32 (real_sb->max_dev)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "spares aren't implemented"); + + array->index = grub_le_to_cpu16 + (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); + array->uuid_len = 16; + array->uuid = grub_malloc (16); + if (!array->uuid) + { + grub_free (real_sb); + return grub_errno; + } + + grub_memcpy (array->uuid, real_sb->set_uuid, 16); + + *start_sector = real_sb->data_offset; + + grub_free (real_sb); + return 0; + } + } + + return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid"); +} + +static struct grub_raid grub_mdraid_dev = { + .name = "mdraid1x", + .detect = grub_mdraid_detect, + .next = 0 +}; + +GRUB_MOD_INIT (mdraid1x) +{ + grub_raid_register (&grub_mdraid_dev); +} + +GRUB_MOD_FINI (mdraid1x) +{ + grub_raid_unregister (&grub_mdraid_dev); +} diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c new file mode 100644 index 000000000..f5cad9dbf --- /dev/null +++ b/grub-core/disk/mdraid_linux.c @@ -0,0 +1,239 @@ +/* mdraid_linux.c - module to handle Linux Software RAID. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + +/* Linux RAID on disk structures and constants, + copied from include/linux/raid/md_p.h. */ + +#define RESERVED_BYTES (64 * 1024) +#define RESERVED_SECTORS (RESERVED_BYTES / 512) + +#define NEW_SIZE_SECTORS(x) ((x & ~(RESERVED_SECTORS - 1)) \ + - RESERVED_SECTORS) + +#define SB_BYTES 4096 +#define SB_WORDS (SB_BYTES / 4) +#define SB_SECTORS (SB_BYTES / 512) + +/* + * The following are counted in 32-bit words + */ +#define SB_GENERIC_OFFSET 0 + +#define SB_PERSONALITY_OFFSET 64 +#define SB_DISKS_OFFSET 128 +#define SB_DESCRIPTOR_OFFSET 992 + +#define SB_GENERIC_CONSTANT_WORDS 32 +#define SB_GENERIC_STATE_WORDS 32 +#define SB_GENERIC_WORDS (SB_GENERIC_CONSTANT_WORDS + \ + SB_GENERIC_STATE_WORDS) + +#define SB_PERSONALITY_WORDS 64 +#define SB_DESCRIPTOR_WORDS 32 +#define SB_DISKS 27 +#define SB_DISKS_WORDS (SB_DISKS * SB_DESCRIPTOR_WORDS) + +#define SB_RESERVED_WORDS (1024 \ + - SB_GENERIC_WORDS \ + - SB_PERSONALITY_WORDS \ + - SB_DISKS_WORDS \ + - SB_DESCRIPTOR_WORDS) + +#define SB_EQUAL_WORDS (SB_GENERIC_WORDS \ + + SB_PERSONALITY_WORDS \ + + SB_DISKS_WORDS) + +/* + * Device "operational" state bits + */ +#define DISK_FAULTY 0 +#define DISK_ACTIVE 1 +#define DISK_SYNC 2 +#define DISK_REMOVED 3 + +#define DISK_WRITEMOSTLY 9 + +#define SB_MAGIC 0xa92b4efc + +/* + * Superblock state bits + */ +#define SB_CLEAN 0 +#define SB_ERRORS 1 + +#define SB_BITMAP_PRESENT 8 + +struct grub_raid_disk_09 +{ + grub_uint32_t number; /* Device number in the entire set. */ + grub_uint32_t major; /* Device major number. */ + grub_uint32_t minor; /* Device minor number. */ + grub_uint32_t raid_disk; /* The role of the device in the raid set. */ + grub_uint32_t state; /* Operational state. */ + grub_uint32_t reserved[SB_DESCRIPTOR_WORDS - 5]; +}; + +struct grub_raid_super_09 +{ + /* + * Constant generic information + */ + grub_uint32_t md_magic; /* MD identifier. */ + grub_uint32_t major_version; /* Major version. */ + grub_uint32_t minor_version; /* Minor version. */ + grub_uint32_t patch_version; /* Patchlevel version. */ + grub_uint32_t gvalid_words; /* Number of used words in this section. */ + grub_uint32_t set_uuid0; /* Raid set identifier. */ + grub_uint32_t ctime; /* Creation time. */ + grub_uint32_t level; /* Raid personality. */ + grub_uint32_t size; /* Apparent size of each individual disk. */ + grub_uint32_t nr_disks; /* Total disks in the raid set. */ + grub_uint32_t raid_disks; /* Disks in a fully functional raid set. */ + grub_uint32_t md_minor; /* Preferred MD minor device number. */ + grub_uint32_t not_persistent; /* Does it have a persistent superblock. */ + grub_uint32_t set_uuid1; /* Raid set identifier #2. */ + grub_uint32_t set_uuid2; /* Raid set identifier #3. */ + grub_uint32_t set_uuid3; /* Raid set identifier #4. */ + grub_uint32_t gstate_creserved[SB_GENERIC_CONSTANT_WORDS - 16]; + + /* + * Generic state information + */ + grub_uint32_t utime; /* Superblock update time. */ + grub_uint32_t state; /* State bits (clean, ...). */ + grub_uint32_t active_disks; /* Number of currently active disks. */ + grub_uint32_t working_disks; /* Number of working disks. */ + grub_uint32_t failed_disks; /* Number of failed disks. */ + grub_uint32_t spare_disks; /* Number of spare disks. */ + grub_uint32_t sb_csum; /* Checksum of the whole superblock. */ + grub_uint64_t events; /* Superblock update count. */ + grub_uint64_t cp_events; /* Checkpoint update count. */ + grub_uint32_t recovery_cp; /* Recovery checkpoint sector count. */ + grub_uint32_t gstate_sreserved[SB_GENERIC_STATE_WORDS - 12]; + + /* + * Personality information + */ + grub_uint32_t layout; /* The array's physical layout. */ + grub_uint32_t chunk_size; /* Chunk size in bytes. */ + grub_uint32_t root_pv; /* LV root PV. */ + grub_uint32_t root_block; /* LV root block. */ + grub_uint32_t pstate_reserved[SB_PERSONALITY_WORDS - 4]; + + /* + * Disks information + */ + struct grub_raid_disk_09 disks[SB_DISKS]; + + /* + * Reserved + */ + grub_uint32_t reserved[SB_RESERVED_WORDS]; + + /* + * Active descriptor + */ + struct grub_raid_disk_09 this_disk; +} __attribute__ ((packed)); + +static grub_err_t +grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, + grub_disk_addr_t *start_sector) +{ + grub_disk_addr_t sector; + grub_uint64_t size; + struct grub_raid_super_09 sb; + grub_uint32_t *uuid; + + /* The sector where the mdraid 0.90 superblock is stored, if available. */ + size = grub_disk_get_size (disk); + sector = NEW_SIZE_SECTORS (size); + + if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb)) + return grub_errno; + + /* Look whether there is a mdraid 0.90 superblock. */ + if (sb.md_magic != SB_MAGIC) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid"); + + if (sb.major_version != 0 || sb.minor_version != 90) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID version: %d.%d", + sb.major_version, sb.minor_version); + + /* FIXME: Check the checksum. */ + + /* Multipath. */ + if ((int) sb.level == -4) + sb.level = 1; + + if (sb.level != 0 && sb.level != 1 && sb.level != 4 && + sb.level != 5 && sb.level != 6 && sb.level != 10) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID level: %d", sb.level); + if (sb.this_disk.number == 0xffff || sb.this_disk.number == 0xfffe) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "spares aren't implemented"); + + array->name = NULL; + array->number = sb.md_minor; + array->level = sb.level; + array->layout = sb.layout; + array->total_devs = sb.raid_disks; + array->disk_size = (sb.size) ? sb.size * 2 : sector; + array->chunk_size = sb.chunk_size >> 9; + array->index = sb.this_disk.number; + array->uuid_len = 16; + array->uuid = grub_malloc (16); + if (!array->uuid) + return grub_errno; + + uuid = (grub_uint32_t *) array->uuid; + uuid[0] = sb.set_uuid0; + uuid[1] = sb.set_uuid1; + uuid[2] = sb.set_uuid2; + uuid[3] = sb.set_uuid3; + + *start_sector = 0; + + return 0; +} + +static struct grub_raid grub_mdraid_dev = { + .name = "mdraid09", + .detect = grub_mdraid_detect, + .next = 0 +}; + +GRUB_MOD_INIT (mdraid09) +{ + grub_raid_register (&grub_mdraid_dev); +} + +GRUB_MOD_FINI (mdraid09) +{ + grub_raid_unregister (&grub_mdraid_dev); +} diff --git a/disk/memdisk.c b/grub-core/disk/memdisk.c similarity index 99% rename from disk/memdisk.c rename to grub-core/disk/memdisk.c index 2e8885020..e00280dd7 100644 --- a/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -41,7 +41,6 @@ grub_memdisk_open (const char *name, grub_disk_t disk) disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE; disk->id = (unsigned long) "mdsk"; - disk->has_partitions = 0; return GRUB_ERR_NONE; } diff --git a/disk/raid.c b/grub-core/disk/raid.c similarity index 89% rename from disk/raid.c rename to grub-core/disk/raid.c index 51a4b00e2..f1b67a859 100644 --- a/disk/raid.c +++ b/grub-core/disk/raid.c @@ -97,16 +97,24 @@ grub_raid_memberlist (grub_disk_t disk) unsigned int i; for (i = 0; i < array->total_devs; i++) - if (array->device[i]) + if (array->members[i].device) { tmp = grub_malloc (sizeof (*tmp)); - tmp->disk = array->device[i]; + tmp->disk = array->members[i].device; tmp->next = list; list = tmp; } return list; } + +static const char * +grub_raid_getname (struct grub_disk *disk) +{ + struct grub_raid_array *array = disk->data; + + return array->driver->name; +} #endif static grub_err_t @@ -126,7 +134,6 @@ grub_raid_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", name); - disk->has_partitions = 1; disk->id = array->number; disk->data = array; @@ -248,13 +255,13 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, k = disknr; for (j = 0; j < far; j++) { - if (array->device[k]) + if (array->members[k].device) { if (grub_errno == GRUB_ERR_READ_ERROR) grub_errno = GRUB_ERR_NONE; - err = grub_disk_read (array->device[k], - array->start_sector[k] + + err = grub_disk_read (array->members[k].device, + array->members[k].start_sector + read_sector + j * far_ofs + b, 0, read_size << GRUB_DISK_SECTOR_BITS, @@ -360,14 +367,14 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, read_size = size; e = 0; - if (array->device[disknr]) + if (array->members[disknr].device) { /* Reset read error. */ if (grub_errno == GRUB_ERR_READ_ERROR) grub_errno = GRUB_ERR_NONE; - err = grub_disk_read (array->device[disknr], - array->start_sector[disknr] + + err = grub_disk_read (array->members[disknr].device, + array->members[disknr].start_sector + read_sector + b, 0, read_size << GRUB_DISK_SECTOR_BITS, buf); @@ -477,7 +484,8 @@ grub_raid_write (grub_disk_t disk __attribute ((unused)), static grub_err_t insert_array (grub_disk_t disk, struct grub_raid_array *new_array, - grub_disk_addr_t start_sector, const char *scanner_name) + grub_disk_addr_t start_sector, const char *scanner_name, + grub_raid_t raid __attribute__ ((unused))) { struct grub_raid_array *array = 0, *p; @@ -492,6 +500,21 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, /* Do some checks before adding the device to the array. */ + if (new_array->index >= array->allocated_devs) + { + void *tmp; + unsigned int newnum = 2 * (new_array->index + 1); + tmp = grub_realloc (array->members, newnum + * sizeof (array->members[0])); + if (!tmp) + return grub_errno; + array->members = tmp; + grub_memset (array->members + array->allocated_devs, + 0, (newnum - array->allocated_devs) + * sizeof (array->members[0])); + array->allocated_devs = newnum; + } + /* FIXME: Check whether the update time of the superblocks are the same. */ @@ -502,7 +525,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?", array->total_devs); - if (array->device[new_array->index] != NULL) + if (array->members[new_array->index].device != NULL) /* We found multiple devices with the same number. Again, this shouldn't happen. */ grub_dprintf ("raid", "Found two disks with the number %d?!?", @@ -525,8 +548,21 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, *array = *new_array; array->nr_devs = 0; - grub_memset (&array->device, 0, sizeof (array->device)); - grub_memset (&array->start_sector, 0, sizeof (array->start_sector)); +#ifdef GRUB_UTIL + array->driver = raid; +#endif + array->allocated_devs = 32; + if (new_array->index >= array->allocated_devs) + array->allocated_devs = 2 * (new_array->index + 1); + + array->members = grub_zalloc (array->allocated_devs + * sizeof (array->members[0])); + + if (!array->members) + { + grub_free (new_array->uuid); + return grub_errno; + } if (! array->name) { @@ -571,6 +607,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, array->name = grub_xasprintf ("md%d", array->number); if (! array->name) { + grub_free (array->members); grub_free (array->uuid); grub_free (array); @@ -586,6 +623,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, if (! new_name) { + grub_free (array->members); grub_free (array->uuid); grub_free (array); @@ -610,8 +648,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, } /* Add the device to the array. */ - array->device[new_array->index] = disk; - array->start_sector[new_array->index] = start_sector; + array->members[new_array->index].device = disk; + array->members[new_array->index].start_sector = start_sector; array->nr_devs++; return 0; @@ -628,14 +666,15 @@ free_array (void) while (array) { struct grub_raid_array *p; - int i; + unsigned int i; p = array; array = array->next; - for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++) - if (p->device[i]) - grub_disk_close (p->device[i]); + for (i = 0; i < p->allocated_devs; i++) + if (p->members[i].device) + grub_disk_close (p->members[i].device); + grub_free (p->members); grub_free (p->uuid); grub_free (p->name); @@ -663,7 +702,8 @@ grub_raid_register (grub_raid_t raid) if ((disk->total_sectors != GRUB_ULONG_MAX) && (! grub_raid_list->detect (disk, &array, &start_sector)) && - (! insert_array (disk, &array, start_sector, grub_raid_list->name))) + (! insert_array (disk, &array, start_sector, grub_raid_list->name, + grub_raid_list))) return 0; /* This error usually means it's not raid, no need to display @@ -707,6 +747,7 @@ static struct grub_disk_dev grub_raid_dev = .write = grub_raid_write, #ifdef GRUB_UTIL .memberlist = grub_raid_memberlist, + .raidname = grub_raid_getname, #endif .next = 0 }; diff --git a/disk/raid5_recover.c b/grub-core/disk/raid5_recover.c similarity index 95% rename from disk/raid5_recover.c rename to grub-core/disk/raid5_recover.c index 31cef88b1..2cda67533 100644 --- a/disk/raid5_recover.c +++ b/grub-core/disk/raid5_recover.c @@ -45,7 +45,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr, if (i == disknr) continue; - err = grub_disk_read (array->device[i], sector, 0, size, buf2); + err = grub_disk_read (array->members[i].device, sector, 0, size, buf2); if (err) { diff --git a/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c similarity index 88% rename from disk/raid6_recover.c rename to grub-core/disk/raid6_recover.c index 550968ceb..01daa2c79 100644 --- a/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -118,8 +118,9 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, bad1 = i; else { - if ((array->device[pos]) && - (! grub_disk_read (array->device[pos], sector, 0, size, buf))) + if ((array->members[pos].device) && + (! grub_disk_read (array->members[pos].device, sector, + 0, size, buf))) { grub_raid_block_xor (pbuf, buf, size); grub_raid_block_mul (raid6_table2[i][i], buf, size); @@ -148,21 +149,21 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, if (bad2 < 0) { /* One bad device */ - if ((array->device[p]) && - (! grub_disk_read (array->device[p], sector, 0, size, buf))) + if ((array->members[p].device) && + (! grub_disk_read (array->members[p].device, sector, 0, size, buf))) { grub_raid_block_xor (buf, pbuf, size); goto quit; } - if (! array->device[q]) + if (! array->members[q].device) { grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); goto quit; } grub_errno = GRUB_ERR_NONE; - if (grub_disk_read (array->device[q], sector, 0, size, buf)) + if (grub_disk_read (array->members[q].device, sector, 0, size, buf)) goto quit; grub_raid_block_xor (buf, qbuf, size); @@ -174,18 +175,18 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, /* Two bad devices */ grub_uint8_t c; - if ((! array->device[p]) || (! array->device[q])) + if ((! array->members[p].device) || (! array->members[q].device)) { grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); goto quit; } - if (grub_disk_read (array->device[p], sector, 0, size, buf)) + if (grub_disk_read (array->members[p].device, sector, 0, size, buf)) goto quit; grub_raid_block_xor (pbuf, buf, size); - if (grub_disk_read (array->device[q], sector, 0, size, buf)) + if (grub_disk_read (array->members[q].device, sector, 0, size, buf)) goto quit; grub_raid_block_xor (qbuf, buf, size); diff --git a/disk/scsi.c b/grub-core/disk/scsi.c similarity index 99% rename from disk/scsi.c rename to grub-core/disk/scsi.c index 60192bef5..902ab12c3 100644 --- a/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -431,12 +431,6 @@ grub_scsi_open (const char *name, grub_disk_t disk) "unknown SCSI device"); } - if (scsi->devtype == grub_scsi_devtype_cdrom) - disk->has_partitions = 0; - else - disk->has_partitions = 1; - - /* According to USB MS tests specification, issue Test Unit Ready * until OK */ maxtime = grub_get_time_ms () + 5000; /* It is safer value */ diff --git a/disk/usbms.c b/grub-core/disk/usbms.c similarity index 98% rename from disk/usbms.c rename to grub-core/disk/usbms.c index 225761e0f..e63105ccc 100644 --- a/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -65,6 +65,7 @@ typedef struct grub_usbms_dev *grub_usbms_dev_t; /* FIXME: remove limit. */ #define MAX_USBMS_DEVICES 128 static grub_usbms_dev_t grub_usbms_devices[MAX_USBMS_DEVICES]; +static int first_available_slot = 0; static grub_err_t grub_usbms_reset (grub_usb_device_t dev, int interface) @@ -96,13 +97,12 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) unsigned curnum; grub_usb_err_t err; - for (curnum = 0; curnum < ARRAY_SIZE (grub_usbms_devices); curnum++) - if (!grub_usbms_devices[curnum]) - break; - - if (curnum == ARRAY_SIZE (grub_usbms_devices)) + if (first_available_slot == ARRAY_SIZE (grub_usbms_devices)) return 0; + curnum = first_available_slot; + first_available_slot++; + interf = usbdev->config[configno].interf[interfno].descif; if ((interf->subclass != GRUB_USBMS_SUBCLASS_BULK diff --git a/efiemu/i386/coredetect.c b/grub-core/efiemu/i386/coredetect.c similarity index 98% rename from efiemu/i386/coredetect.c rename to grub-core/efiemu/i386/coredetect.c index 828508dee..975c4aa5d 100644 --- a/efiemu/i386/coredetect.c +++ b/grub-core/efiemu/i386/coredetect.c @@ -17,7 +17,6 @@ */ #include -#include #include #define cpuid(num,a,b,c,d) \ diff --git a/efiemu/i386/loadcore32.c b/grub-core/efiemu/i386/loadcore32.c similarity index 100% rename from efiemu/i386/loadcore32.c rename to grub-core/efiemu/i386/loadcore32.c diff --git a/efiemu/i386/loadcore64.c b/grub-core/efiemu/i386/loadcore64.c similarity index 100% rename from efiemu/i386/loadcore64.c rename to grub-core/efiemu/i386/loadcore64.c diff --git a/include/grub/sparc64/ieee1275/loader.h b/grub-core/efiemu/i386/nocfgtables.c similarity index 71% rename from include/grub/sparc64/ieee1275/loader.h rename to grub-core/efiemu/i386/nocfgtables.c index 12bb2a69b..775f1d03a 100644 --- a/include/grub/sparc64/ieee1275/loader.h +++ b/grub-core/efiemu/i386/nocfgtables.c @@ -1,3 +1,4 @@ +/* Register SMBIOS and ACPI tables. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2009 Free Software Foundation, Inc. @@ -16,12 +17,14 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_LOADER_MACHINE_HEADER -#define GRUB_LOADER_MACHINE_HEADER 1 +#include +#include +#include +#include +#include -/* The symbol shared between the normal mode and rescue mode - loader. */ -void grub_rescue_cmd_linux (int argc, char *argv[]); -void grub_rescue_cmd_initrd (int argc, char *argv[]); - -#endif /* ! GRUB_LOADER_MACHINE_HEADER */ +grub_err_t +grub_machine_efiemu_init_tables (void) +{ + return GRUB_ERR_NONE; +} diff --git a/efiemu/i386/pc/cfgtables.c b/grub-core/efiemu/i386/pc/cfgtables.c similarity index 98% rename from efiemu/i386/pc/cfgtables.c rename to grub-core/efiemu/i386/pc/cfgtables.c index 9c6b4e55e..9287d3a94 100644 --- a/efiemu/i386/pc/cfgtables.c +++ b/grub-core/efiemu/i386/pc/cfgtables.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c similarity index 99% rename from efiemu/loadcore.c rename to grub-core/efiemu/loadcore.c index 4bf26ee44..edadd4580 100644 --- a/efiemu/loadcore.c +++ b/grub-core/efiemu/loadcore.c @@ -22,7 +22,6 @@ #include #include #include -#include #include /* ELF symbols and their values */ diff --git a/efiemu/loadcore32.c b/grub-core/efiemu/loadcore32.c similarity index 100% rename from efiemu/loadcore32.c rename to grub-core/efiemu/loadcore32.c diff --git a/efiemu/loadcore64.c b/grub-core/efiemu/loadcore64.c similarity index 100% rename from efiemu/loadcore64.c rename to grub-core/efiemu/loadcore64.c diff --git a/efiemu/loadcore_common.c b/grub-core/efiemu/loadcore_common.c similarity index 100% rename from efiemu/loadcore_common.c rename to grub-core/efiemu/loadcore_common.c diff --git a/efiemu/main.c b/grub-core/efiemu/main.c similarity index 96% rename from efiemu/main.c rename to grub-core/efiemu/main.c index b197a8b2c..da813b00d 100644 --- a/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -183,22 +182,6 @@ grub_cmd_efiemu_prepare (grub_command_t cmd __attribute__ ((unused)), - -int -grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key - __attribute__ ((unused))) -{ - /* Nothing to do here yet */ - return 1; -} - -int -grub_efiemu_finish_boot_services (void) -{ - /* Nothing to do here yet */ - return 1; -} - /* Load the runtime from the file FILENAME. */ static grub_err_t grub_efiemu_load_file (const char *filename) @@ -283,11 +266,13 @@ grub_efiemu_prepare (void) if (prepared) return GRUB_ERR_NONE; + err = grub_efiemu_autocore (); + if (err) + return err; + grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n", 8 * grub_efiemu_sizeof_uintn_t ()); - err = grub_efiemu_autocore (); - /* Create NVRAM. */ grub_efiemu_pnvram (); diff --git a/efiemu/mm.c b/grub-core/efiemu/mm.c similarity index 93% rename from efiemu/mm.c rename to grub-core/efiemu/mm.c index 4b293606f..3c1dc2946 100644 --- a/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include struct grub_efiemu_memrequest { @@ -269,10 +269,11 @@ static grub_err_t grub_efiemu_mmap_init (void) { auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); + grub_memory_type_t); int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type + __attribute__ ((unused))) { mmap_reserved_size++; return 0; @@ -323,6 +324,25 @@ grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size, return 1; } +grub_err_t +grub_efiemu_finish_boot_services (grub_efi_uintn_t *memory_map_size, + grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version) +{ + int val = grub_efiemu_get_memory_map (memory_map_size, + memory_map, map_key, + descriptor_size, + descriptor_version); + if (val == 1) + return GRUB_ERR_NONE; + if (val == -1) + return grub_errno; + return grub_error (GRUB_ERR_IO, "memory map buffer is too small"); +} + + /* Free everything */ grub_err_t grub_efiemu_mm_unload (void) @@ -363,32 +383,29 @@ grub_efiemu_mm_init (void) static grub_err_t grub_efiemu_mmap_fill (void) { - auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type) + grub_memory_type_t type) { switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_CONVENTIONAL_MEMORY); -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_ACPI_RECLAIM_MEMORY); -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_ACPI_MEMORY_NVS); -#endif default: - grub_printf ("Unknown memory type %d. Marking as unusable\n", type); - case GRUB_MACHINE_MEMORY_RESERVED: + grub_printf ("Unknown memory type %d. Assuming unusable\n", type); + case GRUB_MEMORY_RESERVED: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_UNUSABLE_MEMORY); } @@ -402,9 +419,7 @@ grub_efiemu_mmap_fill (void) } grub_err_t -grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_efiemu_mmap_iterate (grub_memory_hook_t hook) { unsigned i; @@ -413,18 +428,22 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_CODE); + GRUB_MEMORY_CODE); + break; + + case GRUB_EFI_UNUSABLE_MEMORY: + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, + GRUB_MEMORY_BADRAM); break; case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RUNTIME_SERVICES_DATA: - case GRUB_EFI_UNUSABLE_MEMORY: case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: case GRUB_EFI_MAX_MEMORY_TYPE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -433,17 +452,17 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_ACPI); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_NVS); + GRUB_MEMORY_NVS); break; } diff --git a/efiemu/pnvram.c b/grub-core/efiemu/pnvram.c similarity index 100% rename from efiemu/pnvram.c rename to grub-core/efiemu/pnvram.c diff --git a/efiemu/prepare.c b/grub-core/efiemu/prepare.c similarity index 85% rename from efiemu/prepare.c rename to grub-core/efiemu/prepare.c index 620260049..171e092c9 100644 --- a/efiemu/prepare.c +++ b/grub-core/efiemu/prepare.c @@ -20,9 +20,9 @@ #include #include -#include +#include #include -#include +#include grub_err_t SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks, @@ -123,6 +123,7 @@ SUFFIX (grub_efiemu_crc) (void) int handle; grub_off_t off; struct SUFFIX (grub_efiemu_runtime_services) *runtime_services; + grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; /* compute CRC32 of runtime_services */ err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", @@ -132,19 +133,25 @@ SUFFIX (grub_efiemu_crc) (void) runtime_services = (struct SUFFIX (grub_efiemu_runtime_services) *) ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off); - runtime_services->hdr.crc32 = 0; - runtime_services->hdr.crc32 = grub_getcrc32 - (0, runtime_services, runtime_services->hdr.header_size); + + 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); + + runtime_services->hdr.crc32 = + 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) return err; /* compute CRC32 of system table */ - SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0; - SUFFIX (grub_efiemu_system_table)->hdr.crc32 - = grub_getcrc32 (0, 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(*(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/efiemu/prepare32.c b/grub-core/efiemu/prepare32.c similarity index 100% rename from efiemu/prepare32.c rename to grub-core/efiemu/prepare32.c diff --git a/efiemu/prepare64.c b/grub-core/efiemu/prepare64.c similarity index 100% rename from efiemu/prepare64.c rename to grub-core/efiemu/prepare64.c diff --git a/efiemu/runtime/config.h b/grub-core/efiemu/runtime/config.h similarity index 100% rename from efiemu/runtime/config.h rename to grub-core/efiemu/runtime/config.h diff --git a/efiemu/runtime/efiemu.S b/grub-core/efiemu/runtime/efiemu.S similarity index 100% rename from efiemu/runtime/efiemu.S rename to grub-core/efiemu/runtime/efiemu.S diff --git a/efiemu/runtime/efiemu.c b/grub-core/efiemu/runtime/efiemu.c similarity index 100% rename from efiemu/runtime/efiemu.c rename to grub-core/efiemu/runtime/efiemu.c diff --git a/efiemu/symbols.c b/grub-core/efiemu/symbols.c similarity index 100% rename from efiemu/symbols.c rename to grub-core/efiemu/symbols.c diff --git a/font/font.c b/grub-core/font/font.c similarity index 100% rename from font/font.c rename to grub-core/font/font.c diff --git a/font/font_cmd.c b/grub-core/font/font_cmd.c similarity index 100% rename from font/font_cmd.c rename to grub-core/font/font_cmd.c diff --git a/fs/affs.c b/grub-core/fs/affs.c similarity index 100% rename from fs/affs.c rename to grub-core/fs/affs.c diff --git a/fs/afs.c b/grub-core/fs/afs.c similarity index 100% rename from fs/afs.c rename to grub-core/fs/afs.c diff --git a/fs/afs_be.c b/grub-core/fs/afs_be.c similarity index 100% rename from fs/afs_be.c rename to grub-core/fs/afs_be.c diff --git a/fs/befs.c b/grub-core/fs/befs.c similarity index 100% rename from fs/befs.c rename to grub-core/fs/befs.c diff --git a/fs/befs_be.c b/grub-core/fs/befs_be.c similarity index 100% rename from fs/befs_be.c rename to grub-core/fs/befs_be.c diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c new file mode 100644 index 000000000..a50bae000 --- /dev/null +++ b/grub-core/fs/btrfs.c @@ -0,0 +1,132 @@ +/* btrfs.c - B-tree file system. */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BTRFS_SIGNATURE "_BHRfS_M" + +struct btrfs_superblock +{ + grub_uint8_t dummy1[32]; + grub_uint16_t uuid[8]; + grub_uint8_t dummy2[16]; + grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1]; +} __attribute__ ((packed)); + +struct grub_btrfs_data +{ + struct btrfs_superblock sblock; +}; + +static struct grub_btrfs_data * +grub_btrfs_mount (grub_disk_t disk) +{ + struct grub_btrfs_data *data = grub_malloc (sizeof (*data)); + if (! data) + return NULL; + + if (grub_disk_read (disk, 128, 0, sizeof (data->sblock), + &data->sblock) != GRUB_ERR_NONE) + goto fail; + + if (grub_strncmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1)) + { + grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem"); + goto fail; + } + + return data; + + fail: + grub_free (data); + return NULL; +} + +static grub_err_t +grub_btrfs_open (struct grub_file *file __attribute__ ((unused)), + const char *name __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs"); +} + +static grub_err_t +grub_btrfs_dir (grub_device_t device, + const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) + __attribute__ ((unused))) +{ + struct grub_btrfs_data *data = grub_btrfs_mount (device->disk); + if (grub_errno) + return grub_errno; + + grub_free (data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_btrfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_btrfs_data *data; + + *uuid = NULL; + + data = grub_btrfs_mount (device->disk); + if (! data) + return grub_errno; + + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), + grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), + grub_be_to_cpu16 (data->sblock.uuid[3]), + grub_be_to_cpu16 (data->sblock.uuid[4]), + grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), + grub_be_to_cpu16 (data->sblock.uuid[7])); + + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_btrfs_fs = + { + .name = "btrfs", + .dir = grub_btrfs_dir, + .open = grub_btrfs_open, + .uuid = grub_btrfs_uuid, + }; + +GRUB_MOD_INIT(btrfs) +{ + grub_fs_register (&grub_btrfs_fs); +} + +GRUB_MOD_FINI(btrfs) +{ + grub_fs_unregister (&grub_btrfs_fs); +} diff --git a/fs/cpio.c b/grub-core/fs/cpio.c similarity index 100% rename from fs/cpio.c rename to grub-core/fs/cpio.c diff --git a/fs/ext2.c b/grub-core/fs/ext2.c similarity index 94% rename from fs/ext2.c rename to grub-core/fs/ext2.c index f2fec828a..ed5fafd4c 100644 --- a/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -229,7 +229,7 @@ struct grub_ext2_inode }; grub_uint32_t version; grub_uint32_t acl; - grub_uint32_t dir_acl; + grub_uint32_t size_high; grub_uint32_t fragment_addr; grub_uint32_t osd2[3]; }; @@ -470,10 +470,41 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) blknr = grub_le_to_cpu32 (indir[rblock % perblock]); } /* triple indirect. */ + else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1) + + (blksz / 4) * (blksz / 4) * (blksz / 4 + 1)) + { + unsigned int perblock = blksz / 4; + unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + * (blksz / 4 + 1)); + grub_uint32_t indir[blksz / 4]; + + if (grub_disk_read (data->disk, + ((grub_disk_addr_t) + grub_le_to_cpu32 (inode->blocks.triple_indir_block)) + << log2_blksz, + 0, blksz, indir)) + return grub_errno; + + if (grub_disk_read (data->disk, + ((grub_disk_addr_t) + grub_le_to_cpu32 (indir[(rblock / perblock) / perblock])) + << log2_blksz, + 0, blksz, indir)) + return grub_errno; + + if (grub_disk_read (data->disk, + ((grub_disk_addr_t) + grub_le_to_cpu32 (indir[(rblock / perblock) % perblock])) + << log2_blksz, + 0, blksz, indir)) + return grub_errno; + + blknr = grub_le_to_cpu32 (indir[rblock % perblock]); + } else { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "ext2fs doesn't support triple indirect blocks"); + "ext2fs doesn't support quadruple indirect blocks"); } return blknr; @@ -485,11 +516,12 @@ static grub_ssize_t grub_ext2_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_ext2_read_block, - node->inode.size, + grub_cpu_to_le32 (node->inode.size) + | (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32), LOG2_EXT2_BLOCK_SIZE (node->data)); } @@ -728,22 +760,27 @@ grub_ext2_open (struct grub_file *file, const char *name) { struct grub_ext2_data *data; struct grub_fshelp_node *fdiro = 0; + grub_err_t err; grub_dl_ref (my_mod); data = grub_ext2_mount (file->device->disk); if (! data) - goto fail; + { + err = grub_errno; + goto fail; + } - grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir, - grub_ext2_read_symlink, GRUB_FSHELP_REG); - if (grub_errno) + err = grub_fshelp_find_file (name, &data->diropen, &fdiro, + grub_ext2_iterate_dir, + grub_ext2_read_symlink, GRUB_FSHELP_REG); + if (err) goto fail; if (! fdiro->inode_read) { - grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); - if (grub_errno) + err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); + if (err) goto fail; } @@ -751,6 +788,7 @@ grub_ext2_open (struct grub_file *file, const char *name) grub_free (fdiro); file->size = grub_le_to_cpu32 (data->inode->size); + file->size |= ((grub_off_t) grub_le_to_cpu32 (data->inode->size_high)) << 32; file->data = data; file->offset = 0; @@ -763,7 +801,7 @@ grub_ext2_open (struct grub_file *file, const char *name) grub_dl_unref (my_mod); - return grub_errno; + return err; } static grub_err_t diff --git a/fs/fat.c b/grub-core/fs/fat.c similarity index 100% rename from fs/fat.c rename to grub-core/fs/fat.c diff --git a/fs/fshelp.c b/grub-core/fs/fshelp.c similarity index 100% rename from fs/fshelp.c rename to grub-core/fs/fshelp.c diff --git a/fs/hfs.c b/grub-core/fs/hfs.c similarity index 100% rename from fs/hfs.c rename to grub-core/fs/hfs.c diff --git a/fs/hfsplus.c b/grub-core/fs/hfsplus.c similarity index 100% rename from fs/hfsplus.c rename to grub-core/fs/hfsplus.c diff --git a/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c similarity index 89% rename from fs/i386/pc/pxe.c rename to grub-core/fs/i386/pc/pxe.c index e4d481a8e..cbb3c7d87 100644 --- a/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -27,6 +27,7 @@ #include #include +#include #include #define SEGMENT(x) ((x) >> 4) @@ -40,7 +41,7 @@ struct grub_pxe_disk_data grub_uint32_t gateway_ip; }; -struct grub_pxenv *grub_pxe_pxenv; +struct grub_pxe_bangpxe *grub_pxe_pxenv; static grub_uint32_t grub_pxe_your_ip; static grub_uint32_t grub_pxe_default_server_ip; static grub_uint32_t grub_pxe_default_gateway_ip; @@ -55,6 +56,51 @@ struct grub_pxe_data char filename[0]; }; +static grub_uint32_t pxe_rm_entry = 0; + +static struct grub_pxe_bangpxe * +grub_pxe_scan (void) +{ + struct grub_bios_int_registers regs; + struct grub_pxenv *pxenv; + struct grub_pxe_bangpxe *bangpxe; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + regs.ebx = 0; + regs.ecx = 0; + regs.eax = 0x5650; + regs.es = 0; + + grub_bios_interrupt (0x1a, ®s); + + if ((regs.eax & 0xffff) != 0x564e) + return NULL; + + pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff)); + if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE, + sizeof (pxenv->signature)) + != 0) + return NULL; + + if (pxenv->version < 0x201) + return NULL; + + bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4) + + (pxenv->pxe_ptr & 0xffff)); + + if (!bangpxe) + return NULL; + + if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE, + sizeof (bangpxe->signature)) != 0) + return NULL; + + pxe_rm_entry = bangpxe->rm_entry; + + return bangpxe; +} + static int grub_pxe_iterate (int (*hook) (const char *name)) { @@ -130,7 +176,6 @@ grub_pxe_open (const char *name, grub_disk_t disk) disk->total_sectors = 0; disk->id = (unsigned long) data; - disk->has_partitions = 0; disk->data = data; return GRUB_ERR_NONE; @@ -202,14 +247,14 @@ grub_pxefs_open (struct grub_file *file, const char *name) if (curr_file != 0) { - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2); + grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry); curr_file = 0; } c.c1.server_ip = disk_data->server_ip; c.c1.gateway_ip = disk_data->gateway_ip; grub_strcpy ((char *)&c.c1.filename[0], name); - grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1); + grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); if (c.c1.status) return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); @@ -217,7 +262,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); c.c2.packet_size = grub_pxe_blksize; - grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2); + grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry); if (c.c2.status) return grub_error (GRUB_ERR_BAD_FS, "open fails"); @@ -236,6 +281,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) } file->data = data; + file->not_easly_seekable = 1; grub_memcpy (file_int, file, sizeof (struct grub_file)); curr_file = file_int; @@ -275,14 +321,14 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_pxenv_tftp_open o; if (curr_file != 0) - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o); + grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry); o.server_ip = disk_data->server_ip; o.gateway_ip = disk_data->gateway_ip; grub_strcpy ((char *)&o.filename[0], data->filename); o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); - o.packet_size = grub_pxe_blksize; - grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o); + o.packet_size = data->block_size; + grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry); if (o.status) { grub_error (GRUB_ERR_BAD_FS, "open fails"); @@ -297,7 +343,7 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) while (pn >= data->packet_number) { c.buffer_size = data->block_size; - grub_pxe_call (GRUB_PXENV_TFTP_READ, &c); + grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry); if (c.status) { grub_error (GRUB_ERR_BAD_FS, "read fails"); @@ -318,7 +364,7 @@ grub_pxefs_close (grub_file_t file) if (curr_file == file) { - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c); + grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry); curr_file = 0; } @@ -443,7 +489,7 @@ parse_dhcp_vendor (void *vend, int limit) static void grub_pxe_detect (void) { - struct grub_pxenv *pxenv; + struct grub_pxe_bangpxe *pxenv; struct grub_pxenv_get_cached_info ci; struct grub_pxenv_boot_player *bp; @@ -454,7 +500,7 @@ grub_pxe_detect (void) ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; ci.buffer = 0; ci.buffer_size = 0; - grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci); + grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); if (ci.status) return; diff --git a/fs/iso9660.c b/grub-core/fs/iso9660.c similarity index 100% rename from fs/iso9660.c rename to grub-core/fs/iso9660.c diff --git a/fs/jfs.c b/grub-core/fs/jfs.c similarity index 99% rename from fs/jfs.c rename to grub-core/fs/jfs.c index c9839a22f..76ef2e540 100644 --- a/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -601,7 +601,6 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) char fpath[grub_strlen (path)]; char *name = fpath; char *next; - unsigned int pos = 0; struct grub_jfs_diropen *diro; grub_strncpy (fpath, path, grub_strlen (path) + 1); @@ -664,8 +663,6 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) if (!next) return 0; - pos = 0; - name = next; next = grub_strchr (name, '/'); if (next) diff --git a/fs/minix.c b/grub-core/fs/minix.c similarity index 81% rename from fs/minix.c rename to grub-core/fs/minix.c index a856e38c4..679e1ec51 100644 --- a/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,10 +25,13 @@ #include #include +#ifdef MODE_MINIX2 +#define GRUB_MINIX_MAGIC 0x2468 +#define GRUB_MINIX_MAGIC_30 0x2478 +#else #define GRUB_MINIX_MAGIC 0x137F -#define GRUB_MINIX2_MAGIC 0x2468 #define GRUB_MINIX_MAGIC_30 0x138F -#define GRUB_MINIX2_MAGIC_30 0x2478 +#endif #define GRUB_MINIX_BSIZE 1024U #define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_ROOT_INODE 1 @@ -38,20 +41,25 @@ #define GRUB_MINIX_IFDIR 0040000U #define GRUB_MINIX_IFLNK 0120000U -#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \ - data->inode. field : data->inode2. field) -#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ? \ - grub_le_to_cpu##bits1 (data->inode.field) : \ - grub_le_to_cpu##bits2 (data->inode2.field)) -#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32) -#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16) -#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN \ - (data,dir_zones[blk],16,32) -#define GRUB_MINIX_INODE_INDIR_ZONE(data) \ - GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32) -#define GRUB_MINIX_INODE_DINDIR_ZONE(data) \ - GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32) -#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4) +#ifdef MODE_MINIX2 +typedef grub_uint32_t grub_minix_uintn_t; +#define grub_minix_le_to_cpu_n grub_le_to_cpu32 +#else +typedef grub_uint16_t grub_minix_uintn_t; +#define grub_minix_le_to_cpu_n grub_le_to_cpu16 +#endif + +#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t) + +#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) +#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) +#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \ + (data->inode.dir_zones[blk])) +#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \ + (data->inode.indir_zone)) +#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \ + (data->inode.double_indir_zone)) + #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ + grub_le_to_cpu16 (sblock->log2_zone_size)) #define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \ @@ -69,6 +77,7 @@ struct grub_minix_sblock grub_uint16_t magic; }; +#ifndef MODE_MINIX2 struct grub_minix_inode { grub_uint16_t mode; @@ -82,7 +91,9 @@ struct grub_minix_inode grub_uint16_t double_indir_zone; }; -struct grub_minix2_inode +#else + +struct grub_minix_inode { grub_uint16_t mode; grub_uint16_t nlinks; @@ -99,16 +110,16 @@ struct grub_minix2_inode }; +#endif + /* Information about a "mounted" minix filesystem. */ struct grub_minix_data { struct grub_minix_sblock sblock; struct grub_minix_inode inode; - struct grub_minix2_inode inode2; int ino; int linknest; grub_disk_t disk; - int version; int filename_size; }; @@ -128,24 +139,12 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) /* Read the block pointer in ZONE, on the offset NUM. */ int grub_get_indir (int zone, int num) { - if (data->version == 1) - { - grub_uint16_t indir16; - grub_disk_read (data->disk, - zone << GRUB_MINIX_LOG2_ZONESZ, - sizeof (grub_uint16_t) * num, - sizeof (grub_uint16_t), (char *) &indir16); - return grub_le_to_cpu16 (indir16); - } - else - { - grub_uint32_t indir32; - grub_disk_read (data->disk, - zone << GRUB_MINIX_LOG2_ZONESZ, - sizeof (grub_uint32_t) * num, - sizeof (grub_uint32_t), (char *) &indir32); - return grub_le_to_cpu32 (indir32); - } + grub_minix_uintn_t indirn; + grub_disk_read (data->disk, + zone << GRUB_MINIX_LOG2_ZONESZ, + sizeof (grub_minix_uintn_t) * num, + sizeof (grub_minix_uintn_t), (char *) &indirn); + return grub_minix_le_to_cpu_n (indirn); } /* Direct block. */ @@ -259,27 +258,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino) + grub_le_to_cpu16 (sblock->zone_bmap_size)) << GRUB_MINIX_LOG2_BSIZE); - if (data->version == 1) - { - block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); - int offs = (ino % (GRUB_DISK_SECTOR_SIZE - / sizeof (struct grub_minix_inode)) - * sizeof (struct grub_minix_inode)); - - grub_disk_read (data->disk, block, offs, - sizeof (struct grub_minix_inode), &data->inode); - } - else - { - block += ino / (GRUB_DISK_SECTOR_SIZE - / sizeof (struct grub_minix2_inode)); - int offs = (ino - % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix2_inode)) - * sizeof (struct grub_minix2_inode)); - - grub_disk_read (data->disk, block, offs, - sizeof (struct grub_minix2_inode),&data->inode2); - } + block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); + int offs = (ino % (GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_minix_inode)) + * sizeof (struct grub_minix_inode)); + + grub_disk_read (data->disk, block, offs, + sizeof (struct grub_minix_inode), &data->inode); return GRUB_ERR_NONE; } @@ -424,25 +409,9 @@ grub_minix_mount (grub_disk_t disk) goto fail; if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC) - { - data->version = 1; - data->filename_size = 14; - } - else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC) - { - data->version = 2; - data->filename_size = 14; - } + data->filename_size = 14; else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30) - { - data->version = 1; - data->filename_size = 30; - } - else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC_30) - { - data->version = 2; - data->filename_size = 30; - } + data->filename_size = 30; else goto fail; @@ -453,7 +422,11 @@ grub_minix_mount (grub_disk_t disk) fail: grub_free (data); +#ifdef MODE_MINIX2 + grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem"); +#else grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem"); +#endif return 0; } @@ -463,7 +436,6 @@ grub_minix_dir (grub_device_t device, const char *path, const struct grub_dirhook_info *info)) { struct grub_minix_data *data = 0; - struct grub_minix_sblock *sblock; unsigned int pos = 0; data = grub_minix_mount (device->disk); @@ -474,8 +446,6 @@ grub_minix_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - sblock = &data->sblock; - grub_minix_find_file (data, path); if (grub_errno) goto fail; @@ -583,32 +553,36 @@ grub_minix_close (grub_file_t file) } -static grub_err_t -grub_minix_label (grub_device_t device __attribute ((unused)), - char **label __attribute ((unused))) -{ - return GRUB_ERR_NONE; -} - static struct grub_fs grub_minix_fs = { +#ifdef MODE_MINIX2 + .name = "minix2", +#else .name = "minix", +#endif .dir = grub_minix_dir, .open = grub_minix_open, .read = grub_minix_read, .close = grub_minix_close, - .label = grub_minix_label, .next = 0 }; +#ifdef MODE_MINIX2 +GRUB_MOD_INIT(minix2) +#else GRUB_MOD_INIT(minix) +#endif { grub_fs_register (&grub_minix_fs); my_mod = mod; } +#ifdef MODE_MINIX2 +GRUB_MOD_FINI(minix2) +#else GRUB_MOD_FINI(minix) +#endif { grub_fs_unregister (&grub_minix_fs); } diff --git a/grub-core/fs/minix2.c b/grub-core/fs/minix2.c new file mode 100644 index 000000000..0fcd4b139 --- /dev/null +++ b/grub-core/fs/minix2.c @@ -0,0 +1,2 @@ +#define MODE_MINIX2 1 +#include "minix.c" diff --git a/fs/nilfs2.c b/grub-core/fs/nilfs2.c similarity index 98% rename from fs/nilfs2.c rename to grub-core/fs/nilfs2.c index 8329c01a1..e529775f4 100644 --- a/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -718,10 +718,13 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data) grub_uint64_t partition_size; int valid[2]; int swp = 0; + grub_err_t err; /* Read first super block. */ - grub_disk_read (disk, NILFS_1ST_SUPER_BLOCK, 0, - sizeof (struct grub_nilfs2_super_block), &data->sblock); + err = grub_disk_read (disk, NILFS_1ST_SUPER_BLOCK, 0, + sizeof (struct grub_nilfs2_super_block), &data->sblock); + if (err) + return err; /* Make sure if 1st super block is valid. */ valid[0] = grub_nilfs2_valid_sb (&data->sblock); @@ -729,17 +732,21 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data) if (partition_size != GRUB_DISK_SIZE_UNKNOWN) { /* Read second super block. */ - grub_disk_read (disk, NILFS_2ND_SUPER_BLOCK (partition_size), 0, - sizeof (struct grub_nilfs2_super_block), &sb2); - /* Make sure if 2nd super block is valid. */ - valid[1] = grub_nilfs2_valid_sb (&sb2); + err = grub_disk_read (disk, NILFS_2ND_SUPER_BLOCK (partition_size), 0, + sizeof (struct grub_nilfs2_super_block), &sb2); + if (err) + { + valid[1] = 0; + grub_errno = GRUB_ERR_NONE; + } + else + /* Make sure if 2nd super block is valid. */ + valid[1] = grub_nilfs2_valid_sb (&sb2); } else /* 2nd super block may not exist, so it's invalid. */ valid[1] = 0; - - if (!valid[0] && !valid[1]) return grub_error (GRUB_ERR_BAD_FS, "not a nilfs2 filesystem"); @@ -752,8 +759,7 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data) grub_memcpy (&data->sblock, &sb2, sizeof (struct grub_nilfs2_super_block)); - grub_errno = GRUB_ERR_NONE; - return grub_errno; + return GRUB_ERR_NONE; } static struct grub_nilfs2_data * diff --git a/fs/ntfs.c b/grub-core/fs/ntfs.c similarity index 99% rename from fs/ntfs.c rename to grub-core/fs/ntfs.c index dd041e23a..414f6513d 100644 --- a/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -1072,7 +1072,11 @@ grub_ntfs_uuid (grub_device_t device, char **uuid) data = grub_ntfs_mount (disk); if (data) { + char *ptr; *uuid = grub_xasprintf ("%016llx", (unsigned long long) data->uuid); + if (*uuid) + for (ptr = *uuid; *ptr; ptr++) + *ptr = grub_toupper (*ptr); } else *uuid = NULL; diff --git a/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c similarity index 100% rename from fs/ntfscomp.c rename to grub-core/fs/ntfscomp.c diff --git a/fs/reiserfs.c b/grub-core/fs/reiserfs.c similarity index 100% rename from fs/reiserfs.c rename to grub-core/fs/reiserfs.c diff --git a/fs/sfs.c b/grub-core/fs/sfs.c similarity index 99% rename from fs/sfs.c rename to grub-core/fs/sfs.c index 68f8b3a6e..4a5005908 100644 --- a/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -149,7 +149,6 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block, struct grub_sfs_btree *tree; int i; int next; - int prev; treeblock = grub_malloc (data->blocksize); if (!block) @@ -161,8 +160,6 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block, /* Handle this level in the btree. */ do { - prev = 0; - grub_disk_read (data->disk, next, 0, data->blocksize, treeblock); if (grub_errno) { diff --git a/fs/tar.c b/grub-core/fs/tar.c similarity index 100% rename from fs/tar.c rename to grub-core/fs/tar.c diff --git a/fs/udf.c b/grub-core/fs/udf.c similarity index 76% rename from fs/udf.c rename to grub-core/fs/udf.c index ad109bed9..7041e619e 100644 --- a/fs/udf.c +++ b/grub-core/fs/udf.c @@ -34,9 +34,6 @@ #define U32 grub_le_to_cpu32 #define U64 grub_le_to_cpu64 -#define GRUB_UDF_LOG2_BLKSZ 2 -#define GRUB_UDF_BLKSZ 2048 - #define GRUB_UDF_TAG_IDENT_PVD 0x0001 #define GRUB_UDF_TAG_IDENT_AVDP 0x0002 #define GRUB_UDF_TAG_IDENT_VDP 0x0003 @@ -336,6 +333,13 @@ struct grub_udf_lvd grub_uint8_t part_maps[1608]; } __attribute__ ((packed)); +struct grub_udf_aed +{ + struct grub_udf_tag tag; + grub_uint32_t prev_ae; + grub_uint32_t ae_len; +} __attribute__ ((packed)); + struct grub_udf_data { grub_disk_t disk; @@ -343,7 +347,7 @@ struct grub_udf_data struct grub_udf_pd pds[GRUB_UDF_MAX_PDS]; struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS]; struct grub_udf_long_ad root_icb; - int npd, npm; + int npd, npm, lbshift; }; struct grub_fshelp_node @@ -389,7 +393,7 @@ grub_udf_read_icb (struct grub_udf_data *data, if (grub_errno) return grub_errno; - if (grub_disk_read (data->disk, block << GRUB_UDF_LOG2_BLKSZ, 0, + if (grub_disk_read (data->disk, block << data->lbshift, 0, sizeof (struct grub_udf_file_entry), &node->fe)) return grub_errno; @@ -406,19 +410,26 @@ grub_udf_read_icb (struct grub_udf_data *data, static grub_disk_addr_t grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { + char *buf = NULL; char *ptr; - int len; + grub_ssize_t len; grub_disk_addr_t filebytes; - if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) + switch (U16 (node->fe.tag.tag_ident)) { + case GRUB_UDF_TAG_IDENT_FE: ptr = (char *) &node->fe.ext_attr[0] + U32 (node->fe.ext_attr_length); len = U32 (node->fe.alloc_descs_length); - } - else - { + break; + + case GRUB_UDF_TAG_IDENT_EFE: ptr = (char *) &node->efe.ext_attr[0] + U32 (node->efe.ext_attr_length); len = U32 (node->efe.alloc_descs_length); + break; + + default: + grub_error (GRUB_ERR_BAD_FS, "invalid file entry"); + return 0; } if ((U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK) @@ -426,43 +437,115 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr; - len /= sizeof (struct grub_udf_short_ad); - filebytes = fileblock * GRUB_UDF_BLKSZ; - while (len > 0) + filebytes = fileblock * U32 (node->data->lvd.bsize); + while (len >= (grub_ssize_t) sizeof (struct grub_udf_short_ad)) { - if (filebytes < U32 (ad->length)) - return ((U32 (ad->position) & GRUB_UDF_EXT_MASK) ? 0 : - (grub_udf_get_block (node->data, - node->part_ref, - ad->position) - + (filebytes / GRUB_UDF_BLKSZ))); + grub_uint32_t adlen = U32 (ad->length) & 0x3fffffff; + grub_uint32_t adtype = U32 (ad->length) >> 30; + if (adtype == 3) + { + struct grub_udf_aed *extension; + grub_disk_addr_t sec = grub_udf_get_block(node->data, + node->part_ref, + ad->position); + if (!buf) + { + buf = grub_malloc (U32 (node->data->lvd.bsize)); + if (!buf) + return 0; + } + if (grub_disk_read (node->data->disk, sec << node->data->lbshift, + 0, adlen, buf)) + goto fail; - filebytes -= U32 (ad->length); + extension = (struct grub_udf_aed *) buf; + if (U16 (extension->tag.tag_ident) != GRUB_UDF_TAG_IDENT_AED) + { + grub_error (GRUB_ERR_BAD_FS, "invalid aed tag"); + goto fail; + } + + len = U32 (extension->ae_len); + ad = (struct grub_udf_short_ad *) + (buf + sizeof (struct grub_udf_aed)); + continue; + } + + if (filebytes < adlen) + { + grub_uint32_t ad_pos = ad->position; + grub_free (buf); + return ((U32 (ad_pos) & GRUB_UDF_EXT_MASK) ? 0 : + (grub_udf_get_block (node->data, node->part_ref, ad_pos) + + (filebytes >> (GRUB_DISK_SECTOR_BITS + + node->data->lbshift)))); + } + + filebytes -= adlen; ad++; - len--; + len -= sizeof (struct grub_udf_short_ad); } } else { struct grub_udf_long_ad *ad = (struct grub_udf_long_ad *) ptr; - len /= sizeof (struct grub_udf_long_ad); - filebytes = fileblock * GRUB_UDF_BLKSZ; - while (len > 0) + filebytes = fileblock * U32 (node->data->lvd.bsize); + while (len >= (grub_ssize_t) sizeof (struct grub_udf_long_ad)) { - if (filebytes < U32 (ad->length)) - return ((U32 (ad->block.block_num) & GRUB_UDF_EXT_MASK) ? 0 : - (grub_udf_get_block (node->data, - ad->block.part_ref, - ad->block.block_num) - + (filebytes / GRUB_UDF_BLKSZ))); + grub_uint32_t adlen = U32 (ad->length) & 0x3fffffff; + grub_uint32_t adtype = U32 (ad->length) >> 30; + if (adtype == 3) + { + struct grub_udf_aed *extension; + grub_disk_addr_t sec = grub_udf_get_block(node->data, + ad->block.part_ref, + ad->block.block_num); + if (!buf) + { + buf = grub_malloc (U32 (node->data->lvd.bsize)); + if (!buf) + return 0; + } + if (grub_disk_read (node->data->disk, sec << node->data->lbshift, + 0, adlen, buf)) + goto fail; - filebytes -= U32 (ad->length); + extension = (struct grub_udf_aed *) buf; + if (U16 (extension->tag.tag_ident) != GRUB_UDF_TAG_IDENT_AED) + { + grub_error (GRUB_ERR_BAD_FS, "invalid aed tag"); + goto fail; + } + + len = U32 (extension->ae_len); + ad = (struct grub_udf_long_ad *) + (buf + sizeof (struct grub_udf_aed)); + continue; + } + + if (filebytes < adlen) + { + grub_uint32_t ad_block_num = ad->block.block_num; + grub_uint32_t ad_part_ref = ad->block.part_ref; + grub_free (buf); + return ((U32 (ad_block_num) & GRUB_UDF_EXT_MASK) ? 0 : + (grub_udf_get_block (node->data, ad_part_ref, + ad_block_num) + + (filebytes >> (GRUB_DISK_SECTOR_BITS + + node->data->lbshift)))); + } + + filebytes -= adlen; ad++; - len--; + len -= sizeof (struct grub_udf_long_ad); } } +fail: + if (buf) + grub_free (buf); + return 0; } @@ -471,7 +554,7 @@ grub_udf_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { switch (U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK) { @@ -496,21 +579,21 @@ grub_udf_read_file (grub_fshelp_node_t node, } return grub_fshelp_read_file (node->data->disk, node, read_hook, - pos, len, buf, grub_udf_read_block, - U64 (node->fe.file_size), - GRUB_UDF_LOG2_BLKSZ); + pos, len, buf, grub_udf_read_block, + U64 (node->fe.file_size), + node->data->lbshift); } -static int sblocklist[] = { 256, 512, 0 }; +static unsigned sblocklist[] = { 256, 512, 0 }; static struct grub_udf_data * grub_udf_mount (grub_disk_t disk) { struct grub_udf_data *data = 0; struct grub_udf_fileset root_fs; - int *sblklist = sblocklist; - grub_uint32_t block; - int i; + unsigned *sblklist; + grub_uint32_t block, vblock; + int i, lbshift; data = grub_malloc (sizeof (struct grub_udf_data)); if (!data) @@ -518,12 +601,48 @@ grub_udf_mount (grub_disk_t disk) data->disk = disk; + /* Search for Anchor Volume Descriptor Pointer (AVDP) + * and determine logical block size. */ + block = 0; + for (lbshift = 0; lbshift < 4; lbshift++) + { + for (sblklist = sblocklist; *sblklist; sblklist++) + { + struct grub_udf_avdp avdp; + + if (grub_disk_read (disk, *sblklist << lbshift, 0, + sizeof (struct grub_udf_avdp), &avdp)) + { + grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); + goto fail; + } + + if (U16 (avdp.tag.tag_ident) == GRUB_UDF_TAG_IDENT_AVDP && + U32 (avdp.tag.tag_location) == *sblklist) + { + block = U32 (avdp.vds.start); + break; + } + } + + if (block) + break; + } + + if (!block) + { + grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); + goto fail; + } + data->lbshift = lbshift; + /* Search for Volume Recognition Sequence (VRS). */ - for (block = 16;; block++) + for (vblock = (32767 >> (lbshift + GRUB_DISK_SECTOR_BITS)) + 1;; + vblock += (2047 >> (lbshift + GRUB_DISK_SECTOR_BITS)) + 1) { struct grub_udf_vrs vrs; - if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0, + if (grub_disk_read (disk, vblock << lbshift, 0, sizeof (struct grub_udf_vrs), &vrs)) { grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); @@ -545,39 +664,13 @@ grub_udf_mount (grub_disk_t disk) } } - /* Search for Anchor Volume Descriptor Pointer (AVDP). */ - while (1) - { - struct grub_udf_avdp avdp; - - if (grub_disk_read (disk, *sblklist << GRUB_UDF_LOG2_BLKSZ, 0, - sizeof (struct grub_udf_avdp), &avdp)) - { - grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); - goto fail; - } - - if (U16 (avdp.tag.tag_ident) == GRUB_UDF_TAG_IDENT_AVDP) - { - block = U32 (avdp.vds.start); - break; - } - - sblklist++; - if (*sblklist == 0) - { - grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); - goto fail; - } - } - data->npd = data->npm = 0; /* Locate Partition Descriptor (PD) and Logical Volume Descriptor (LVD). */ while (1) { struct grub_udf_tag tag; - if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0, + if (grub_disk_read (disk, block << lbshift, 0, sizeof (struct grub_udf_tag), &tag)) { grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); @@ -593,7 +686,7 @@ grub_udf_mount (grub_disk_t disk) goto fail; } - if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0, + if (grub_disk_read (disk, block << lbshift, 0, sizeof (struct grub_udf_pd), &data->pds[data->npd])) { @@ -609,7 +702,7 @@ grub_udf_mount (grub_disk_t disk) struct grub_udf_partmap *ppm; - if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0, + if (grub_disk_read (disk, block << lbshift, 0, sizeof (struct grub_udf_lvd), &data->lvd)) { @@ -673,7 +766,7 @@ grub_udf_mount (grub_disk_t disk) if (grub_errno) goto fail; - if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0, + if (grub_disk_read (disk, block << lbshift, 0, sizeof (struct grub_udf_fileset), &root_fs)) { grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); @@ -704,7 +797,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, { grub_fshelp_node_t child; struct grub_udf_file_ident dirent; - grub_uint32_t offset = 0; + grub_off_t offset = 0; child = grub_malloc (sizeof (struct grub_fshelp_node)); if (!child) @@ -729,57 +822,60 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, return 0; } - child = grub_malloc (sizeof (struct grub_fshelp_node)); - if (!child) - return 0; - - if (grub_udf_read_icb (dir->data, &dirent.icb, child)) - return 0; - offset += sizeof (dirent) + U16 (dirent.imp_use_length); - if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT) + if (!(dirent.characteristics & GRUB_UDF_FID_CHAR_DELETED)) { - /* This is the parent directory. */ - if (hook ("..", GRUB_FSHELP_DIR, child)) - return 1; - } - else - { - enum grub_fshelp_filetype type; - grub_uint8_t raw[dirent.file_ident_length]; - grub_uint16_t utf16[dirent.file_ident_length - 1]; - grub_uint8_t filename[dirent.file_ident_length * 2]; - grub_size_t utf16len = 0; - - type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? - (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); - - if ((grub_udf_read_file (dir, 0, offset, - dirent.file_ident_length, - (char *) raw)) - != dirent.file_ident_length) + child = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!child) return 0; - if (raw[0] == 8) + if (grub_udf_read_icb (dir->data, &dirent.icb, child)) + return 0; + + if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT) { - unsigned i; - utf16len = dirent.file_ident_length - 1; - for (i = 0; i < utf16len; i++) - utf16[i] = raw[i + 1]; + /* This is the parent directory. */ + if (hook ("..", GRUB_FSHELP_DIR, child)) + return 1; } - if (raw[0] == 16) + else { - unsigned i; - utf16len = (dirent.file_ident_length - 1) / 2; - for (i = 0; i < utf16len; i++) - utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; - } - if (raw[0] == 8 || raw[0] == 16) - { - *grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0'; - - if (hook ((char *) filename, type, child)) - return 1; + enum grub_fshelp_filetype type; + grub_uint8_t raw[dirent.file_ident_length]; + grub_uint16_t utf16[dirent.file_ident_length - 1]; + grub_uint8_t filename[dirent.file_ident_length * 2]; + grub_size_t utf16len = 0; + + type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? + (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); + + if ((grub_udf_read_file (dir, 0, offset, + dirent.file_ident_length, + (char *) raw)) + != dirent.file_ident_length) + return 0; + + if (raw[0] == 8) + { + unsigned i; + utf16len = dirent.file_ident_length - 1; + for (i = 0; i < utf16len; i++) + utf16[i] = raw[i + 1]; + } + if (raw[0] == 16) + { + unsigned i; + utf16len = (dirent.file_ident_length - 1) / 2; + for (i = 0; i < utf16len; i++) + utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; + } + if (raw[0] == 8 || raw[0] == 16) + { + *grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0'; + + if (hook ((char *) filename, type, child)) + return 1; + } } } diff --git a/fs/ufs.c b/grub-core/fs/ufs.c similarity index 99% rename from fs/ufs.c rename to grub-core/fs/ufs.c index 40cf068e6..2b1021db6 100644 --- a/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -568,7 +568,6 @@ grub_ufs_dir (grub_device_t device, const char *path, const struct grub_dirhook_info *info)) { struct grub_ufs_data *data; - struct grub_ufs_sblock *sblock; unsigned int pos = 0; data = grub_ufs_mount (device->disk); @@ -579,8 +578,6 @@ grub_ufs_dir (grub_device_t device, const char *path, if (grub_errno) return grub_errno; - sblock = &data->sblock; - if (!path || path[0] != '/') { grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); diff --git a/fs/ufs2.c b/grub-core/fs/ufs2.c similarity index 100% rename from fs/ufs2.c rename to grub-core/fs/ufs2.c diff --git a/fs/xfs.c b/grub-core/fs/xfs.c similarity index 100% rename from fs/xfs.c rename to grub-core/fs/xfs.c diff --git a/genemuinit.sh b/grub-core/genemuinit.sh similarity index 100% rename from genemuinit.sh rename to grub-core/genemuinit.sh diff --git a/genemuinitheader.sh b/grub-core/genemuinitheader.sh similarity index 100% rename from genemuinitheader.sh rename to grub-core/genemuinitheader.sh diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in new file mode 100644 index 000000000..8dfd5d347 --- /dev/null +++ b/grub-core/genmod.sh.in @@ -0,0 +1,73 @@ +#! /bin/sh -e +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This gensymlist.sh is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program 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. + +# +# Example: +# +# genmod.sh moddep.lst normal.module normal.mod +# + +moddep=$1 +infile=$2 +outfile=$3 + +tmpfile=${outfile}.tmp +modname=`echo $infile | sed -e 's@\.module.*$@@'` + +if ! grep ^$modname: $moddep >/dev/null; then + echo "warning: moddep.lst has no dependencies for $modname" >&2 + exit 0 +fi + +deps=`grep ^$modname: $moddep | sed s@^.*:@@` + +# remove old files if any +rm -f $tmpfile $outfile + +# stripout .modname and .moddeps sections from input module +objcopy -R .modname -R .moddeps $infile $tmpfile + +# Attach .modname and .moddeps sections +t1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 +printf "$modname\0" >$t1 + +t2=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 +for dep in $deps; do printf "$dep\0" >> $t2; done + +if test -n "$deps"; then + objcopy --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile +else + objcopy --add-section .modname=$t1 $tmpfile +fi +rm -f $t1 $t2 + +if test x@TARGET_APPLE_CC@ != x1; then + if ! test -z "@TARGET_OBJ2ELF@"; then + ./@TARGET_OBJ2ELF@ $tmpfile || exit 1 + fi + if test x@platform@ != xemu; then + @STRIP@ --strip-unneeded \ + -K grub_mod_init -K grub_mod_fini \ + -K _grub_mod_init -K _grub_mod_fini \ + -R .note -R .comment $tmpfile || exit 1 + fi +else +# XXX Test these Apple CC fixes + cp $tmpfile $tmpfile.bin + @OBJCONV@ -f@TARGET_MODULE_FORMAT@ \ + -nr:_grub_mod_init:grub_mod_init \ + -nr:_grub_mod_fini:grub_mod_fini \ + -wd1106 -ew2030 -ew2050 -nu -nd $tmpfile.bin $tmpfile || exit 1 + rm -f $name.bin +fi +mv $tmpfile $outfile diff --git a/genmoddep.awk b/grub-core/genmoddep.awk similarity index 68% rename from genmoddep.awk rename to grub-core/genmoddep.awk index 48419a091..e412d4370 100644 --- a/genmoddep.awk +++ b/grub-core/genmoddep.awk @@ -11,27 +11,28 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. -# Read defined symbols from stdin. +# Read symbols' info from stdin. BEGIN { + error = 0 + lineno = 0; while (getline <"/dev/stdin") { - symtab[$1] = $2 - } -} - -# The first line contains a module name. -FNR == 1 { - module = $1 - next -}; - -# The rest is undefined symbols. -{ - if ($1 in symtab) { - modtab[module] = modtab[module] " " symtab[$1]; - } - else if ($1 != "__gnu_local_gp") { - printf "%s in %s is not defined\n", $1, module >"/dev/stderr"; - error++; + lineno++; + if ($1 == "defined") { + symtab[$3] = $2; + modtab[$2] = "" modtab[$2] + } else if ($1 == "undefined") { + if ($3 in symtab) + modtab[$2] = modtab[$2] " " symtab[$3]; + else if ($3 != "__gnu_local_gp") { + printf "%s in %s is not defined\n", $3, $2 >"/dev/stderr"; + error++; + } + } + else { + printf "error: %u: unrecognized input format\n", lineno; + error++; + break; + } } } diff --git a/grub-core/gensyminfo.sh.in b/grub-core/gensyminfo.sh.in new file mode 100644 index 000000000..4f5184913 --- /dev/null +++ b/grub-core/gensyminfo.sh.in @@ -0,0 +1,34 @@ +#! /bin/sh -e +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This gensymlist.sh is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program 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. + +# +# Example: +# +# gensyms.sh normal.module +# + +module=$1 +modname=`echo $module | sed -e 's@\.module.*$@@'` + +# Print all symbols defined by module +if test x@TARGET_APPLE_CC@ = x1; then + @NM@ -g -P -p $module | \ + grep -E '^[a-zA-Z0-9_]* [TDS]' | \ + sed "s@^\([^ ]*\).*@defined $modname \1@g" +else + @NM@ -g --defined-only -P -p $module | \ + sed "s@^\([^ ]*\).*@defined $modname \1@g" +fi + +# Print all undefined symbols used by module +@NM@ -u -P -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" diff --git a/gensymlist.sh.in b/grub-core/gensymlist.sh similarity index 84% rename from gensymlist.sh.in rename to grub-core/gensymlist.sh index 3c3ddfa6c..0ab56e9cb 100644 --- a/gensymlist.sh.in +++ b/grub-core/gensymlist.sh @@ -1,6 +1,6 @@ #! /bin/sh # -# Copyright (C) 2002,2006,2007,2008 Free Software Foundation, Inc. +# Copyright (C) 2002,2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # This gensymlist.sh.in is free software; the author # gives unlimited permission to copy and/or distribute it, @@ -11,17 +11,11 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. -### The configure script will replace these variables. - -: ${srcdir=@srcdir@} -: ${CC=@TARGET_CC@} - - cat <. */ -#include EOF for i in $*; do @@ -60,7 +53,7 @@ cat < int -main () +main (int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) { int i; diff --git a/gettext/gettext.c b/grub-core/gettext/gettext.c similarity index 98% rename from gettext/gettext.c rename to grub-core/gettext/gettext.c index bc7d42824..9ab4c3b8d 100644 --- a/gettext/gettext.c +++ b/grub-core/gettext/gettext.c @@ -26,7 +26,6 @@ #include #include #include -#include #include /* @@ -219,7 +218,7 @@ grub_gettext_translate (const char *orig) return ret; } -/* This is similar to grub_gzfile_open. */ +/* This is similar to grub_file_open. */ static grub_file_t grub_mofile_open (const char *filename) { @@ -229,7 +228,7 @@ grub_mofile_open (const char *filename) /* Using fd_mo and not another variable because it's needed for grub_gettext_get_info. */ - fd_mo = grub_gzfile_open (filename, 1); + fd_mo = grub_file_open (filename); grub_errno = GRUB_ERR_NONE; if (!fd_mo) @@ -288,8 +287,10 @@ grub_gettext_init_ext (const char *lang) /* Will try adding .gz as well. */ if (fd_mo == NULL) { - grub_free (mo_file); + char *mo_file_old; + mo_file_old = mo_file; mo_file = grub_xasprintf ("%s.gz", mo_file); + grub_free (mo_file_old); if (!mo_file) return; fd_mo = grub_mofile_open (mo_file); diff --git a/gfxmenu/font.c b/grub-core/gfxmenu/font.c similarity index 100% rename from gfxmenu/font.c rename to grub-core/gfxmenu/font.c diff --git a/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c similarity index 100% rename from gfxmenu/gfxmenu.c rename to grub-core/gfxmenu/gfxmenu.c diff --git a/gfxmenu/gui_box.c b/grub-core/gfxmenu/gui_box.c similarity index 100% rename from gfxmenu/gui_box.c rename to grub-core/gfxmenu/gui_box.c diff --git a/gfxmenu/gui_canvas.c b/grub-core/gfxmenu/gui_canvas.c similarity index 100% rename from gfxmenu/gui_canvas.c rename to grub-core/gfxmenu/gui_canvas.c diff --git a/gfxmenu/gui_circular_progress.c b/grub-core/gfxmenu/gui_circular_progress.c similarity index 100% rename from gfxmenu/gui_circular_progress.c rename to grub-core/gfxmenu/gui_circular_progress.c diff --git a/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c similarity index 100% rename from gfxmenu/gui_image.c rename to grub-core/gfxmenu/gui_image.c diff --git a/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c similarity index 100% rename from gfxmenu/gui_label.c rename to grub-core/gfxmenu/gui_label.c diff --git a/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c similarity index 99% rename from gfxmenu/gui_list.c rename to grub-core/gfxmenu/gui_list.c index 8058fcc4f..b6b07dfd6 100644 --- a/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -563,7 +563,6 @@ grub_gui_list_new (void) list_impl_t self; grub_font_t default_font; grub_gui_color_t default_fg_color; - grub_gui_color_t default_bg_color; self = grub_zalloc (sizeof (*self)); if (! self) @@ -576,7 +575,6 @@ grub_gui_list_new (void) default_font = grub_font_get ("Unknown Regular 16"); default_fg_color = grub_gui_color_rgb (0, 0, 0); - default_bg_color = grub_gui_color_rgb (255, 255, 255); self->icon_width = 32; self->icon_height = 32; diff --git a/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c similarity index 100% rename from gfxmenu/gui_progress_bar.c rename to grub-core/gfxmenu/gui_progress_bar.c diff --git a/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c similarity index 100% rename from gfxmenu/gui_string_util.c rename to grub-core/gfxmenu/gui_string_util.c diff --git a/gfxmenu/gui_util.c b/grub-core/gfxmenu/gui_util.c similarity index 100% rename from gfxmenu/gui_util.c rename to grub-core/gfxmenu/gui_util.c diff --git a/gfxmenu/icon_manager.c b/grub-core/gfxmenu/icon_manager.c similarity index 100% rename from gfxmenu/icon_manager.c rename to grub-core/gfxmenu/icon_manager.c diff --git a/gfxmenu/model.c b/grub-core/gfxmenu/model.c similarity index 100% rename from gfxmenu/model.c rename to grub-core/gfxmenu/model.c diff --git a/gfxmenu/named_colors.c b/grub-core/gfxmenu/named_colors.c similarity index 100% rename from gfxmenu/named_colors.c rename to grub-core/gfxmenu/named_colors.c diff --git a/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c similarity index 100% rename from gfxmenu/theme_loader.c rename to grub-core/gfxmenu/theme_loader.c diff --git a/gfxmenu/view.c b/grub-core/gfxmenu/view.c similarity index 99% rename from gfxmenu/view.c rename to grub-core/gfxmenu/view.c index 518c3ba53..901cdc889 100644 --- a/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -309,10 +309,8 @@ redraw_menu_visit (grub_gui_component_t component, view = userdata; if (component->ops->is_instance (component, "list")) { - grub_gui_list_t list; grub_video_rect_t bounds; - list = (grub_gui_list_t) component; component->ops->get_bounds (component, &bounds); grub_gfxmenu_view_redraw (view, &bounds); } diff --git a/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c similarity index 94% rename from gfxmenu/widget-box.c rename to grub-core/gfxmenu/widget-box.c index 079fd66d4..244fe1e6c 100644 --- a/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -79,21 +79,9 @@ static void draw (grub_gfxmenu_box_t self, int x, int y) { int height_n; - int height_s; - int height_e; - int height_w; - int width_n; - int width_s; - int width_e; int width_w; height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); - height_s = get_height (self->scaled_pixmaps[BOX_PIXMAP_S]); - height_e = get_height (self->scaled_pixmaps[BOX_PIXMAP_E]); - height_w = get_height (self->scaled_pixmaps[BOX_PIXMAP_W]); - width_n = get_width (self->scaled_pixmaps[BOX_PIXMAP_N]); - width_s = get_width (self->scaled_pixmaps[BOX_PIXMAP_S]); - width_e = get_width (self->scaled_pixmaps[BOX_PIXMAP_E]); width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); /* Draw sides. */ 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/gnulib/alloca.h b/grub-core/gnulib/alloca.in.h similarity index 96% rename from gnulib/alloca.h rename to grub-core/gnulib/alloca.in.h index 107534e98..44f20b7a1 100644 --- a/gnulib/alloca.h +++ b/grub-core/gnulib/alloca.in.h @@ -5,7 +5,7 @@ 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, or (at your option) + 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, diff --git a/gnulib/argp-ba.c b/grub-core/gnulib/argp-ba.c similarity index 100% rename from gnulib/argp-ba.c rename to grub-core/gnulib/argp-ba.c diff --git a/gnulib/argp-eexst.c b/grub-core/gnulib/argp-eexst.c similarity index 100% rename from gnulib/argp-eexst.c rename to grub-core/gnulib/argp-eexst.c diff --git a/gnulib/argp-fmtstream.c b/grub-core/gnulib/argp-fmtstream.c similarity index 100% rename from gnulib/argp-fmtstream.c rename to grub-core/gnulib/argp-fmtstream.c diff --git a/gnulib/argp-fmtstream.h b/grub-core/gnulib/argp-fmtstream.h similarity index 100% rename from gnulib/argp-fmtstream.h rename to grub-core/gnulib/argp-fmtstream.h diff --git a/gnulib/argp-fs-xinl.c b/grub-core/gnulib/argp-fs-xinl.c similarity index 100% rename from gnulib/argp-fs-xinl.c rename to grub-core/gnulib/argp-fs-xinl.c diff --git a/gnulib/argp-help.c b/grub-core/gnulib/argp-help.c similarity index 100% rename from gnulib/argp-help.c rename to grub-core/gnulib/argp-help.c diff --git a/gnulib/argp-namefrob.h b/grub-core/gnulib/argp-namefrob.h similarity index 100% rename from gnulib/argp-namefrob.h rename to grub-core/gnulib/argp-namefrob.h diff --git a/gnulib/argp-parse.c b/grub-core/gnulib/argp-parse.c similarity index 100% rename from gnulib/argp-parse.c rename to grub-core/gnulib/argp-parse.c diff --git a/gnulib/argp-pin.c b/grub-core/gnulib/argp-pin.c similarity index 100% rename from gnulib/argp-pin.c rename to grub-core/gnulib/argp-pin.c diff --git a/gnulib/argp-pv.c b/grub-core/gnulib/argp-pv.c similarity index 100% rename from gnulib/argp-pv.c rename to grub-core/gnulib/argp-pv.c diff --git a/gnulib/argp-pvh.c b/grub-core/gnulib/argp-pvh.c similarity index 100% rename from gnulib/argp-pvh.c rename to grub-core/gnulib/argp-pvh.c diff --git a/gnulib/argp-xinl.c b/grub-core/gnulib/argp-xinl.c similarity index 100% rename from gnulib/argp-xinl.c rename to grub-core/gnulib/argp-xinl.c diff --git a/gnulib/argp.h b/grub-core/gnulib/argp.h similarity index 100% rename from gnulib/argp.h rename to grub-core/gnulib/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/gnulib/argp-version-etc.c b/grub-core/gnulib/btowc.c similarity index 52% rename from gnulib/argp-version-etc.c rename to grub-core/gnulib/btowc.c index f500a8f56..8744602aa 100644 --- a/gnulib/argp-version-etc.c +++ b/grub-core/gnulib/btowc.c @@ -1,5 +1,6 @@ -/* Version hook for Argp. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. +/* 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 @@ -15,24 +16,24 @@ along with this program. If not, see . */ #include -#include -#include -#include -static const char *program_canonical_name; -static const char * const *program_authors; +/* Specification. */ +#include -static void -version_etc_hook (FILE *stream, struct argp_state *state) +#include +#include + +wint_t +btowc (int c) { - version_etc_ar (stream, program_canonical_name, PACKAGE_NAME, VERSION, - program_authors); -} + if (c != EOF) + { + char buf[1]; + wchar_t wc; -void -argp_version_setup (const char *name, const char * const *authors) -{ - argp_program_version_hook = version_etc_hook; - program_canonical_name = name; - program_authors = authors; + 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/gnulib/error.c b/grub-core/gnulib/error.c similarity index 91% rename from gnulib/error.c rename to grub-core/gnulib/error.c index c79e8d42c..ed9dba0d2 100644 --- a/gnulib/error.c +++ b/grub-core/gnulib/error.c @@ -88,6 +88,15 @@ extern void __error_at_line (int status, int errnum, const char *file_name, # 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" @@ -104,10 +113,29 @@ extern char *program_name; # 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 && defined F_GETFL +#if !_LIBC int stdout_fd; # if GNULIB_FREOPEN_SAFER @@ -124,7 +152,7 @@ flush_stdout (void) /* 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 && 0 <= fcntl (stdout_fd, F_GETFL)) + if (0 <= stdout_fd && is_open (stdout_fd)) #endif fflush (stdout); } diff --git a/gnulib/error.h b/grub-core/gnulib/error.h similarity index 100% rename from gnulib/error.h rename to grub-core/gnulib/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/gnulib/fnmatch.c b/grub-core/gnulib/fnmatch.c similarity index 99% rename from gnulib/fnmatch.c rename to grub-core/gnulib/fnmatch.c index f15dbb806..d73e47dae 100644 --- a/gnulib/fnmatch.c +++ b/grub-core/gnulib/fnmatch.c @@ -3,7 +3,7 @@ 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, or (at your option) + 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, diff --git a/gnulib/fnmatch.h b/grub-core/gnulib/fnmatch.in.h similarity index 63% rename from gnulib/fnmatch.h rename to grub-core/gnulib/fnmatch.in.h index b086b45aa..8caab1959 100644 --- a/gnulib/fnmatch.h +++ b/grub-core/gnulib/fnmatch.in.h @@ -1,11 +1,11 @@ /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003, - 2005, 2007 Free Software Foundation, Inc. + 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 2, or (at your option) + 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, @@ -17,8 +17,10 @@ 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 +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +/* The definition of _GL_ARG_NONNULL is copied here. */ #ifdef __cplusplus extern "C" { @@ -26,37 +28,38 @@ extern "C" { /* 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 +#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. */ +#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. */ +# 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 +#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) +# 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); + int __flags) + _GL_ARG_NONNULL ((1, 2)); #ifdef __cplusplus } diff --git a/gnulib/fnmatch_loop.c b/grub-core/gnulib/fnmatch_loop.c similarity index 99% rename from gnulib/fnmatch_loop.c rename to grub-core/gnulib/fnmatch_loop.c index 8cd444404..741c993ef 100644 --- a/gnulib/fnmatch_loop.c +++ b/grub-core/gnulib/fnmatch_loop.c @@ -4,7 +4,7 @@ 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, or (at your option) + 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, diff --git a/gnulib/getdelim.c b/grub-core/gnulib/getdelim.c similarity index 98% rename from gnulib/getdelim.c rename to grub-core/gnulib/getdelim.c index c0240900c..66d07b9ae 100644 --- a/gnulib/getdelim.c +++ b/grub-core/gnulib/getdelim.c @@ -4,7 +4,7 @@ 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, or (at + 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 diff --git a/gnulib/getline.c b/grub-core/gnulib/getline.c similarity index 91% rename from gnulib/getline.c rename to grub-core/gnulib/getline.c index 6cf187be2..30c076e87 100644 --- a/gnulib/getline.c +++ b/grub-core/gnulib/getline.c @@ -3,7 +3,7 @@ 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, or (at + 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 @@ -21,7 +21,6 @@ #include #include -#include ssize_t getline (char **lineptr, size_t *n, FILE *stream) diff --git a/gnulib/getopt.c b/grub-core/gnulib/getopt.c similarity index 97% rename from gnulib/getopt.c rename to grub-core/gnulib/getopt.c index aaabc8d19..3791f1293 100644 --- a/gnulib/getopt.c +++ b/grub-core/gnulib/getopt.c @@ -348,8 +348,6 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int long_only, struct _getopt_data *d, int posixly_correct) { int print_errors = d->opterr; - if (optstring[0] == ':') - print_errors = 0; if (argc < 1) return -1; @@ -364,6 +362,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, 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 @@ -633,8 +635,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '--%s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -651,8 +653,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + _("%s: option '--%s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); @@ -736,13 +738,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, { char c = *d->__nextchar++; - char *temp = strchr (optstring, c); + 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 == ':') + if (temp == NULL || c == ':' || c == ';') { if (print_errors) { @@ -864,7 +866,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, pfound = p; indfound = option_index; } - else + 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; } @@ -876,7 +881,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) + argv[0], d->optarg) >= 0) { _IO_flockfile (stderr); @@ -892,7 +897,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]); + argv[0], d->optarg); #endif } d->__nextchar += strlen (d->__nextchar); @@ -955,8 +960,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -972,15 +977,17 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, free (buf); } #else - fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + 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; diff --git a/gnulib/getopt.h b/grub-core/gnulib/getopt.in.h similarity index 80% rename from gnulib/getopt.h rename to grub-core/gnulib/getopt.in.h index d2d3e6e63..57a8e8992 100644 --- a/gnulib/getopt.h +++ b/grub-core/gnulib/getopt.in.h @@ -1,6 +1,6 @@ /* Declarations for getopt. - Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007 - Free Software Foundation, Inc. + 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 @@ -16,24 +16,42 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef _GETOPT_H +#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 _GETOPT_H 1 +# 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. Then systematically rename + 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 -# include -# include -# include +# if !@HAVE_GETOPT_H@ +# include +# include +# include +# endif # undef __need_getopt # undef getopt # undef getopt_long @@ -42,6 +60,7 @@ # 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) @@ -52,6 +71,8 @@ # 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 @@ -94,12 +115,14 @@ # define __GNUC_PREREQ(maj, min) (0) # endif # if defined __cplusplus && __GNUC_PREREQ (2,8) -# define __THROW throw () +# define __THROW throw () # else # define __THROW # endif #endif +/* The definition of _GL_ARG_NONNULL is copied here. */ + #ifdef __cplusplus extern "C" { #endif @@ -142,9 +165,9 @@ extern int optopt; 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. + 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 @@ -169,10 +192,10 @@ struct option /* 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 */ +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ /* Get definitions and prototypes for functions to process the @@ -201,17 +224,17 @@ struct option the environment, then do not permute arguments. */ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) - __THROW; + __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; + 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; + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); #endif @@ -223,3 +246,4 @@ extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, #undef __need_getopt #endif /* getopt.h */ +#endif /* getopt.h */ diff --git a/gnulib/getopt1.c b/grub-core/gnulib/getopt1.c similarity index 100% rename from gnulib/getopt1.c rename to grub-core/gnulib/getopt1.c diff --git a/gnulib/getopt_int.h b/grub-core/gnulib/getopt_int.h similarity index 70% rename from gnulib/getopt_int.h rename to grub-core/gnulib/getopt_int.h index 169def5b2..980b7507f 100644 --- a/gnulib/getopt_int.h +++ b/grub-core/gnulib/getopt_int.h @@ -30,6 +30,40 @@ extern int _getopt_internal (int ___argc, char **___argv, /* 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 { @@ -54,39 +88,8 @@ struct _getopt_data by advancing to the next ARGV-element. */ char *__nextchar; - /* 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 - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - } __ordering; + /* See __ord above. */ + enum __ord __ordering; /* If the POSIXLY_CORRECT environment variable is set or getopt was called. */ diff --git a/gnulib/gettext.h b/grub-core/gnulib/gettext.h similarity index 99% rename from gnulib/gettext.h rename to grub-core/gnulib/gettext.h index 6a069c448..881ae3304 100644 --- a/gnulib/gettext.h +++ b/grub-core/gnulib/gettext.h @@ -4,7 +4,7 @@ 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, or (at your option) + 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, 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/gnulib/progname.c b/grub-core/gnulib/progname.c similarity index 100% rename from gnulib/progname.c rename to grub-core/gnulib/progname.c diff --git a/gnulib/progname.h b/grub-core/gnulib/progname.h similarity index 100% rename from gnulib/progname.h rename to grub-core/gnulib/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/gnulib/regcomp.c b/grub-core/gnulib/regcomp.c similarity index 99% rename from gnulib/regcomp.c rename to grub-core/gnulib/regcomp.c index 7eff56925..86ca02b0c 100644 --- a/gnulib/regcomp.c +++ b/grub-core/gnulib/regcomp.c @@ -6,7 +6,7 @@ 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, or (at your option) + 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, diff --git a/gnulib/regex.c b/grub-core/gnulib/regex.c similarity index 97% rename from gnulib/regex.c rename to grub-core/gnulib/regex.c index 904fe62c8..ba0eebee7 100644 --- a/gnulib/regex.c +++ b/grub-core/gnulib/regex.c @@ -6,7 +6,7 @@ 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, or (at your option) + 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, diff --git a/gnulib/regex.h b/grub-core/gnulib/regex.h similarity index 97% rename from gnulib/regex.h rename to grub-core/gnulib/regex.h index 594d5e6aa..e8bd5496c 100644 --- a/gnulib/regex.h +++ b/grub-core/gnulib/regex.h @@ -7,7 +7,7 @@ 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, or (at your option) + 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, @@ -114,10 +114,10 @@ typedef unsigned long int reg_syntax_t; /* 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. + ^ 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. @@ -219,8 +219,8 @@ typedef unsigned long int reg_syntax_t; whether ^ should be special. */ # define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) -/* If this bit is set, then \{ cannot be first in an bre or - immediately after an alternation or begin-group operator. */ +/* 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 @@ -495,8 +495,8 @@ struct re_pattern_buffer #endif unsigned int _REG_RE_NAME (regs_allocated) : 2; - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ + /* 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 @@ -610,8 +610,8 @@ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, 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. */ + 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, diff --git a/gnulib/regex_internal.c b/grub-core/gnulib/regex_internal.c similarity index 99% rename from gnulib/regex_internal.c rename to grub-core/gnulib/regex_internal.c index 378b767d8..98b8d5d21 100644 --- a/gnulib/regex_internal.c +++ b/grub-core/gnulib/regex_internal.c @@ -6,7 +6,7 @@ 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, or (at your option) + 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, @@ -733,15 +733,17 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) mbstate_t cur_state; wchar_t wc2; Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; 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)); diff --git a/gnulib/regex_internal.h b/grub-core/gnulib/regex_internal.h similarity index 99% rename from gnulib/regex_internal.h rename to grub-core/gnulib/regex_internal.h index e1b4c61b3..5aa5aa287 100644 --- a/gnulib/regex_internal.h +++ b/grub-core/gnulib/regex_internal.h @@ -6,7 +6,7 @@ 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, or (at your option) + 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, @@ -467,6 +467,8 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, # 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 diff --git a/gnulib/regexec.c b/grub-core/gnulib/regexec.c similarity index 99% rename from gnulib/regexec.c rename to grub-core/gnulib/regexec.c index 9388ac12b..dc449ce52 100644 --- a/gnulib/regexec.c +++ b/grub-core/gnulib/regexec.c @@ -6,7 +6,7 @@ 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, or (at your option) + 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, 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/gnulib/argp-version-etc.h b/grub-core/gnulib/strnlen1.h similarity index 52% rename from gnulib/argp-version-etc.h rename to grub-core/gnulib/strnlen1.h index 7c12c0181..dfaf62dcb 100644 --- a/gnulib/argp-version-etc.h +++ b/grub-core/gnulib/strnlen1.h @@ -1,5 +1,5 @@ -/* Version hook for Argp. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. +/* 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 @@ -14,27 +14,26 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef _ARGP_VERSION_ETC_H -#define _ARGP_VERSION_ETC_H +#ifndef _STRNLEN1_H +#define _STRNLEN1_H + +#include + #ifdef __cplusplus extern "C" { #endif -/* Setup standard display of the version information for the `--version' - option. NAME is the canonical program name, and AUTHORS is a NULL- - terminated array of author names. At least one author name must be - given. - If NAME is NULL, the package name (as given by the PACKAGE macro) - is asumed to be the name of the program. +/* 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); - This function is intended to be called before argp_parse(). -*/ -extern void argp_version_setup (const char *name, const char * const *authors); #ifdef __cplusplus } #endif -#endif /* _ARGP_VERSION_ETC_H */ + +#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/hello/hello.c b/grub-core/hello/hello.c similarity index 86% rename from hello/hello.c rename to grub-core/hello/hello.c index eff07d941..77c4c96b1 100644 --- a/hello/hello.c +++ b/grub-core/hello/hello.c @@ -27,7 +27,7 @@ #include static grub_err_t -grub_cmd_hello (struct grub_extcmd *cmd __attribute__ ((unused)), +grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { @@ -39,8 +39,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hello) { - cmd = grub_register_extcmd ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, - 0, N_("Say \"Hello World\"."), 0); + cmd = grub_register_extcmd ("hello", grub_cmd_hello, 0, 0, + N_("Say \"Hello World\"."), 0); } GRUB_MOD_FINI(hello) diff --git a/hook/datehook.c b/grub-core/hook/datehook.c similarity index 100% rename from hook/datehook.c rename to grub-core/hook/datehook.c diff --git a/io/bufio.c b/grub-core/io/bufio.c similarity index 98% rename from io/bufio.c rename to grub-core/io/bufio.c index 92f29279e..8a72ecd79 100644 --- a/io/bufio.c +++ b/grub-core/io/bufio.c @@ -74,6 +74,7 @@ grub_bufio_open (grub_file_t io, int size) file->data = bufio; file->read_hook = 0; file->fs = &grub_bufio_fs; + file->not_easly_seekable = io->not_easly_seekable; return file; } diff --git a/io/gzio.c b/grub-core/io/gzio.c similarity index 96% rename from io/gzio.c rename to grub-core/io/gzio.c index 9bf609105..43b67c373 100644 --- a/io/gzio.c +++ b/grub-core/io/gzio.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include /* * Window Size @@ -206,7 +206,7 @@ test_header (grub_file_t file) || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1)) || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1))) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, "unsupported gzip format"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); return 0; } @@ -214,12 +214,14 @@ test_header (grub_file_t file) grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4); - if (grub_file_read (gzio->file, &orig_len, 4) != 4) + if (grub_file_seekable (gzio->file)) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format"); - return 0; + if (grub_file_read (gzio->file, &orig_len, 4) != 4) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format"); + return 0; + } } - /* FIXME: this does not handle files whose original size is over 4GB. But how can we know the real original size? */ file->size = grub_le_to_cpu32 (orig_len); @@ -644,7 +646,7 @@ inflate_codes_in_window (grub_file_t file) { if (e == 99) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "an unused code found"); return 1; } @@ -683,7 +685,7 @@ inflate_codes_in_window (grub_file_t file) { if (e == 99) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "an unused code found"); return 1; } @@ -769,7 +771,7 @@ init_stored_block (grub_file_t file) DUMPBITS (16); NEEDBITS (16); if (gzio->block_len != (int) ((~b) & 0xffff)) - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "the length of a stored block does not match"); DUMPBITS (16); @@ -803,7 +805,7 @@ init_fixed_block (grub_file_t file) if (huft_build (l, 288, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0) { if (grub_errno == GRUB_ERR_NONE) - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); return; } @@ -815,7 +817,7 @@ init_fixed_block (grub_file_t file) if (huft_build (l, 30, 0, cpdist, cpdext, &gzio->td, &gzio->bd) > 1) { if (grub_errno == GRUB_ERR_NONE) - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); huft_free (gzio->tl); gzio->tl = 0; @@ -862,7 +864,7 @@ init_dynamic_block (grub_file_t file) DUMPBITS (4); if (nl > 286 || nd > 30) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, "too much data"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too much data"); return; } @@ -880,7 +882,7 @@ init_dynamic_block (grub_file_t file) gzio->bl = 7; if (huft_build (ll, 19, 19, NULL, NULL, &gzio->tl, &gzio->bl) != 0) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); return; } @@ -904,7 +906,7 @@ init_dynamic_block (grub_file_t file) DUMPBITS (2); if ((unsigned) i + j > n) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found"); return; } while (j--) @@ -917,7 +919,7 @@ init_dynamic_block (grub_file_t file) DUMPBITS (3); if ((unsigned) i + j > n) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found"); return; } while (j--) @@ -932,7 +934,7 @@ init_dynamic_block (grub_file_t file) DUMPBITS (7); if ((unsigned) i + j > n) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found"); return; } while (j--) @@ -954,7 +956,7 @@ init_dynamic_block (grub_file_t file) gzio->bl = lbits; if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0) { - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); return; } @@ -963,7 +965,7 @@ init_dynamic_block (grub_file_t file) { huft_free (gzio->tl); gzio->tl = 0; - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); return; } @@ -1039,7 +1041,7 @@ inflate_window (grub_file_t file) } if (gzio->block_type > INFLATE_DYNAMIC) - grub_error (GRUB_ERR_BAD_GZIP_DATA, + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unknown block type %d", gzio->block_type); if (grub_errno != GRUB_ERR_NONE) @@ -1111,8 +1113,8 @@ initialize_tables (grub_file_t file) /* Open a new decompressing object on the top of IO. If TRANSPARENT is true, even if IO does not contain data compressed by gzip, return a valid file object. Note that this function won't close IO, even if an error occurs. */ -grub_file_t -grub_gzio_open (grub_file_t io, int transparent) +static grub_file_t +grub_gzio_open (grub_file_t io) { grub_file_t file; grub_gzio_t gzio = 0; @@ -1135,6 +1137,7 @@ grub_gzio_open (grub_file_t io, int transparent) file->data = gzio; file->read_hook = 0; file->fs = &grub_gzio_fs; + file->not_easly_seekable = 1; if (! test_header (file)) { @@ -1142,33 +1145,11 @@ grub_gzio_open (grub_file_t io, int transparent) grub_free (file); grub_file_seek (io, 0); - if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && transparent) + if (grub_errno == GRUB_ERR_BAD_FILE_TYPE) { grub_errno = GRUB_ERR_NONE; return io; } - else - return 0; - } - - return file; -} - -/* This is similar to grub_gzio_open, but takes a file name as an argument. */ -grub_file_t -grub_gzfile_open (const char *name, int transparent) -{ - grub_file_t io, file; - - io = grub_file_open (name); - if (! io) - return 0; - - file = grub_gzio_open (io, transparent); - if (! file) - { - grub_file_close (io); - return 0; } return file; @@ -1249,3 +1230,13 @@ static struct grub_fs grub_gzio_fs = .label = 0, .next = 0 }; + +GRUB_MOD_INIT(gzio) +{ + grub_file_filter_register (GRUB_FILE_FILTER_GZIO, grub_gzio_open); +} + +GRUB_MOD_FINI(gzio) +{ + grub_file_filter_unregister (GRUB_FILE_FILTER_GZIO); +} diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c new file mode 100644 index 000000000..1a22bdc70 --- /dev/null +++ b/grub-core/io/xzio.c @@ -0,0 +1,353 @@ +/* xzio.c - decompression support for xz */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include "xz.h" +#include "xz_stream.h" + +#define XZBUFSIZ 0x2000 +#define VLI_MAX_DIGITS 9 +#define XZ_STREAM_FOOTER_SIZE 12 + +struct grub_xzio +{ + grub_file_t file; + struct xz_buf buf; + struct xz_dec *dec; + grub_uint8_t inbuf[XZBUFSIZ]; + grub_uint8_t outbuf[XZBUFSIZ]; + grub_off_t saved_offset; +}; + +typedef struct grub_xzio *grub_xzio_t; +static struct grub_fs grub_xzio_fs; + +static grub_size_t +decode_vli (const grub_uint8_t buf[], grub_size_t size_max, + grub_uint64_t * num) +{ + if (size_max == 0) + return 0; + + if (size_max > VLI_MAX_DIGITS) + size_max = VLI_MAX_DIGITS; + + *num = buf[0] & 0x7F; + grub_size_t i = 0; + + while (buf[i++] & 0x80) + { + if (i >= size_max || buf[i] == 0x00) + return 0; + + *num |= (uint64_t) (buf[i] & 0x7F) << (i * 7); + } + + return i; +} + +static grub_ssize_t +read_vli (grub_file_t file, grub_uint64_t * num) +{ + grub_uint8_t buf[VLI_MAX_DIGITS]; + grub_ssize_t read; + grub_size_t dec; + + read = grub_file_read (file, buf, VLI_MAX_DIGITS); + if (read < 0) + return -1; + + dec = decode_vli (buf, read, num); + grub_file_seek (file, file->offset - (read - dec)); + return dec; +} + +/* Function xz_dec_run() should consume header and ask for more (XZ_OK) + * else file is corrupted (or options not supported) or not xz. */ +static int +test_header (grub_file_t file) +{ + grub_xzio_t xzio = file->data; + xzio->buf.in_size = grub_file_read (xzio->file, xzio->inbuf, + STREAM_HEADER_SIZE); + + if (xzio->buf.in_size != STREAM_HEADER_SIZE) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "no xz magic found"); + return 0; + } + + enum xz_ret ret = xz_dec_run (xzio->dec, &xzio->buf); + + if (ret == XZ_FORMAT_ERROR) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "no xz magic found"); + return 0; + } + + if (ret != XZ_OK) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "not supported xz options"); + return 0; + } + + return 1; +} + +/* Try to find out size of uncompressed data, + * also do some footer sanity checks. */ +static int +test_footer (grub_file_t file) +{ + grub_xzio_t xzio = file->data; + grub_uint8_t footer[FOOTER_MAGIC_SIZE]; + grub_uint32_t backsize; + grub_uint8_t imarker; + grub_uint64_t uncompressed_size_total = 0; + grub_uint64_t uncompressed_size; + grub_uint64_t records; + + grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE); + if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) != + FOOTER_MAGIC_SIZE + || grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0) + goto ERROR; + + grub_file_seek (xzio->file, xzio->file->size - 8); + if (grub_file_read (xzio->file, &backsize, sizeof (backsize)) + != sizeof (backsize)) + goto ERROR; + + /* Calculate real backward size. */ + backsize = (grub_le_to_cpu32 (backsize) + 1) * 4; + + /* Set file to the beginning of stream index. */ + grub_file_seek (xzio->file, + xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize); + + /* Test index marker. */ + if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) != + sizeof (imarker) && imarker != 0x00) + goto ERROR; + + if (read_vli (xzio->file, &records) <= 0) + goto ERROR; + + for (; records != 0; records--) + { + if (read_vli (xzio->file, &uncompressed_size) <= 0) /* Ignore unpadded. */ + goto ERROR; + if (read_vli (xzio->file, &uncompressed_size) <= 0) /* Uncompressed. */ + goto ERROR; + + uncompressed_size_total += uncompressed_size; + } + + file->size = uncompressed_size_total; + grub_file_seek (xzio->file, STREAM_HEADER_SIZE); + return 1; + +ERROR: + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "bad footer magic"); + return 0; +} + +static grub_file_t +grub_xzio_open (grub_file_t io) +{ + grub_file_t file; + grub_xzio_t xzio; + + file = (grub_file_t) grub_zalloc (sizeof (*file)); + if (!file) + return 0; + + xzio = grub_zalloc (sizeof (*xzio)); + if (!xzio) + { + grub_free (file); + return 0; + } + + 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_easly_seekable = 1; + + if (grub_file_tell (xzio->file) != 0) + grub_file_seek (xzio->file, 0); + + /* Allocated 64KiB for dictionary. + * Decoder will relocate if bigger is needed. */ + xzio->dec = xz_dec_init (1 << 16); + if (!xzio->dec) + { + grub_free (file); + grub_free (xzio); + return 0; + } + + 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; + + if (!test_header (file) || !(grub_file_seekable (io) && test_footer (file))) + { + grub_errno = GRUB_ERR_NONE; + grub_file_seek (io, 0); + xz_dec_end (xzio->dec); + grub_free (xzio); + grub_free (file); + + return io; + } + + return file; +} + +static grub_ssize_t +grub_xzio_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_ssize_t ret = 0; + grub_ssize_t readret; + enum xz_ret xzret; + grub_xzio_t xzio = file->data; + grub_off_t current_offset; + + /* If seek backward need to reset decoder and start from beginning of file. + TODO Possible improvement by jumping blocks. */ + if (file->offset < xzio->saved_offset) + { + xz_dec_reset (xzio->dec); + xzio->saved_offset = 0; + xzio->buf.out_pos = 0; + xzio->buf.in_pos = 0; + xzio->buf.in_size = 0; + grub_file_seek (xzio->file, 0); + } + + current_offset = xzio->saved_offset; + + while (len > 0) + { + xzio->buf.out_size = grub_min (file->offset + ret + len - current_offset, + XZBUFSIZ); + + /* Feed input. */ + if (xzio->buf.in_pos == xzio->buf.in_size) + { + readret = grub_file_read (xzio->file, xzio->inbuf, XZBUFSIZ); + if (readret < 0) + return -1; + xzio->buf.in_size = readret; + xzio->buf.in_pos = 0; + } + + xzret = xz_dec_run (xzio->dec, &xzio->buf); + switch (xzret) + { + case XZ_MEMLIMIT_ERROR: + case XZ_FORMAT_ERROR: + case XZ_OPTIONS_ERROR: + case XZ_DATA_ERROR: + case XZ_BUF_ERROR: + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "file corrupted or unsupported block options"); + return -1; + default: + break; + } + + { + grub_off_t new_offset = current_offset + xzio->buf.out_pos; + + if (file->offset <= new_offset) + /* Store first chunk of data in buffer. */ + { + grub_size_t delta = new_offset - (file->offset + ret); + grub_memmove (buf, xzio->buf.out + (xzio->buf.out_pos - delta), + delta); + len -= delta; + buf += delta; + ret += delta; + } + current_offset = new_offset; + } + xzio->buf.out_pos = 0; + + if (xzret == XZ_STREAM_END) /* Stream end, EOF. */ + break; + } + + if (ret >= 0) + xzio->saved_offset = file->offset + ret; + + return ret; +} + +/* Release everything, including the underlying file object. */ +static grub_err_t +grub_xzio_close (grub_file_t file) +{ + grub_xzio_t xzio = file->data; + + xz_dec_end (xzio->dec); + + grub_file_close (xzio->file); + grub_free (xzio); + + /* Device must not be closed twice. */ + file->device = 0; + return grub_errno; +} + +static struct grub_fs grub_xzio_fs = { + .name = "xzio", + .dir = 0, + .open = 0, + .read = grub_xzio_read, + .close = grub_xzio_close, + .label = 0, + .next = 0 +}; + +GRUB_MOD_INIT (xzio) +{ + grub_file_filter_register (GRUB_FILE_FILTER_XZIO, grub_xzio_open); +} + +GRUB_MOD_FINI (xzio) +{ + grub_file_filter_unregister (GRUB_FILE_FILTER_XZIO); +} diff --git a/kern/command.c b/grub-core/kern/command.c similarity index 97% rename from kern/command.c rename to grub-core/kern/command.c index 477240d57..7f353b653 100644 --- a/kern/command.c +++ b/grub-core/kern/command.c @@ -40,7 +40,7 @@ grub_register_command_prio (const char *name, cmd->summary = (summary) ? summary : ""; cmd->description = description; - cmd->flags = GRUB_COMMAND_FLAG_BOTH; + cmd->flags = 0; cmd->prio = prio; grub_prio_list_insert (GRUB_AS_PRIO_LIST_P (&grub_command_list), diff --git a/kern/corecmd.c b/grub-core/kern/corecmd.c similarity index 95% rename from kern/corecmd.c rename to grub-core/kern/corecmd.c index 8675248d3..687692f3c 100644 --- a/kern/corecmd.c +++ b/grub-core/kern/corecmd.c @@ -178,9 +178,12 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), void grub_register_core_commands (void) { - grub_register_command ("set", grub_core_cmd_set, - N_("[ENVVAR=VALUE]"), - N_("Set an environment variable.")); + grub_command_t cmd; + cmd = grub_register_command ("set", grub_core_cmd_set, + N_("[ENVVAR=VALUE]"), + N_("Set an environment variable.")); + if (cmd) + cmd->flags |= GRUB_COMMAND_FLAG_EXTRACTOR; grub_register_command ("unset", grub_core_cmd_unset, N_("ENVVAR"), N_("Remove an environment variable.")); diff --git a/kern/device.c b/grub-core/kern/device.c similarity index 89% rename from kern/device.c rename to grub-core/kern/device.c index 4273fedfe..3db14f50e 100644 --- a/kern/device.c +++ b/grub-core/kern/device.c @@ -103,7 +103,7 @@ grub_device_iterate (int (*hook) (const char *name)) return 0; } - if (dev->disk && dev->disk->has_partitions) + if (dev->disk) { struct part_ent *p; int ret = 0; @@ -135,28 +135,28 @@ grub_device_iterate (int (*hook) (const char *name)) int iterate_partition (grub_disk_t disk, const grub_partition_t partition) { - char *partition_name; struct part_ent *p; - - partition_name = grub_partition_get_name (partition); - if (! partition_name) - return 1; + char *part_name; p = grub_malloc (sizeof (*p)); if (!p) { - grub_free (partition_name); return 1; } - p->name = grub_xasprintf ("%s,%s", disk->name, partition_name); - if (!p->name) + 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 (partition_name); grub_free (p); return 1; } - grub_free (partition_name); p->next = ents; ents = p; diff --git a/kern/disk.c b/grub-core/kern/disk.c similarity index 98% rename from kern/disk.c rename to grub-core/kern/disk.c index ccd5f200f..807ee4277 100644 --- a/kern/disk.c +++ b/grub-core/kern/disk.c @@ -248,10 +248,6 @@ grub_disk_open (const char *name) if (! disk) return 0; - disk->name = grub_strdup (name); - if (! disk->name) - goto fail; - p = find_part_sep (name); if (p) { @@ -263,7 +259,13 @@ grub_disk_open (const char *name) grub_memcpy (raw, name, len); raw[len] = '\0'; + disk->name = grub_strdup (raw); } + else + disk->name = grub_strdup (name); + if (! disk->name) + goto fail; + for (dev = grub_disk_dev_list; dev; dev = dev->next) { @@ -281,12 +283,6 @@ grub_disk_open (const char *name) goto fail; } - if (p && ! disk->has_partitions) - { - grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk"); - goto fail; - } - disk->dev = dev; if (p) diff --git a/kern/dl.c b/grub-core/kern/dl.c similarity index 97% rename from kern/dl.c rename to grub-core/kern/dl.c index 09849f174..02d785b9b 100644 --- a/kern/dl.c +++ b/grub-core/kern/dl.c @@ -682,20 +682,3 @@ grub_dl_unload_unneeded (void) p = p->next; } } - -/* Unload all modules. */ -void -grub_dl_unload_all (void) -{ - while (grub_dl_head) - { - grub_dl_t p; - - grub_dl_unload_unneeded (); - - /* Force to decrement the ref count. This will purge pre-loaded - modules and manually inserted modules. */ - for (p = grub_dl_head; p; p = p->next) - p->ref_count--; - } -} diff --git a/kern/efi/efi.c b/grub-core/kern/efi/efi.c similarity index 95% rename from kern/efi/efi.c rename to grub-core/kern/efi/efi.c index 126e40901..fa1d0c730 100644 --- a/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -174,26 +174,6 @@ grub_reboot (void) } #endif -void -grub_halt (void) -{ - grub_efi_fini (); - efi_call_4 (grub_efi_system_table->runtime_services->reset_system, - GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); - for (;;) ; -} - -int -grub_efi_exit_boot_services (grub_efi_uintn_t map_key) -{ - grub_efi_boot_services_t *b; - grub_efi_status_t status; - - b = grub_efi_system_table->boot_services; - status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, map_key); - return status == GRUB_EFI_SUCCESS; -} - grub_err_t grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, grub_efi_uintn_t descriptor_size, @@ -760,26 +740,3 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) dp = (grub_efi_device_path_t *) ((char *) dp + len); } } - -int -grub_efi_finish_boot_services (void) -{ - grub_efi_uintn_t mmap_size = 0; - grub_efi_uintn_t map_key; - grub_efi_uintn_t desc_size; - grub_efi_uint32_t desc_version; - void *mmap_buf = 0; - - if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, - &desc_size, &desc_version) < 0) - return 0; - - mmap_buf = grub_malloc (mmap_size); - - if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, - &desc_size, &desc_version) <= 0) - return 0; - - return grub_efi_exit_boot_services (map_key); -} - diff --git a/kern/efi/init.c b/grub-core/kern/efi/init.c similarity index 75% rename from kern/efi/init.c rename to grub-core/kern/efi/init.c index c124aa292..1b0a872b4 100644 --- a/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -66,10 +66,33 @@ grub_efi_set_prefix (void) path = grub_strdup (pptr); } - if (!device || !path) + if ((!device || device[0] == ',' || !device[0]) || !path) image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (image && !device) - device = grub_efidisk_get_device_name (image->device_handle); + if (image) + { + if (!device) + device = grub_efidisk_get_device_name (image->device_handle); + else if (device[0] == ',' || !device[0]) + { + /* We have a partition, but still need to fill in the drive. */ + char *image_device, *comma, *new_device; + + image_device = grub_efidisk_get_device_name (image->device_handle); + comma = grub_strchr (image_device, ','); + if (comma) + { + char *drive = grub_strndup (image_device, comma - image_device); + new_device = grub_xasprintf ("%s%s", drive, device); + grub_free (drive); + } + else + new_device = grub_xasprintf ("%s%s", image_device, device); + + grub_free (image_device); + grub_free (device); + device = new_device; + } + } if (image && !path) { diff --git a/kern/efi/mm.c b/grub-core/kern/efi/mm.c similarity index 81% rename from kern/efi/mm.c rename to grub-core/kern/efi/mm.c index 2abd6325d..a715da076 100644 --- a/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -25,30 +25,23 @@ #define NEXT_MEMORY_DESCRIPTOR(desc, size) \ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) -#define BYTES_TO_PAGES(bytes) ((bytes) >> 12) +#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) #define PAGES_TO_BYTES(pages) ((pages) << 12) /* The size of a memory map obtained from the firmware. This must be a multiplier of 4KB. */ #define MEMORY_MAP_SIZE 0x3000 -/* Maintain the list of allocated pages. */ -struct allocated_page -{ - grub_efi_physical_address_t addr; - grub_efi_uint64_t num_pages; -}; - -#define ALLOCATED_PAGES_SIZE 0x1000 -#define MAX_ALLOCATED_PAGES \ - (ALLOCATED_PAGES_SIZE / sizeof (struct allocated_page)) - -static struct allocated_page *allocated_pages = 0; - /* The minimum and maximum heap size for GRUB itself. */ #define MIN_HEAP_SIZE 0x100000 #define MAX_HEAP_SIZE (1600 * 0x100000) +static void *finish_mmap_buf = 0; +static grub_efi_uintn_t finish_mmap_size = 0; +static grub_efi_uintn_t finish_key = 0; +static grub_efi_uintn_t finish_desc_size; +static grub_efi_uint32_t finish_desc_version; +int grub_efi_is_finished = 0; /* Allocate pages. Return the pointer to the first of allocated pages. */ void * @@ -96,22 +89,6 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, return 0; } - if (allocated_pages) - { - unsigned i; - - for (i = 0; i < MAX_ALLOCATED_PAGES; i++) - if (allocated_pages[i].addr == 0) - { - allocated_pages[i].addr = address; - allocated_pages[i].num_pages = pages; - break; - } - - if (i == MAX_ALLOCATED_PAGES) - grub_fatal ("too many page allocations"); - } - return (void *) ((grub_addr_t) address); } @@ -122,24 +99,55 @@ grub_efi_free_pages (grub_efi_physical_address_t address, { grub_efi_boot_services_t *b; - if (allocated_pages - && ((grub_efi_physical_address_t) ((grub_addr_t) allocated_pages) - != address)) - { - unsigned i; - - for (i = 0; i < MAX_ALLOCATED_PAGES; i++) - if (allocated_pages[i].addr == address) - { - allocated_pages[i].addr = 0; - break; - } - } - b = grub_efi_system_table->boot_services; efi_call_2 (b->free_pages, address, pages); } +grub_err_t +grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *efi_desc_size, + grub_efi_uint32_t *efi_desc_version) +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + + 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"); + + finish_mmap_buf = grub_malloc (finish_mmap_size); + if (!finish_mmap_buf) + return grub_errno; + + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) <= 0) + return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + + 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"); + + grub_efi_is_finished = 1; + if (outbuf_size) + *outbuf_size = finish_mmap_size; + if (outbuf) + grub_memcpy (outbuf, finish_mmap_buf, finish_mmap_size); + if (map_key) + *map_key = finish_key; + if (efi_desc_size) + *efi_desc_size = finish_desc_size; + if (efi_desc_version) + *efi_desc_version = finish_desc_version; + + return GRUB_ERR_NONE; +} + /* 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 @@ -154,6 +162,29 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size, grub_efi_uintn_t key; grub_efi_uint32_t version; + if (grub_efi_is_finished) + { + int ret = 1; + if (*memory_map_size < finish_mmap_size) + { + grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size); + ret = 0; + } + else + { + grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size); + ret = 1; + } + *memory_map_size = finish_mmap_size; + if (map_key) + *map_key = finish_key; + if (descriptor_size) + *descriptor_size = finish_desc_size; + if (descriptor_version) + *descriptor_version = finish_desc_version; + return ret; + } + /* Allow some parameters to be missing. */ if (! map_key) map_key = &key; @@ -348,14 +379,6 @@ grub_efi_mm_init (void) grub_efi_uint64_t required_pages; int mm_status; - /* First of all, allocate pages to maintain allocations. */ - allocated_pages - = grub_efi_allocate_pages (0, BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE)); - if (! allocated_pages) - grub_fatal ("cannot allocate memory"); - - grub_memset (allocated_pages, 0, ALLOCATED_PAGES_SIZE); - /* Prepare a memory region to store two memory maps. */ memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); @@ -373,6 +396,9 @@ grub_efi_mm_init (void) ((grub_efi_physical_address_t) ((grub_addr_t) memory_map), 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + /* Freeing/allocating operations may increase memory map size. */ + map_size += desc_size * 32; + memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size)); if (! memory_map) grub_fatal ("cannot allocate memory"); @@ -425,24 +451,3 @@ grub_efi_mm_init (void) grub_efi_free_pages ((grub_addr_t) memory_map, 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); } - -void -grub_efi_mm_fini (void) -{ - if (allocated_pages) - { - unsigned i; - - for (i = 0; i < MAX_ALLOCATED_PAGES; i++) - { - struct allocated_page *p; - - p = allocated_pages + i; - if (p->addr != 0) - grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages); - } - - grub_efi_free_pages ((grub_addr_t) allocated_pages, - BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE)); - } -} diff --git a/kern/elf.c b/grub-core/kern/elf.c similarity index 95% rename from kern/elf.c rename to grub-core/kern/elf.c index d9948a822..56218b4e4 100644 --- a/kern/elf.c +++ b/grub-core/kern/elf.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -95,7 +94,7 @@ grub_elf_open (const char *name) grub_file_t file; grub_elf_t elf; - file = grub_gzfile_open (name, 1); + file = grub_file_open (name); if (! file) return 0; @@ -140,7 +139,7 @@ grub_elf32_load_phdrs (grub_elf_t elf) return GRUB_ERR_NONE; } -static grub_err_t +grub_err_t grub_elf32_phdr_iterate (grub_elf_t elf, int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *), void *hook_arg) @@ -172,11 +171,12 @@ grub_elf32_phdr_iterate (grub_elf_t elf, /* Calculate the amount of memory spanned by the segments. */ grub_size_t -grub_elf32_size (grub_elf_t elf, Elf32_Addr *base) +grub_elf32_size (grub_elf_t elf, 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. */ @@ -193,6 +193,8 @@ grub_elf32_size (grub_elf_t elf, Elf32_Addr *base) 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; } @@ -216,7 +218,8 @@ grub_elf32_size (grub_elf_t elf, Elf32_Addr *base) if (base) *base = segments_start; - + if (max_align) + *max_align = curr_align; return segments_end - segments_start; } @@ -291,7 +294,6 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, return err; } - /* 64-bit */ @@ -326,7 +328,7 @@ grub_elf64_load_phdrs (grub_elf_t elf) return GRUB_ERR_NONE; } -static grub_err_t +grub_err_t grub_elf64_phdr_iterate (grub_elf_t elf, int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *), void *hook_arg) @@ -358,16 +360,17 @@ grub_elf64_phdr_iterate (grub_elf_t elf, /* Calculate the amount of memory spanned by the segments. */ grub_size_t -grub_elf64_size (grub_elf_t elf, Elf64_Addr *base) +grub_elf64_size (grub_elf_t elf, 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)), + int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), Elf64_Phdr *phdr, void *_arg __attribute__ ((unused))) { @@ -379,6 +382,8 @@ grub_elf64_size (grub_elf_t elf, Elf64_Addr *base) 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; } @@ -402,11 +407,11 @@ grub_elf64_size (grub_elf_t elf, Elf64_Addr *base) 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, grub_elf64_load_hook_t _load_hook, diff --git a/grub-core/kern/emu/cache.S b/grub-core/kern/emu/cache.S new file mode 100644 index 000000000..abd81c910 --- /dev/null +++ b/grub-core/kern/emu/cache.S @@ -0,0 +1,28 @@ +#ifndef GRUB_MACHINE_EMU +#error "This source is only meant for grub-emu platform" +#endif + +#if defined(__i386__) || defined(__x86_64__) +/* Nothing is necessary. */ +#elif defined(__sparc__) +#include "../sparc64/cache.S" +#elif defined(__mips__) +/* On MIPS we must go through standard functions. */ +#include + +FUNCTION (grub_cpu_flush_cache) +FUNCTION (grub_arch_sync_caches) + .set nomacro + .set noreorder + lui $t0, %hi(_flush_cache) + addui $t0, $t0, %lo(_flush_cache) + move $a3, $zero + jr $t0 + nop + .set reorder + .set macro +#elif defined(__powerpc__) +#include "../powerpc/cache.S" +#else +#error "No target cpu type is defined" +#endif diff --git a/kern/emu/console.c b/grub-core/kern/emu/console.c similarity index 85% rename from kern/emu/console.c rename to grub-core/kern/emu/console.c index f6b13b19b..7fd1fc0c9 100644 --- a/kern/emu/console.c +++ b/grub-core/kern/emu/console.c @@ -18,6 +18,7 @@ */ #include +#include /* For compatibility. */ #ifndef A_NORMAL @@ -37,6 +38,8 @@ # include #elif defined(HAVE_CURSES_H) # include +#else +#error What the hell? #endif static int grub_console_attr = A_NORMAL; @@ -102,63 +105,32 @@ grub_ncurses_setcolorstate (struct grub_term_output *term, } } -static int saved_char = ERR; - -static int -grub_ncurses_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - int c; - - /* Check for SAVED_CHAR. This should not be true, because this - means checkkey is called twice continuously. */ - if (saved_char != ERR) - return saved_char; - - wtimeout (stdscr, 100); - c = getch (); - /* If C is not ERR, then put it back in the input queue. */ - if (c != ERR) - { - saved_char = c; - return c; - } - - return -1; -} - static int grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) { int c; - /* If checkkey has already got a character, then return it. */ - if (saved_char != ERR) - { - c = saved_char; - saved_char = ERR; - } - else - { - wtimeout (stdscr, -1); - c = getch (); - } + wtimeout (stdscr, 100); + c = getch (); switch (c) { + case ERR: + return -1; case KEY_LEFT: - c = GRUB_TERM_LEFT; + c = GRUB_TERM_KEY_LEFT; break; case KEY_RIGHT: - c = GRUB_TERM_RIGHT; + c = GRUB_TERM_KEY_RIGHT; break; case KEY_UP: - c = GRUB_TERM_UP; + c = GRUB_TERM_KEY_UP; break; case KEY_DOWN: - c = GRUB_TERM_DOWN; + c = GRUB_TERM_KEY_DOWN; break; case KEY_IC: @@ -166,30 +138,30 @@ grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) break; case KEY_DC: - c = GRUB_TERM_DC; + c = GRUB_TERM_KEY_DC; break; case KEY_BACKSPACE: /* XXX: For some reason ncurses on xterm does not return KEY_BACKSPACE. */ case 127: - c = GRUB_TERM_BACKSPACE; + c = '\b'; break; case KEY_HOME: - c = GRUB_TERM_HOME; + c = GRUB_TERM_KEY_HOME; break; case KEY_END: - c = GRUB_TERM_END; + c = GRUB_TERM_KEY_END; break; case KEY_NPAGE: - c = GRUB_TERM_NPAGE; + c = GRUB_TERM_KEY_NPAGE; break; case KEY_PPAGE: - c = GRUB_TERM_PPAGE; + c = GRUB_TERM_KEY_PPAGE; break; } @@ -288,7 +260,6 @@ grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused))) static struct grub_term_input grub_ncurses_term_input = { .name = "console", - .checkkey = grub_ncurses_checkkey, .getkey = grub_ncurses_getkey, }; diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c new file mode 100644 index 000000000..70bcae78f --- /dev/null +++ b/grub-core/kern/emu/full.c @@ -0,0 +1,71 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +void +grub_register_exported_symbols (void) +{ +} + +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + (void) ehdr; + return GRUB_ERR_BAD_MODULE; +} + +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + (void) mod; + (void) ehdr; + return GRUB_ERR_BAD_MODULE; +} + +void +grub_emu_init (void) +{ + grub_no_autoload = 1; +} + +#ifdef GRUB_LINKER_HAVE_INIT +void +grub_arch_dl_init_linker (void) +{ +} +#endif + +void +grub_emu_post_init (void) +{ + grub_lvm_fini (); + grub_mdraid09_fini (); + grub_mdraid1x_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid09_init (); + grub_mdraid1x_init (); + grub_lvm_init (); +} diff --git a/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c similarity index 91% rename from kern/emu/getroot.c rename to grub-core/kern/emu/getroot.c index ee6e1c7ba..f51dcd770 100644 --- a/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -181,39 +181,48 @@ find_root_device_from_libzfs (const char *dir) char *device; char *poolname; char *poolfs; - char *mnt_point; - mnt_point = grub_find_mount_point_from_dir (dir); - grub_find_zpool_from_mount_point (mnt_point, &poolname, &poolfs); + grub_find_zpool_from_dir (dir, &poolname, &poolfs); if (! poolname) - { - free (mnt_point); - return NULL; - } + return NULL; { zpool_handle_t *zpool; - nvlist_t *nvlist; - nvlist_t **nvlist_array; + libzfs_handle_t *libzfs; + nvlist_t *config, *vdev_tree; + nvlist_t **children, **path; unsigned int nvlist_count; + unsigned int i; - zpool = zpool_open (grub_get_libzfs_handle (), poolname); - nvlist = zpool_get_config (zpool, NULL); + libzfs = grub_get_libzfs_handle (); + if (! libzfs) + return NULL; - if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0) + zpool = zpool_open (libzfs, poolname); + config = zpool_get_config (zpool, NULL); + + if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0) error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")"); - if (nvlist_lookup_nvlist_array (nvlist, "children", &nvlist_array, &nvlist_count) != 0) + if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0) error (1, errno, "nvlist_lookup_nvlist_array (\"children\")"); + assert (nvlist_count > 0); - do + while (nvlist_lookup_nvlist_array (children[0], "children", + &children, &nvlist_count) == 0) + assert (nvlist_count > 0); + + for (i = 0; i < nvlist_count; i++) { - assert (nvlist_count > 0); - } while (nvlist_lookup_nvlist_array (nvlist_array[0], "children", - &nvlist_array, &nvlist_count) == 0); + if (nvlist_lookup_string (children[i], "path", &device) != 0) + error (1, errno, "nvlist_lookup_string (\"path\")"); - if (nvlist_lookup_string (nvlist_array[0], "path", &device) != 0) - error (1, errno, "nvlist_lookup_string (\"path\")"); + struct stat st; + if (stat (device, &st) == 0) + break; + + device = NULL; + } zpool_close (zpool); } @@ -228,8 +237,8 @@ find_root_device_from_libzfs (const char *dir) #ifdef __MINGW32__ -static char * -find_root_device (const char *dir __attribute__ ((unused)), +char * +grub_find_device (const char *dir __attribute__ ((unused)), dev_t dev __attribute__ ((unused))) { return 0; @@ -237,13 +246,22 @@ find_root_device (const char *dir __attribute__ ((unused)), #elif ! defined(__CYGWIN__) -static char * -find_root_device (const char *dir, dev_t dev) +char * +grub_find_device (const char *dir, dev_t dev) { DIR *dp; char *saved_cwd; struct dirent *ent; + if (! dir) + { +#ifdef __CYGWIN__ + return NULL; +#else + dir = "/dev"; +#endif + } + dp = opendir (dir); if (! dp) return 0; @@ -292,7 +310,7 @@ find_root_device (const char *dir, dev_t dev) /* Find it recursively. */ char *res; - res = find_root_device (ent->d_name, dev); + res = grub_find_device (ent->d_name, dev); if (res) { @@ -402,8 +420,8 @@ get_bootsec_serial (const char *os_dev, int mbr) return serial; } -static char * -find_cygwin_root_device (const char *path, dev_t dev) +char * +grub_find_device (const char *path, dev_t dev) { /* No root device for /cygdrive. */ if (dev == (DEV_CYGDRIVE_MAJOR << 16)) @@ -424,7 +442,7 @@ find_cygwin_root_device (const char *path, dev_t dev) /* Cygwin returns the partition serial number in stat.st_dev. This is never identical to the device number of the emulated - /dev/sdXN device, so above find_root_device () does not work. + /dev/sdXN device, so above grub_find_device () does not work. Search the partition with the same serial in boot sector instead. */ char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */ int d; @@ -529,12 +547,12 @@ grub_guess_root_device (const char *dir) #ifdef __CYGWIN__ /* Cygwin specific function. */ - os_dev = find_cygwin_root_device (dir, st.st_dev); + os_dev = grub_find_device (dir, st.st_dev); #else /* This might be truly slow, but is there any better way? */ - os_dev = find_root_device ("/dev", st.st_dev); + os_dev = grub_find_device ("/dev", st.st_dev); #endif #endif /* !__GNU__ */ @@ -564,6 +582,8 @@ grub_util_is_dmraid (const char *os_dev) return 1; else if (! strncmp (os_dev, "/dev/mapper/sil_", 16)) return 1; + else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17)) + return 1; return 0; } @@ -572,6 +592,10 @@ int grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) { #ifdef __linux__ + /* User explicitly claims that this drive is visible by BIOS. */ + if (grub_util_biosdisk_is_present (os_dev)) + return GRUB_DEV_ABSTRACTION_NONE; + /* Check for LVM. */ if (!strncmp (os_dev, "/dev/mapper/", 12) && ! grub_util_is_dmraid (os_dev) diff --git a/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c similarity index 86% rename from kern/emu/hostdisk.c rename to grub-core/kern/emu/hostdisk.c index 2cdf449e2..12dbe7469 100644 --- a/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1,7 +1,7 @@ /* hostdisk.c - emulate biosdisk */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,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 @@ -102,13 +102,22 @@ struct hd_geometry # include #endif -#if defined(__NetBSD__) +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# define HAVE_DIOCGDINFO # include # include /* struct disklabel */ +#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 FLOPPY_MAJOR +# define FLOPPY_MAJOR 2 +# endif /* ! FLOPPY_MAJOR */ # ifndef RAW_FLOPPY_MAJOR # define RAW_FLOPPY_MAJOR 9 # endif /* ! RAW_FLOPPY_MAJOR */ @@ -221,7 +230,6 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no mapping exists for `%s'", name); - disk->has_partitions = 1; disk->id = drive; disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); data->dev = NULL; @@ -329,17 +337,17 @@ device_is_mapped (const char *dev) } #endif /* HAVE_DEVICE_MAPPER */ -#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) static grub_disk_addr_t find_partition_start (const char *dev) { int fd; -# if !defined(__NetBSD__) +# if !defined(HAVE_DIOCGDINFO) struct hd_geometry hdg; -# else /* defined(__NetBSD__) */ +# else /* defined(HAVE_DIOCGDINFO) */ struct disklabel label; int p_index; -# endif /* !defined(__NetBSD__) */ +# endif /* !defined(HAVE_DIOCGDINFO) */ # ifdef HAVE_DEVICE_MAPPER if (grub_device_mapper_supported () && device_is_mapped (dev)) { @@ -413,36 +421,38 @@ devmapper_fail: if (fd == -1) { grub_error (GRUB_ERR_BAD_DEVICE, -# if !defined(__NetBSD__) +# if !defined(HAVE_DIOCGDINFO) "cannot open `%s' while attempting to get disk geometry", dev); -# else /* defined(__NetBSD__) */ +# else /* defined(HAVE_DIOCGDINFO) */ "cannot open `%s' while attempting to get disk label", dev); -# endif /* !defined(__NetBSD__) */ +# endif /* !defined(HAVE_DIOCGDINFO) */ return 0; } -# if !defined(__NetBSD__) +# if !defined(HAVE_DIOCGDINFO) if (ioctl (fd, HDIO_GETGEO, &hdg)) -# else /* defined(__NetBSD__) */ +# else /* defined(HAVE_DIOCGDINFO) */ +# if defined(__NetBSD__) configure_device_driver (fd); +# endif /* defined(__NetBSD__) */ if (ioctl (fd, DIOCGDINFO, &label) == -1) -# endif /* !defined(__NetBSD__) */ +# endif /* !defined(HAVE_DIOCGDINFO) */ { grub_error (GRUB_ERR_BAD_DEVICE, -# if !defined(__NetBSD__) +# if !defined(HAVE_DIOCGDINFO) "cannot get disk geometry of `%s'", dev); -# else /* defined(__NetBSD__) */ +# else /* defined(HAVE_DIOCGDINFO) */ "cannot get disk label of `%s'", dev); -# endif /* !defined(__NetBSD__) */ +# endif /* !defined(HAVE_DIOCGDINFO) */ close (fd); return 0; } close (fd); -# if !defined(__NetBSD__) +# if !defined(HAVE_DIOCGDINFO) return hdg.start; -# else /* defined(__NetBSD__) */ +# else /* defined(HAVE_DIOCGDINFO) */ p_index = dev[strlen(dev) - 1] - 'a'; if (p_index >= label.d_npartitions) @@ -452,9 +462,9 @@ devmapper_fail: return 0; } return (grub_disk_addr_t) label.d_partitions[p_index].p_offset; -# endif /* !defined(__NetBSD__) */ +# endif /* !defined(HAVE_DIOCGDINFO) */ } -#endif /* __linux__ || __CYGWIN__ */ +#endif /* __linux__ || __CYGWIN__ || HAVE_DIOCGDINFO */ #ifdef __linux__ /* Cache of partition start sectors for each disk. */ @@ -956,13 +966,16 @@ read_device_map (const char *dev_map) #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 = xmalloc (PATH_MAX); - if (! realpath (p, map[drive].device)) - grub_util_error ("cannot get the real path of `%s'", p); -#else - 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 ("cannot get the real path of `%s'", p); + } + else #endif + map[drive].device = xstrdup (p); } fclose (fp); @@ -994,8 +1007,7 @@ grub_util_biosdisk_fini (void) /* * Note: we do not use the new partition naming scheme as dos_part does not - * necessarily correspond to an msdos partition. See e.g. the FreeBSD code - * in function grub_util_biosdisk_get_grub_dev. + * necessarily correspond to an msdos partition. */ static char * make_device_name (int drive, int dos_part, int bsd_part) @@ -1117,6 +1129,16 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) return path; } + if (strncmp ("md", p, 2) == 0 + && p[2] >= '0' && p[2] <= '9') + { + char *ptr = p + 2; + while (*ptr >= '0' && *ptr <= '9') + ptr++; + *ptr = 0; + return path; + } + /* If this is an IDE, SCSI or Virtio disk. */ if (strncmp ("vdisk", p, 5) == 0 && p[5] >= 'a' && p[5] <= 'z') @@ -1130,36 +1152,42 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) || strncmp ("sd", p, 2) == 0) && p[2] >= 'a' && p[2] <= 'z') { - /* /dev/[hsv]d[a-z][0-9]* */ - p[3] = '\0'; + char *pp = p + 2; + while (*pp >= 'a' && *pp <= 'z') + pp++; + /* /dev/[hsv]d[a-z]+[0-9]* */ + *pp = '\0'; return path; } /* If this is a Xen virtual block device. */ if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z') { - /* /dev/xvd[a-z][0-9]* */ - p[4] = '\0'; + char *pp = p + 3; + while (*pp >= 'a' && *pp <= 'z') + pp++; + /* /dev/xvd[a-z]+[0-9]* */ + *pp = '\0'; return path; } #ifdef HAVE_DEVICE_MAPPER - /* If this is a DM-RAID device. */ - if ((strncmp ("mapper/", p, 7) == 0)) + /* If this is a DM-RAID device. + Compare os_dev rather than path here, since nodes under + /dev/mapper/ are often symlinks. */ + if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) { - static struct dm_tree *tree = NULL; + struct dm_tree *tree; uint32_t maj, min; - struct dm_tree_node *node, *child; + struct dm_tree_node *node = NULL, *child; void *handle; - const char *node_uuid, *mapper_name, *child_uuid, *child_name; - - if (! tree) - tree = dm_tree_create (); + const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; + tree = dm_tree_create (); if (! tree) { grub_dprintf ("hostdisk", "dm_tree_create failed\n"); - return NULL; + goto devmapper_out; } maj = major (st->st_rdev); @@ -1167,29 +1195,30 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) if (! dm_tree_add_dev (tree, maj, min)) { grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); - return NULL; + goto devmapper_out; } node = dm_tree_find_node (tree, maj, min); if (! node) { grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); - return NULL; + goto devmapper_out; } node_uuid = dm_tree_node_get_uuid (node); if (! node_uuid) { grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); - return NULL; + node = NULL; + goto devmapper_out; } else if (strncmp (node_uuid, "DMRAID-", 7) != 0) { grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); - return NULL; + node = NULL; + goto devmapper_out; } handle = NULL; - mapper_name = NULL; /* Counter-intuitively, device-mapper refers to the disk-like device containing a DM-RAID partition device as a "child" of the partition device. */ @@ -1219,17 +1248,20 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) mapper_name = child_name; devmapper_out: - if (! mapper_name) + if (! mapper_name && node) { /* This is a DM-RAID disk, not a partition. */ mapper_name = dm_tree_node_get_name (node); if (! mapper_name) - { - grub_dprintf ("hostdisk", "%s has no DM name\n", path); - return NULL; - } + grub_dprintf ("hostdisk", "%s has no DM name\n", path); } - return xasprintf ("/dev/mapper/%s", mapper_name); + if (tree) + dm_tree_free (tree); + free (path); + if (mapper_name) + return xasprintf ("/dev/mapper/%s", mapper_name); + else + return NULL; } #endif /* HAVE_DEVICE_MAPPER */ } @@ -1333,13 +1365,37 @@ device_is_wholedisk (const char *os_dev) } #endif /* defined(__NetBSD__) */ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) static int -find_system_device (const char *os_dev, struct stat *st) +device_is_wholedisk (const char *os_dev) +{ + const char *p; + + if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) + return 0; + + for (p = os_dev + sizeof ("/dev/") - 1; *p; ++p) + if (grub_isdigit (*p)) + { + if (strchr (p, 's')) + return 0; + break; + } + + return 1; +} +#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */ + +static int +find_system_device (const char *os_dev, struct stat *st, int convert, int add) { unsigned int i; char *os_disk; - os_disk = convert_system_partition_to_system_disk (os_dev, st); + if (convert) + os_disk = convert_system_partition_to_system_disk (os_dev, st); + else + os_disk = xstrdup (os_dev); if (! os_disk) return -1; @@ -1352,6 +1408,9 @@ find_system_device (const char *os_dev, struct stat *st) return i; } + if (!add) + return -1; + if (i == ARRAY_SIZE (map)) grub_util_error (_("device count exceeds limit")); @@ -1361,6 +1420,17 @@ find_system_device (const char *os_dev, struct stat *st) return i; } +int +grub_util_biosdisk_is_present (const char *os_dev) +{ + struct stat st; + + if (stat (os_dev, &st) < 0) + return 0; + + return find_system_device (os_dev, &st, 1, 0) != -1; +} + char * grub_util_biosdisk_get_grub_dev (const char *os_dev) { @@ -1373,7 +1443,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return 0; } - drive = find_system_device (os_dev, &st); + drive = find_system_device (os_dev, &st, 1, 1); if (drive < 0) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, @@ -1392,7 +1462,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) #endif return make_device_name (drive, -1, -1); -#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) /* Linux counts partitions uniformly, whether a BSD partition or a DOS partition, so mapping them to GRUB devices is not trivial. Here, get the start sector of a partition by HDIO_GETGEO, and @@ -1402,8 +1472,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) does not count the extended partition and missing primary partitions. Use same method as on Linux here. - For NetBSD, proceed as for Linux, except that the start sector is - obtained from the disk label. */ + For NetBSD and FreeBSD, proceed as for Linux, except that the start + sector is obtained from the disk label. */ { char *name, *partname; grub_disk_t disk; @@ -1431,13 +1501,13 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) name = make_device_name (drive, -1, -1); -# if !defined(__NetBSD__) +# if !defined(HAVE_DIOCGDINFO) if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) return name; -# else /* defined(__NetBSD__) */ +# else /* defined(HAVE_DIOCGDINFO) */ /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are * different, we know that os_dev cannot be a floppy device. */ -# endif /* !defined(__NetBSD__) */ +# endif /* !defined(HAVE_DIOCGDINFO) */ start = find_partition_start (os_dev); if (grub_errno != GRUB_ERR_NONE) @@ -1456,7 +1526,32 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) free (name); if (! disk) - return 0; + { + /* We already know that the partition exists. Given that we already + checked the device map above, we can only get + GRUB_ERR_UNKNOWN_DEVICE at this point if the disk does not exist. + This can happen on Xen, where disk images in the host can be + assigned to devices that have partition-like names in the guest + but are really more like disks. */ + if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + { + grub_util_warn + ("disk does not exist, so falling back to partition device %s", + os_dev); + + drive = find_system_device (os_dev, &st, 0, 1); + if (drive < 0) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "no mapping exists for `%s'", os_dev); + return 0; + } + + return make_device_name (drive, -1, -1); + } + else + return 0; + } partname = NULL; grub_partition_iterate (disk, find_partition); @@ -1506,41 +1601,6 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return make_device_name (drive, dos_part, bsd_part); } -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) - /* FreeBSD uses "/dev/[a-z]+[0-9]+([sp][0-9]+[a-z]?)?". */ - { - int dos_part = -1; - int bsd_part = -1; - - if (strncmp ("/dev/", os_dev, 5) == 0) - { - const char *p; - char *q; - long int n; - - for (p = os_dev + 5; *p; ++p) - if (grub_isdigit(*p)) - { - p = strpbrk (p, "sp"); /* msdos or apple (or ... ?) partition map */ - if (p) - { - p++; - n = strtol (p, &q, 10); - if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX) - { - dos_part = (int) n - 1; - - if (*q >= 'a' && *q <= 'g') - bsd_part = *q - 'a'; - } - } - break; - } - } - - return make_device_name (drive, dos_part, bsd_part); - } - #else # warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly." return make_device_name (drive, -1, -1); @@ -1552,3 +1612,38 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk) { return map[disk->id].device; } + +int +grub_util_biosdisk_is_floppy (grub_disk_t disk) +{ + struct stat st; + int fd; + + fd = open (map[disk->id].device, O_RDONLY); + /* Shouldn't happen. */ + if (fd == -1) + return 0; + + /* Shouldn't happen either. */ + if (fstat (fd, &st) < 0) + return 0; + +#if defined(__NetBSD__) + if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) + return 1; +#endif + +#if defined(FLOPPY_MAJOR) + if (major(st.st_rdev) == FLOPPY_MAJOR) +#else + /* Some kernels (e.g. kFreeBSD) don't have a static major number + for floppies, but they still use a "fd[0-9]" pathname. */ + if (map[disk->id].device[5] == 'f' + && map[disk->id].device[6] == 'd' + && map[disk->id].device[7] >= '0' + && map[disk->id].device[7] <= '9') +#endif + return 1; + + return 0; +} diff --git a/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c similarity index 100% rename from kern/emu/hostfs.c rename to grub-core/kern/emu/hostfs.c diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c new file mode 100644 index 000000000..32e12a079 --- /dev/null +++ b/grub-core/kern/emu/lite.c @@ -0,0 +1,45 @@ +#include +#include + +#ifndef GRUB_MACHINE_EMU +#error "This source is only meant for grub-emu platform" +#endif + +#if defined(__i386__) +#include "../i386/dl.c" +#elif defined(__x86_64__) +#include "../x86_64/dl.c" +#elif defined(__sparc__) +#include "../sparc64/dl.c" +#elif defined(__mips__) +#include "../mips/dl.c" +#elif defined(__powerpc__) +#include "../powerpc/dl.c" +#else +#error "No target cpu type is defined" +#endif + +/* grub-emu-lite supports dynamic module loading, so it won't have any + embedded modules. */ +void +grub_init_all (void) +{ + return; +} + +void +grub_fini_all (void) +{ + return; +} + +void +grub_emu_init (void) +{ + return; +} + +void +grub_emu_post_init (void) +{ +} diff --git a/kern/emu/main.c b/grub-core/kern/emu/main.c similarity index 90% rename from kern/emu/main.c rename to grub-core/kern/emu/main.c index fb5dbf19f..0a7645992 100644 --- a/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -42,56 +41,30 @@ #include #include -#define ENABLE_RELOCATABLE 0 #include "progname.h" +#define ENABLE_RELOCATABLE 0 + /* Used for going back to the main function. */ static jmp_buf main_env; /* Store the prefix specified by an argument. */ static char *prefix = NULL; +int grub_no_autoload; + grub_addr_t grub_arch_modules_addr (void) { return 0; } -#if GRUB_NO_MODULES -grub_err_t -grub_arch_dl_check_header (void *ehdr) -{ - (void) ehdr; - - return GRUB_ERR_BAD_MODULE; -} - -grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) -{ - (void) mod; - (void) ehdr; - - return GRUB_ERR_BAD_MODULE; -} -#endif - void grub_reboot (void) { longjmp (main_env, 1); } -void -grub_halt ( -#ifdef GRUB_MACHINE_PCBIOS - int no_apm __attribute__ ((unused)) -#endif - ) -{ - grub_reboot (); -} - void grub_machine_init (void) { @@ -154,10 +127,7 @@ void grub_hostfs_init (void); void grub_hostfs_fini (void); void grub_host_init (void); void grub_host_fini (void); -#if GRUB_NO_MODULES -void grub_init_all (void); -void grub_fini_all (void); -#endif +void grub_emu_init (void); int main (int argc, char *argv[]) @@ -216,16 +186,18 @@ main (int argc, char *argv[]) } signal (SIGINT, SIG_IGN); + grub_emu_init (); grub_console_init (); grub_host_init (); - grub_hostfs_init (); /* XXX: This is a bit unportable. */ grub_util_biosdisk_init (dev_map); -#if GRUB_NO_MODULES grub_init_all (); -#endif + + grub_hostfs_init (); + + grub_emu_post_init (); /* Make sure that there is a root device. */ if (! root_dev) @@ -255,9 +227,7 @@ main (int argc, char *argv[]) if (setjmp (main_env) == 0) grub_main (); -#if GRUB_NO_MODULES grub_fini_all (); -#endif grub_hostfs_fini (); grub_host_fini (); @@ -287,10 +257,3 @@ grub_millisleep (grub_uint32_t ms) } #endif - -#if GRUB_NO_MODULES -void -grub_register_exported_symbols (void) -{ -} -#endif diff --git a/kern/emu/misc.c b/grub-core/kern/emu/misc.c similarity index 77% rename from kern/emu/misc.c rename to grub-core/kern/emu/misc.c index 5a148c708..c8b95443b 100644 --- a/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -16,6 +16,7 @@ * along with GRUB. If not, see . */ +#include #include #include @@ -32,10 +33,6 @@ #include #endif -#ifdef HAVE_GETMNTANY -# include -#endif - #include #include #include @@ -57,10 +54,23 @@ # include #endif -#ifdef HAVE_GETFSSTAT +#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 @@ -151,7 +161,7 @@ vasprintf (char **buf, const char *fmt, va_list ap) /* Should be large enough. */ *buf = xmalloc (512); - return vsprintf (*buf, fmt, ap); + return vsnprintf (*buf, 512, fmt, ap); } #endif @@ -165,7 +175,7 @@ asprintf (char **buf, const char *fmt, ...) va_list ap; va_start (ap, fmt); - status = vasprintf (*buf, fmt, ap); + status = vasprintf (buf, fmt, ap); va_end (ap); return status; @@ -268,7 +278,9 @@ grub_get_libzfs_handle (void) if (! __libzfs_handle) { __libzfs_handle = libzfs_init (); - atexit (fini_libzfs); + + if (__libzfs_handle) + atexit (fini_libzfs); } return __libzfs_handle; @@ -276,112 +288,49 @@ grub_get_libzfs_handle (void) #endif /* HAVE_LIBZFS */ #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) -/* Not ZFS-specific in itself, but for now it's only used by ZFS-related code. */ -char * -grub_find_mount_point_from_dir (const char *dir) -{ - struct stat st; - typeof (st.st_dev) fs; - char *prev, *next, *slash, *statdir; - - if (stat (dir, &st) == -1) - error (1, errno, "stat (%s)", dir); - - fs = st.st_dev; - - prev = xstrdup (dir); - - while (1) - { - /* Remove last slash. */ - next = xstrdup (prev); - slash = strrchr (next, '/'); - if (! slash) - { - free (next); - free (prev); - return NULL; - } - *slash = '\0'; - - /* A next empty string counts as /. */ - if (next[0] == '\0') - statdir = "/"; - else - statdir = next; - - if (stat (statdir, &st) == -1) - error (1, errno, "stat (%s)", next); - - if (st.st_dev != fs) - { - /* Found mount point. */ - free (next); - return prev; - } - - free (prev); - prev = next; - - /* We've already seen an empty string, which means we - reached /. Nothing left to do. */ - if (prev[0] == '\0') - { - free (prev); - return xstrdup ("/"); - } - } -} -#endif - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - /* ZFS has similar problems to those of btrfs (see above). */ void -grub_find_zpool_from_mount_point (const char *mnt_point, char **poolname, char **poolfs) +grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) { char *slash; *poolname = *poolfs = NULL; -#if defined(HAVE_GETFSSTAT) /* FreeBSD and GNU/kFreeBSD */ +#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME) + /* FreeBSD and GNU/kFreeBSD. */ { - int mnt_count = getfsstat (NULL, 0, MNT_WAIT); - if (mnt_count == -1) - error (1, errno, "getfsstat"); + struct statfs mnt; - struct statfs *mnt = xmalloc (mnt_count * sizeof (*mnt)); + if (statfs (dir, &mnt) != 0) + return; - mnt_count = getfsstat (mnt, mnt_count * sizeof (*mnt), MNT_WAIT); - if (mnt_count == -1) - error (1, errno, "getfsstat"); + if (strcmp (mnt.f_fstypename, "zfs") != 0) + return; - unsigned int i; - for (i = 0; i < (unsigned) mnt_count; i++) - if (!strcmp (mnt[i].f_fstypename, "zfs") - && !strcmp (mnt[i].f_mntonname, mnt_point)) - { - *poolname = xstrdup (mnt[i].f_mntfromname); - break; - } - - free (mnt); + *poolname = xstrdup (mnt.f_mntfromname); } -#elif defined(HAVE_GETMNTANY) /* OpenSolaris */ +#elif defined(HAVE_GETEXTMNTENT) + /* Solaris. */ { - FILE *mnttab = fopen ("/etc/mnttab", "r"); - struct mnttab mp; - struct mnttab mpref = - { - .mnt_special = NULL, - .mnt_mountp = mnt_point, - .mnt_fstype = "zfs", - .mnt_mntopts = NULL, - .mnt_time = NULL, - }; + struct stat st; + struct extmnttab mnt; - if (getmntany (mnttab, &mp, &mpref) == 0) - *poolname = xstrdup (mp.mnt_special); + if (stat (dir, &st) != 0) + return; + + FILE *mnttab = fopen ("/etc/mnttab", "r"); + if (! mnttab) + return; + + while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0) + { + if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev + && !strcmp (mnt.mnt_fstype, "zfs")) + { + *poolname = xstrdup (mnt.mnt_special); + break; + } + } fclose (mnttab); } @@ -407,12 +356,15 @@ char * grub_make_system_path_relative_to_its_root (const char *path) { struct stat st; - char *p, *buf, *buf2, *buf3; - char *mnt_point, *poolname = NULL, *poolfs = NULL, *ret; + char *p, *buf, *buf2, *buf3, *ret; uintptr_t offset = 0; dev_t num; size_t len; +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + char *poolfs = NULL; +#endif + /* canonicalize. */ p = canonicalize_file_name (path); if (p == NULL) @@ -420,12 +372,10 @@ grub_make_system_path_relative_to_its_root (const char *path) #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ - mnt_point = grub_find_mount_point_from_dir (p); - if (mnt_point) - { - grub_find_zpool_from_mount_point (mnt_point, &poolname, &poolfs); - free (mnt_point); - } + { + char *dummy; + grub_find_zpool_from_dir (p, &dummy, &poolfs); + } #endif len = strlen (p) + 1; @@ -466,6 +416,10 @@ grub_make_system_path_relative_to_its_root (const char *path) { free (buf); free (buf2); +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + if (poolfs) + return xasprintf ("/%s/@", poolfs); +#endif return xstrdup (""); } else @@ -506,12 +460,14 @@ grub_make_system_path_relative_to_its_root (const char *path) len--; } +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (poolfs) { - ret = xasprintf ("/%s@%s", poolfs, buf3); + ret = xasprintf ("/%s/@%s", poolfs, buf3); free (buf3); } else +#endif ret = buf3; return ret; diff --git a/kern/emu/mm.c b/grub-core/kern/emu/mm.c similarity index 98% rename from kern/emu/mm.c rename to grub-core/kern/emu/mm.c index 0e9e9f3a8..6a70efb4c 100644 --- a/kern/emu/mm.c +++ b/grub-core/kern/emu/mm.c @@ -16,6 +16,8 @@ * along with GRUB. If not, see . */ +#include + #include #include #include diff --git a/kern/emu/time.c b/grub-core/kern/emu/time.c similarity index 100% rename from kern/emu/time.c rename to grub-core/kern/emu/time.c diff --git a/kern/env.c b/grub-core/kern/env.c similarity index 100% rename from kern/env.c rename to grub-core/kern/env.c diff --git a/kern/err.c b/grub-core/kern/err.c similarity index 96% rename from kern/err.c rename to grub-core/kern/err.c index 8272467f5..74f3915aa 100644 --- a/kern/err.c +++ b/grub-core/kern/err.c @@ -27,6 +27,7 @@ grub_err_t grub_errno; char grub_errmsg[GRUB_MAX_ERRMSG]; +int grub_err_printed_errors; static struct { @@ -122,7 +123,10 @@ grub_print_error (void) do { if (grub_errno != GRUB_ERR_NONE) - grub_err_printf (_("error: %s.\n"), grub_errmsg); + { + grub_err_printf (_("error: %s.\n"), grub_errmsg); + grub_err_printed_errors++; + } } while (grub_error_pop ()); diff --git a/kern/file.c b/grub-core/kern/file.c similarity index 82% rename from kern/file.c rename to grub-core/kern/file.c index e17c35f95..c93fbf737 100644 --- a/kern/file.c +++ b/grub-core/kern/file.c @@ -24,6 +24,9 @@ #include #include +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 * grub_file_get_device_name (const char *name) @@ -54,14 +57,15 @@ grub_file_get_device_name (const char *name) grub_file_t grub_file_open (const char *name) { - grub_device_t device; - grub_file_t file = 0; + grub_device_t device = 0; + grub_file_t file = 0, last_file = 0; char *device_name; char *file_name; + grub_file_filter_id_t filter; device_name = grub_file_get_device_name (name); if (grub_errno) - return 0; + goto fail; /* Get the file part of NAME. */ file_name = grub_strchr (name, ')'); @@ -94,6 +98,19 @@ grub_file_open (const char *name) if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE) goto fail; + for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters_enabled); + filter++) + if (grub_file_filters_enabled[filter]) + { + last_file = file; + 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; fail: @@ -104,6 +121,9 @@ grub_file_open (const char *name) grub_free (file); + grub_memcpy (grub_file_filters_enabled, grub_file_filters_all, + sizeof (grub_file_filters_enabled)); + return 0; } diff --git a/kern/fs.c b/grub-core/kern/fs.c similarity index 100% rename from kern/fs.c rename to grub-core/kern/fs.c diff --git a/kern/generic/millisleep.c b/grub-core/kern/generic/millisleep.c similarity index 100% rename from kern/generic/millisleep.c rename to grub-core/kern/generic/millisleep.c diff --git a/kern/generic/rtc_get_time_ms.c b/grub-core/kern/generic/rtc_get_time_ms.c similarity index 100% rename from kern/generic/rtc_get_time_ms.c rename to grub-core/kern/generic/rtc_get_time_ms.c diff --git a/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c similarity index 76% rename from kern/i386/coreboot/init.c rename to grub-core/kern/i386/coreboot/init.c index 0afbfd3af..434b9b5a8 100644 --- a/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -19,9 +19,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -32,33 +32,21 @@ #include #include #include +#include #include #ifdef GRUB_MACHINE_QEMU #include #endif -#define GRUB_FLOPPY_REG_DIGITAL_OUTPUT 0x3f2 - extern char _start[]; extern char _end[]; -grub_addr_t grub_os_area_addr; -grub_size_t grub_os_area_size; - grub_uint32_t grub_get_rtc (void) { grub_fatal ("grub_get_rtc() is not implemented.\n"); } -/* Stop the floppy drive from spinning, so that other software is - jumped to with a known state. */ -void -grub_stop_floppy (void) -{ - grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT); -} - void grub_exit (void) { @@ -77,8 +65,10 @@ grub_machine_init (void) /* 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_uint32_t); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + 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. */ @@ -88,7 +78,7 @@ grub_machine_init (void) size = GRUB_ULONG_MAX - addr; #endif - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; /* Avoid the lower memory. */ @@ -103,20 +93,7 @@ grub_machine_init (void) } } - if (addr == GRUB_MEMORY_MACHINE_UPPER_START - || (addr >= GRUB_MEMORY_MACHINE_LOWER_SIZE - && addr <= GRUB_MEMORY_MACHINE_UPPER_START - && (addr + size > GRUB_MEMORY_MACHINE_UPPER_START))) - { - grub_size_t quarter = size >> 2; - - grub_os_area_addr = addr; - grub_os_area_size = size - quarter; - grub_mm_init_region ((void *) (grub_os_area_addr + grub_os_area_size), - quarter); - } - else - grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size); + grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size); return 0; } diff --git a/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c similarity index 96% rename from kern/i386/coreboot/mmap.c rename to grub-core/kern/i386/coreboot/mmap.c index d06627a08..8b0b20265 100644 --- a/kern/i386/coreboot/mmap.c +++ b/grub-core/kern/i386/coreboot/mmap.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -74,7 +75,7 @@ signature_found: } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { mem_region_t mem_region; diff --git a/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S similarity index 94% rename from kern/i386/coreboot/startup.S rename to grub-core/kern/i386/coreboot/startup.S index bcc0d14ab..cac023ddf 100644 --- a/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 @@ -51,7 +53,7 @@ VARIABLE(grub_prefix) * Leave some breathing room for the prefix. */ - . = _start + GRUB_KERNEL_MACHINE_DATA_END + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END /* * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). @@ -85,7 +87,3 @@ codestart: */ #include "../realmode.S" -/* - * Routines needed by Linux and Multiboot loaders. - */ -#include "../loader.S" diff --git a/kern/i386/dl.c b/grub-core/kern/i386/dl.c similarity index 100% rename from kern/i386/dl.c rename to grub-core/kern/i386/dl.c diff --git a/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c similarity index 100% rename from kern/i386/efi/init.c rename to grub-core/kern/i386/efi/init.c diff --git a/kern/i386/efi/startup.S b/grub-core/kern/i386/efi/startup.S similarity index 100% rename from kern/i386/efi/startup.S rename to grub-core/kern/i386/efi/startup.S diff --git a/kern/i386/ieee1275/startup.S b/grub-core/kern/i386/ieee1275/startup.S similarity index 91% rename from kern/i386/ieee1275/startup.S rename to grub-core/kern/i386/ieee1275/startup.S index c0a08a954..82087323b 100644 --- a/kern/i386/ieee1275/startup.S +++ b/grub-core/kern/i386/ieee1275/startup.S @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include #include @@ -51,7 +51,7 @@ VARIABLE(grub_prefix) * Leave some breathing room for the prefix. */ - . = _start + GRUB_KERNEL_MACHINE_DATA_END + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END codestart: movl %eax, EXT_C(grub_ieee1275_entry_fn) @@ -63,7 +63,3 @@ codestart: */ #include "../realmode.S" -/* - * Routines needed by Linux and Multiboot loaders. - */ -#include "../loader.S" diff --git a/kern/i386/multiboot_mmap.c b/grub-core/kern/i386/multiboot_mmap.c similarity index 84% rename from kern/i386/multiboot_mmap.c rename to grub-core/kern/i386/multiboot_mmap.c index 0f463c23c..7f4bc3b5c 100644 --- a/kern/i386/multiboot_mmap.c +++ b/grub-core/kern/i386/multiboot_mmap.c @@ -16,15 +16,12 @@ * along with GRUB. If not, see . */ -#include #include #include #include #include #include -grub_size_t grub_lower_mem, grub_upper_mem; - /* A pointer to the MBI in its initial location. */ struct multiboot_info *startup_multiboot_info; @@ -57,21 +54,10 @@ grub_machine_mmap_init () } grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length); kern_multiboot_info.mmap_addr = (grub_uint32_t) mmap_entries; - - if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEMORY) == 0) - { - grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE; - grub_upper_mem = 0; - } - else - { - grub_lower_mem = kern_multiboot_info.mem_lower * 1024; - grub_upper_mem = kern_multiboot_info.mem_upper * 1024; - } } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr; diff --git a/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c similarity index 85% rename from kern/i386/pc/init.c rename to grub-core/kern/i386/pc/init.c index 8cbc757b2..122c2c556 100644 --- a/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -19,10 +19,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include #include @@ -44,9 +45,6 @@ struct mem_region static struct mem_region mem_regions[MAX_REGIONS]; static int num_regions; -grub_addr_t grub_os_area_addr; -grub_size_t grub_os_area_size; - static char * make_install_device (void) { @@ -142,6 +140,22 @@ compact_mem_regions (void) } } +/* + * + * grub_get_conv_memsize(i) : return the conventional memory size in KB. + * BIOS call "INT 12H" to get conventional memory size + * The return value in AX. + */ +static inline grub_uint16_t +grub_get_conv_memsize (void) +{ + struct grub_bios_int_registers regs; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x12, ®s); + return regs.eax & 0xffff; +} + void grub_machine_init (void) { @@ -151,17 +165,12 @@ grub_machine_init (void) /* Initialize the console as early as possible. */ grub_console_init (); - grub_lower_mem = grub_get_memsize (0) << 10; + grub_lower_mem = grub_get_conv_memsize () << 10; /* Sanity check. */ if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END) grub_fatal ("too small memory"); -#if 0 - /* Turn on Gate A20 to access >1MB. */ - grub_gate_a20 (1); -#endif - /* FIXME: This prevents loader/i386/linux.c from using low memory. When our heap implements support for requesting a chunk in low memory, this should no longer be a problem. */ @@ -172,8 +181,10 @@ grub_machine_init (void) grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + 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) @@ -186,7 +197,7 @@ grub_machine_init (void) } /* Ignore >4GB. */ - if (addr <= 0xFFFFFFFF && type == GRUB_MACHINE_MEMORY_AVAILABLE) + if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) { grub_size_t len; @@ -203,25 +214,9 @@ grub_machine_init (void) compact_mem_regions (); - /* Add the memory regions to free memory, except for the region starting - from 1MB. This region is partially used for loading OS images. - For now, 1/4 of this is added to free memory. */ for (i = 0; i < num_regions; i++) - if (mem_regions[i].addr == 0x100000) - { - grub_size_t quarter = mem_regions[i].size >> 2; - - grub_os_area_addr = mem_regions[i].addr; - grub_os_area_size = mem_regions[i].size - quarter; - grub_mm_init_region ((void *) (grub_os_area_addr + grub_os_area_size), - quarter); - } - else grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size); - if (! grub_os_area_addr) - grub_fatal ("no upper memory"); - grub_tsc_init (); } diff --git a/kern/i386/pc/lzma_decode.S b/grub-core/kern/i386/pc/lzma_decode.S similarity index 92% rename from kern/i386/pc/lzma_decode.S rename to grub-core/kern/i386/pc/lzma_decode.S index a5a86848a..88c668d5e 100644 --- a/kern/i386/pc/lzma_decode.S +++ b/grub-core/kern/i386/pc/lzma_decode.S @@ -77,69 +77,6 @@ #define RepLenCoder (LenCoder + kNumLenProbs) #define Literal (RepLenCoder + kNumLenProbs) - -#if 0 - -DbgOut: - pushf - pushl %ebp - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - pushl %eax - - call _DebugPrint - - popl %eax - popl %ebx - popl %ecx - popl %edx - popl %esi - popl %edi - popl %ebp - popf - - ret - - -/* - * int LzmaDecodeProperties(CLzmaProperties *propsRes, - * const unsigned char *propsData, - * int size); - */ - -_LzmaDecodePropertiesA: - movb (%edx), %dl - - xorl %ecx, %ecx -1: - cmpb $45, %dl - jb 2f - incl %ecx - subb $45, %dl - jmp 1b -2: - movl %ecx, 8(%eax) /* pb */ - xorl %ecx, %ecx -1: - cmpb $9, %dl - jb 2f - incl %ecx - subb $9, %dl -2: - movl %ecx, 4(%eax) /* lp */ - movb %dl, %cl - movl %ecx, (%eax) /* lc */ - -#endif - -#ifndef ASM_FILE - xorl %eax, %eax -#endif - ret - #define out_size 8(%ebp) #define now_pos -4(%ebp) diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c new file mode 100644 index 000000000..a305d4511 --- /dev/null +++ b/grub-core/kern/i386/pc/mmap.c @@ -0,0 +1,169 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,2006,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 + +struct grub_machine_mmap_entry +{ + grub_uint32_t size; + grub_uint64_t addr; + grub_uint64_t len; +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +#define GRUB_MACHINE_MEMORY_RESERVED 2 +#define GRUB_MACHINE_MEMORY_ACPI 3 +#define GRUB_MACHINE_MEMORY_NVS 4 +#define GRUB_MACHINE_MEMORY_BADRAM 5 + grub_uint32_t type; +} __attribute__((packed)); + + +/* + * grub_get_ext_memsize() : return the extended memory size in KB. + * BIOS call "INT 15H, AH=88H" to get extended memory size + * The return value in AX. + * + */ +static inline grub_uint16_t +grub_get_ext_memsize (void) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x8800; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + return regs.eax & 0xffff; +} + +/* Get a packed EISA memory map. Lower 16 bits are between 1MB and 16MB + in 1KB parts, and upper 16 bits are above 16MB in 64KB parts. If error, return zero. + BIOS call "INT 15H, AH=E801H" to get EISA memory map, + AX = memory between 1M and 16M in 1K parts. + BX = memory above 16M in 64K parts. +*/ + +static inline grub_uint32_t +grub_get_eisa_mmap (void) +{ + struct grub_bios_int_registers regs; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + regs.eax = 0xe801; + grub_bios_interrupt (0x15, ®s); + + if ((regs.eax & 0xff00) == 0x8600) + return 0; + + return (regs.eax & 0xffff) | (regs.ebx << 16); +} + +/* + * + * grub_get_mmap_entry(addr, cont) : address and old continuation value (zero to + * start), for the Query System Address Map BIOS call. + * + * Sets the first 4-byte int value of "addr" to the size returned by + * the call. If the call fails, sets it to zero. + * + * Returns: new (non-zero) continuation value, 0 if done. + */ +/* Get a memory map entry. Return next continuation value. Zero means + the end. */ +static grub_uint32_t +grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, + grub_uint32_t cont) +{ + struct grub_bios_int_registers regs; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + /* place address (+4) in ES:DI */ + regs.es = ((grub_addr_t) &entry->addr) >> 4; + regs.edi = ((grub_addr_t) &entry->addr) & 0xf; + + /* set continuation value */ + regs.ebx = cont; + + /* set default maximum buffer size */ + regs.ecx = sizeof (*entry) - sizeof (entry->size); + + /* set EDX to 'SMAP' */ + regs.edx = 0x534d4150; + + regs.eax = 0xe820; + grub_bios_interrupt (0x15, ®s); + + /* write length of buffer (zero if error) into ADDR */ + if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) || regs.eax != 0x534d4150 + || regs.ecx < 0x14 || regs.ecx > 0x400) + entry->size = 0; + else + entry->size = regs.ecx; + + /* return the continuation value */ + return regs.ebx; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook) +{ + grub_uint32_t cont; + struct grub_machine_mmap_entry *entry + = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + + grub_memset (entry, 0, sizeof (entry)); + + /* Check if grub_get_mmap_entry works. */ + cont = grub_get_mmap_entry (entry, 0); + + 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 (! cont) + break; + + grub_memset (entry, 0, sizeof (entry)); + + cont = grub_get_mmap_entry (entry, cont); + } + while (entry->size); + else + { + grub_uint32_t eisa_mmap = grub_get_eisa_mmap (); + + if (eisa_mmap) + { + if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, + GRUB_MEMORY_AVAILABLE) == 0) + hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE); + } + else + hook (0x100000, grub_get_ext_memsize () << 10, GRUB_MEMORY_AVAILABLE); + } + + return 0; +} diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S new file mode 100644 index 000000000..d089a3e15 --- /dev/null +++ b/grub-core/kern/i386/pc/startup.S @@ -0,0 +1,1013 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,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 + * 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 . + */ + + +/* + * Note: These functions defined in this file may be called from C. + * Be careful of that you must not modify some registers. Quote + * from gcc-2.95.2/gcc/config/i386/i386.h: + + 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. + + ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg +{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + */ + +/* + * Note: GRUB is compiled with the options -mrtd and -mregparm=3. + * So the first three arguments are passed in %eax, %edx, and %ecx, + * respectively, and if a function has a fixed number of arguments + * and the number is greater than three, the function must return + * with "ret $N" where N is ((the number of arguments) - 3) * 4. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) + + .file "startup.S" + + .text + + /* Tell GAS to generate 16-bit instructions so that this code works + in real mode. */ + .code16 + + .globl start, _start +start: +_start: +LOCAL (base): + /* + * Guarantee that "main" is loaded at 0x0:0x8200. + */ +#ifdef __APPLE__ + ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000) +#else + ljmp $0, $ABS(LOCAL (codestart)) +#endif + /* + * Compatibility version number + * + * These MUST be at byte offset 6 and 7 of the executable + * DO NOT MOVE !!! + */ + . = _start + 0x6 + .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR + + /* + * This is a special data area 8 bytes from the beginning. + */ + + . = _start + 0x8 + +VARIABLE(grub_total_module_size) + .long 0 +VARIABLE(grub_kernel_image_size) + .long 0 +VARIABLE(grub_compressed_size) + .long 0 +VARIABLE(grub_install_dos_part) + .long 0xFFFFFFFF +VARIABLE(grub_install_bsd_part) + .long 0xFFFFFFFF +reed_solomon_redundancy: + .long 0 + +#ifdef APPLE_CC +bss_start: + .long 0 +bss_end: + .long 0 +#endif +/* + * This is the area for all of the special variables. + */ + +VARIABLE(grub_boot_drive) + .byte 0 + +/* the real mode code continues... */ +LOCAL (codestart): + cli /* we're not safe here! */ + + /* set up %ds, %ss, and %es */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + + /* set up the real mode/BIOS stack */ + movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp + movl %ebp, %esp + + sti /* we're safe again */ + + /* save the boot drive */ + ADDR32 movb %dl, EXT_C(grub_boot_drive) + + /* reset disk system (%ah = 0) */ + int $0x13 + + /* transition to protected mode */ + DATA32 call real_to_prot + + /* The ".code32" directive takes GAS out of 16-bit mode. */ + .code32 + + incl %eax + call grub_gate_a20 + + movl EXT_C(grub_compressed_size), %edx + addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx + movl reed_solomon_redundancy, %ecx + leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax + testl %edx, %edx + jz post_reed_solomon + call EXT_C (grub_reed_solomon_recover) + jmp post_reed_solomon + +#include + + .text + + . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART +/* + * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). + * This uses the a.out kludge to load raw binary to the area starting at 1MB, + * and relocates itself after loaded. + */ + .p2align 2 /* force 4-byte alignment */ +multiboot_header: + /* magic */ + .long 0x1BADB002 + /* flags */ + .long (1 << 16) + /* checksum */ + .long -0x1BADB002 - (1 << 16) + /* header addr */ + .long multiboot_header - _start + 0x100000 + 0x200 + /* load addr */ + .long 0x100000 + /* load end addr */ + .long 0 + /* bss end addr */ + .long 0 + /* entry addr */ + .long multiboot_entry - _start + 0x100000 + 0x200 + +multiboot_entry: + .code32 + /* obtain the boot device */ + movl 12(%ebx), %edx + + movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp + movl %ebp, %esp + + /* relocate the code */ + movl $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx + addl EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx + movl $0x100000, %esi + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi + cld + rep + movsb + /* jump to the real address */ + movl $multiboot_trampoline, %eax + jmp *%eax + +multiboot_trampoline: + /* fill the boot information */ + movl %edx, %eax + shrl $8, %eax + xorl %ebx, %ebx + cmpb $0xFF, %ah + je 1f + movb %ah, %bl + movl %ebx, EXT_C(grub_install_dos_part) +1: + cmpb $0xFF, %al + je 2f + movb %al, %bl + movl %ebx, EXT_C(grub_install_bsd_part) +2: + shrl $24, %edx + movb $0xFF, %dh + /* enter the usual booting */ + call prot_to_real + jmp LOCAL (codestart) + +post_reed_solomon: + +#ifdef ENABLE_LZMA + movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi + movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi + pushl %edi + pushl %esi + movl EXT_C(grub_kernel_image_size), %ecx + addl EXT_C(grub_total_module_size), %ecx + subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx + pushl %ecx + leal (%edi, %ecx), %ebx + call _LzmaDecodeA + /* _LzmaDecodeA clears DF, so no need to run cld */ + popl %ecx + popl %edi + popl %esi +#endif + + /* copy back the decompressed part (except the modules) */ + subl EXT_C(grub_total_module_size), %ecx + rep + movsb + +#if 0 + /* copy modules before cleaning out the bss */ + movl EXT_C(grub_total_module_size), %ecx + movl EXT_C(grub_kernel_image_size), %esi + addl %ecx, %esi + addl $_start, %esi + decl %esi + movl $END_SYMBOL, %edi + addl %ecx, %edi + decl %edi + std + rep + movsb +#endif + +#ifdef APPLE_CC + /* clean out the bss */ + bss_start_abs = ABS (bss_start) + bss_end_abs = ABS (bss_end) + + movl bss_start_abs, %edi + + /* compute the bss length */ + movl bss_end_abs, %ecx + subl %edi, %ecx +#else + /* clean out the bss */ + movl $BSS_START_SYMBOL, %edi + + /* compute the bss length */ + movl $END_SYMBOL, %ecx + subl %edi, %ecx +#endif + + /* clean out */ + xorl %eax, %eax + cld + rep + stosb + + /* + * Call the start of main body of C code. + */ + call EXT_C(grub_main) + +#include "../realmode.S" + +/* + * grub_gate_a20(int on) + * + * Gate address-line 20 for high memory. + * + * This routine is probably overconservative in what it does, but so what? + * + * It also eats any keystrokes in the keyboard buffer. :-( + */ + +grub_gate_a20: + movl %eax, %edx + +gate_a20_test_current_state: + /* first of all, test if already in a good state */ + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_bios + ret + +gate_a20_try_bios: + /* second, try a BIOS call */ + pushl %ebp + call prot_to_real + + .code16 + movw $0x2400, %ax + testb %dl, %dl + jz 1f + incw %ax +1: int $0x15 + + DATA32 call real_to_prot + .code32 + + popl %ebp + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_system_control_port_a + ret + +gate_a20_try_system_control_port_a: + /* + * In macbook, the keyboard test would hang the machine, so we move + * this forward. + */ + /* fourth, try the system control port A */ + inb $0x92 + andb $(~0x03), %al + testb %dl, %dl + jz 6f + orb $0x02, %al +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 + cmpb %al, %dl + jnz gate_a20_try_keyboard_controller +7: ret + +gate_a20_flush_keyboard_buffer: + inb $0x64 + andb $0x02, %al + jnz gate_a20_flush_keyboard_buffer +2: + inb $0x64 + andb $0x01, %al + jz 3f + inb $0x60 + jmp 2b +3: + ret + +gate_a20_try_keyboard_controller: + /* third, try the keyboard controller */ + call gate_a20_flush_keyboard_buffer + + movb $0xd1, %al + outb $0x64 +4: + inb $0x64 + andb $0x02, %al + jnz 4b + + 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) */ + movb $0xff, %al + outb $0x64 + call gate_a20_flush_keyboard_buffer + + call gate_a20_check_state + cmpb %al, %dl + /* everything failed, so restart from the beginning */ + jnz gate_a20_try_bios + ret + +gate_a20_check_state: + /* iterate the checking for a while */ + movl $100, %ecx +1: + call 3f + cmpb %al, %dl + jz 2f + loop 1b +2: + ret +3: + pushl %ebx + pushl %ecx + xorl %eax, %eax + /* compare the byte at 0x8000 with that at 0x108000 */ + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx + pushl %ebx + /* save the original byte in CL */ + movb (%ebx), %cl + /* store the value at 0x108000 in AL */ + addl $0x100000, %ebx + movb (%ebx), %al + /* try to set one less value at 0x8000 */ + popl %ebx + movb %al, %ch + decb %ch + movb %ch, (%ebx) + /* serialize */ + outb %al, $0x80 + outb %al, $0x80 + /* obtain the value at 0x108000 in CH */ + pushl %ebx + addl $0x100000, %ebx + movb (%ebx), %ch + /* 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) + popl %ecx + popl %ebx + ret + +#ifdef ENABLE_LZMA +#include "lzma_decode.S" +#endif + +/* + * The code beyond this point is compressed. Assert that the uncompressed + * code fits GRUB_KERNEL_MACHINE_RAW_SIZE. + */ + . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE + + . = _start + GRUB_KERNEL_MACHINE_PREFIX +VARIABLE(grub_prefix) + /* to be filled by grub-mkimage */ + + /* + * Leave some breathing room for the prefix. + */ + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END + + + +/* + * grub_exit() + * + * Exit the system. + */ +FUNCTION(grub_exit) + call prot_to_real + .code16 + /* Tell the BIOS a boot failure. If this does not work, reboot. */ + int $0x18 + jmp cold_reboot + .code32 + +/* + * void grub_chainloader_real_boot (int drive, void *part_addr) + * + * This starts another boot loader. + */ + +FUNCTION(grub_chainloader_real_boot) + pushl %edx + pushl %eax + + /* Turn off Gate A20 */ + xorl %eax, %eax + call grub_gate_a20 + + /* set up to pass boot drive */ + popl %edx + + /* ESI must point to a partition table entry */ + popl %esi + + call prot_to_real + .code16 + ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR + .code32 + +/* + * void grub_console_putchar (int c) + * + * Put the character C on the console. Because GRUB wants to write a + * character with an attribute, this implementation is a bit tricky. + * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh + * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, + * save the current position, restore the original position, write the + * character and the attribute, and restore the current position. + * + * The reason why this is so complicated is that there is no easy way to + * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't + * support setting a background attribute. + */ +FUNCTION(grub_console_putchar) + /* Retrieve the base character. */ + movl 0(%edx), %edx + pusha + movb EXT_C(grub_console_cur_color), %bl + + call prot_to_real + .code16 + movb %dl, %al + xorb %bh, %bh + + /* use teletype output if control character */ + cmpb $0x7, %al + je 1f + cmpb $0x8, %al + je 1f + cmpb $0xa, %al + je 1f + cmpb $0xd, %al + je 1f + + /* save the character and the attribute on the stack */ + pushw %ax + pushw %bx + + /* get the current position */ + movb $0x3, %ah + int $0x10 + + /* check the column with the width */ + cmpb $79, %dl + jl 2f + + /* print CR and LF, if next write will exceed the width */ + movw $0x0e0d, %ax + int $0x10 + movb $0x0a, %al + int $0x10 + + /* get the current position */ + movb $0x3, %ah + int $0x10 + +2: + /* restore the character and the attribute */ + popw %bx + popw %ax + + /* write the character with the attribute */ + movb $0x9, %ah + movw $1, %cx + int $0x10 + + /* move the cursor forward */ + incb %dl + movb $0x2, %ah + int $0x10 + + jmp 3f + +1: movw $1, %bx + movb $0xe, %ah + int $0x10 + +3: DATA32 call real_to_prot + .code32 + + popa + ret + + +LOCAL(bypass_table): + .word 0x011b, 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r' + .word 0x1c00 | '\n' +LOCAL(bypass_table_end): + +/* + * int grub_console_getkey (void) + * if there is a character pending, return it; otherwise return -1 + * BIOS call "INT 16H Function 01H" to check whether a character is pending + * Call with %ah = 0x1 + * Return: + * If key waiting to be input: + * %ah = keyboard scan code + * %al = ASCII character + * Zero flag = clear + * else + * Zero flag = set + * BIOS call "INT 16H Function 00H" to read character from keyboard + * Call with %ah = 0x0 + * Return: %ah = keyboard scan code + * %al = ASCII character + */ + +FUNCTION(grub_console_getkey) + pushl %ebp + pushl %edi + + call prot_to_real + .code16 + + /* + * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would + * cause the machine to hang at the second keystroke. However, we can + * work around this problem by ensuring the presence of keystroke with + * INT 16/AH = 1 before calling INT 16/AH = 0. + */ + + movb $1, %ah + int $0x16 + jz notpending + + movb $0, %ah + int $0x16 + + xorl %edx, %edx + movw %ax, %dx /* real_to_prot uses %eax */ + + DATA32 call real_to_prot + .code32 + + movl $0xff, %eax + testl %eax, %edx + jz 1f + + andl %edx, %eax + cmpl $0x20, %eax + jae 2f + movl %edx, %eax + leal LOCAL(bypass_table), %edi + movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) / 2), %ecx + repne scasw + jz 3f + + andl $0xff, %eax + addl $(('a' - 1) | GRUB_TERM_CTRL), %eax + jmp 2f +3: + andl $0xff, %eax + jmp 2f + +1: movl %edx, %eax + shrl $8, %eax + orl $GRUB_TERM_EXTENDED, %eax +2: + popl %edi + popl %ebp + ret + +notpending: + .code16 + DATA32 call real_to_prot + .code32 +#if GRUB_TERM_NO_KEY != 0 +#error Fix this asm code +#endif + jmp 2b + + +/* + * grub_uint16_t grub_console_getxy (void) + * BIOS call "INT 10H Function 03h" to get cursor position + * Call with %ah = 0x03 + * %bh = page + * Returns %ch = starting scan line + * %cl = ending scan line + * %dh = row (0 is top) + * %dl = column (0 is left) + */ + + +FUNCTION(grub_console_getxy) + pushl %ebp + pushl %ebx /* save EBX */ + + call prot_to_real + .code16 + + xorb %bh, %bh /* set page to 0 */ + movb $0x3, %ah + int $0x10 /* get cursor position */ + + DATA32 call real_to_prot + .code32 + + movb %dl, %ah + movb %dh, %al + + popl %ebx + popl %ebp + ret + + +/* + * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y) + * BIOS call "INT 10H Function 02h" to set cursor position + * Call with %ah = 0x02 + * %bh = page + * %dh = row (0 is top) + * %dl = column (0 is left) + */ + + +FUNCTION(grub_console_gotoxy) + pushl %ebp + pushl %ebx /* save EBX */ + + movb %cl, %dh /* %dh = y */ + /* %dl = x */ + + call prot_to_real + .code16 + + xorb %bh, %bh /* set page to 0 */ + movb $0x2, %ah + int $0x10 /* set cursor position */ + + DATA32 call real_to_prot + .code32 + + popl %ebx + popl %ebp + ret + + +/* + * void grub_console_cls (void) + * BIOS call "INT 10H Function 09h" to write character and attribute + * Call with %ah = 0x09 + * %al = (character) + * %bh = (page number) + * %bl = (attribute) + * %cx = (number of times) + */ + +FUNCTION(grub_console_cls) + pushl %ebp + pushl %ebx /* save EBX */ + + call prot_to_real + .code16 + + /* move the cursor to the beginning */ + movb $0x02, %ah + xorb %bh, %bh + xorw %dx, %dx + int $0x10 + + /* write spaces to the entire screen */ + movw $0x0920, %ax + movw $0x07, %bx + movw $(80 * 25), %cx + int $0x10 + + /* move back the cursor */ + movb $0x02, %ah + int $0x10 + + DATA32 call real_to_prot + .code32 + + popl %ebx + popl %ebp + ret + + +/* + * void grub_console_setcursor (int on) + * BIOS call "INT 10H Function 01h" to set cursor type + * Call with %ah = 0x01 + * %ch = cursor starting scanline + * %cl = cursor ending scanline + */ + +console_cursor_state: + .byte 1 +console_cursor_shape: + .word 0 + +FUNCTION(grub_console_setcursor) + pushl %ebp + pushl %ebx + + /* push ON */ + pushl %edx + + /* check if the standard cursor shape has already been saved */ + movw console_cursor_shape, %ax + testw %ax, %ax + jne 1f + + call prot_to_real + .code16 + + movb $0x03, %ah + xorb %bh, %bh + int $0x10 + + DATA32 call real_to_prot + .code32 + + cmp %cl, %ch + jb 3f + movw $0x0d0e, %cx +3: + movw %cx, console_cursor_shape +1: + /* set %cx to the designated cursor shape */ + movw $0x2000, %cx + popl %eax + testl %eax, %eax + jz 2f + movw console_cursor_shape, %cx +2: + call prot_to_real + .code16 + + movb $0x1, %ah + int $0x10 + + DATA32 call real_to_prot + .code32 + + popl %ebx + popl %ebp + ret + +/* + * grub_get_rtc() + * return the real time in ticks, of which there are about + * 18-20 per second + */ +FUNCTION(grub_get_rtc) + pushl %ebp + + call prot_to_real /* enter real mode */ + .code16 + + /* %ax is already zero */ + int $0x1a + + DATA32 call real_to_prot + .code32 + + movl %ecx, %eax + shll $16, %eax + movw %dx, %ax + + popl %ebp + ret + +/* + * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry); + */ +FUNCTION(grub_pxe_call) + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %edi + pushl %ebx + + movl %ecx, %ebx + movl %eax, %ecx + movl %edx, %eax + andl $0xF, %eax + shrl $4, %edx + shll $16, %edx + addl %eax, %edx + + call prot_to_real + .code16 + + pushl %ebx + pushl %edx + pushw %cx + movw %sp, %bx + lcall *%ss:6(%bx) + cld + addw $10, %sp + movw %ax, %cx + + DATA32 call real_to_prot + .code32 + + movzwl %cx, %eax + + popl %ebx + popl %edi + popl %esi + popl %ebp + ret + +FUNCTION(grub_bios_interrupt) + pushl %ebp + pushl %ecx + pushl %eax + pushl %ebx + pushl %esi + pushl %edi + pushl %edx + + movb %al, intno + movl (%edx), %eax + movl %eax, LOCAL(bios_register_eax) + movw 4(%edx), %ax + movw %ax, LOCAL(bios_register_es) + movw 6(%edx), %ax + movw %ax, LOCAL(bios_register_ds) + movw 8(%edx), %ax + movw %ax, LOCAL(bios_register_flags) + + movl 12(%edx), %ebx + movl 16(%edx), %ecx + movl 20(%edx), %edi + movl 24(%edx), %esi + movl 28(%edx), %edx + + call prot_to_real + .code16 + + mov %ds, %ax + push %ax + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_es): + .short 0 + movw %ax, %es + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_ds): + .short 0 + movw %ax, %ds + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_flags): + .short 0 + push %ax + popf + + /* movl imm32, %eax*/ + .byte 0x66, 0xb8 +LOCAL(bios_register_eax): + .long 0 + + /* int imm8. */ + .byte 0xcd +intno: + .byte 0 + + movl %eax, %cs:LOCAL(bios_register_eax) + movw %ds, %ax + movw %ax, %cs:LOCAL(bios_register_ds) + pop %ax + mov %ax, %ds + pushf + pop %ax + movw %ax, LOCAL(bios_register_flags) + mov %es, %ax + movw %ax, LOCAL(bios_register_es) + + DATA32 call real_to_prot + .code32 + + popl %eax + + movl %ebx, 12(%eax) + movl %ecx, 16(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %edx, 28(%eax) + + movl %eax, %edx + + movl LOCAL(bios_register_eax), %eax + movl %eax, (%edx) + movw LOCAL(bios_register_es), %ax + movw %ax, 4(%edx) + movw LOCAL(bios_register_ds), %ax + movw %ax, 6(%edx) + movw LOCAL(bios_register_flags), %ax + movw %ax, 8(%edx) + + popl %edi + popl %esi + popl %ebx + popl %eax + popl %ecx + popl %ebp + ret diff --git a/kern/i386/pit.c b/grub-core/kern/i386/pit.c similarity index 100% rename from kern/i386/pit.c rename to grub-core/kern/i386/pit.c diff --git a/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c similarity index 91% rename from kern/i386/qemu/init.c rename to grub-core/kern/i386/qemu/init.c index 201ba3633..054dfa86b 100644 --- a/kern/i386/qemu/init.c +++ b/grub-core/kern/i386/qemu/init.c @@ -69,10 +69,7 @@ load_palette (void) { unsigned i; for (i = 0; i < 16; i++) - { - grub_outb (i, GRUB_VGA_IO_ARX); - grub_outb (i, GRUB_VGA_IO_ARX); - } + grub_vga_write_arx (i, i); for (i = 0; i < ARRAY_SIZE (colors); i++) grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b); @@ -90,7 +87,7 @@ grub_qemu_init_cirrus (void) addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class = grub_pci_read (addr); - if (((class >> 16) & 0xffff) != 0x0300) + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA) return 0; /* FIXME: chooose addresses dynamically. */ @@ -110,7 +107,7 @@ grub_qemu_init_cirrus (void) grub_pci_iterate (find_card); - grub_outb (1, 0x3c2); + grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); load_font (); @@ -124,11 +121,11 @@ grub_qemu_init_cirrus (void) GRUB_VGA_SR_MAP_MASK_REGISTER); grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT); - grub_vga_cr_write (79, GRUB_VGA_CR_WIDTH); + grub_vga_cr_write (79, GRUB_VGA_CR_HORIZ_END); grub_vga_cr_write (40, GRUB_VGA_CR_PITCH); int vert = 25 * 16; - grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_HEIGHT); + grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_VDISPLAY_END); grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) | ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) @@ -137,10 +134,8 @@ grub_qemu_init_cirrus (void) load_palette (); - grub_outb (0x10, 0x3c0); - grub_outb (0, 0x3c1); - grub_outb (0x14, 0x3c0); - grub_outb (0, 0x3c1); + grub_vga_write_arx (GRUB_VGA_ARX_MODE_TEXT, GRUB_VGA_ARX_MODE); + grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT); grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK, GRUB_VGA_SR_CLOCKING_MODE); diff --git a/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c similarity index 86% rename from kern/i386/qemu/mmap.c rename to grub-core/kern/i386/qemu/mmap.c index f2a998e78..208f36b7e 100644 --- a/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -16,13 +16,14 @@ * along with GRUB. If not, see . */ -#include +#include #include #include #include #include #include #include +#include #define QEMU_CMOS_MEMSIZE_HIGH 0x35 #define QEMU_CMOS_MEMSIZE_LOW 0x34 @@ -61,33 +62,38 @@ grub_machine_mmap_init () } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { if (hook (0x0, (grub_addr_t) _start, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) + return 1; + + if (hook ((grub_addr_t) _end, + 0xa0000 - (grub_addr_t) _end, + GRUB_MEMORY_AVAILABLE)) return 1; if (hook (GRUB_MEMORY_MACHINE_UPPER, 0x100000 - GRUB_MEMORY_MACHINE_UPPER, - GRUB_MACHINE_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED)) return 1; /* Everything else is free. */ if (hook (0x100000, min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MACHINE_MEMORY_AVAILABLE)) + 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_MACHINE_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED)) return 1; if (above_4g != 0 && hook (0x100000000ULL, above_4g, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; return 0; diff --git a/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S similarity index 95% rename from kern/i386/qemu/startup.S rename to grub-core/kern/i386/qemu/startup.S index dc40cc4a2..7834d1df5 100644 --- a/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -18,6 +18,8 @@ #include #include + +#include #include #include @@ -39,7 +41,7 @@ VARIABLE(grub_prefix) * Leave some breathing room for the prefix. */ - . = _start + GRUB_KERNEL_MACHINE_DATA_END + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END codestart: /* Relocate to low memory. First we figure out our location. @@ -94,6 +96,9 @@ codestart: call EXT_C(grub_main) /* This should never happen. */ - jmp EXT_C(grub_stop) + cli +1: + hlt + jmp 1b #include "../realmode.S" diff --git a/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S similarity index 100% rename from kern/i386/realmode.S rename to grub-core/kern/i386/realmode.S diff --git a/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c similarity index 100% rename from kern/i386/tsc.c rename to grub-core/kern/i386/tsc.c diff --git a/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c similarity index 94% rename from kern/ieee1275/cmain.c rename to grub-core/kern/ieee1275/cmain.c index d3c3a8d88..30eacbbdd 100644 --- a/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -138,11 +138,16 @@ grub_ieee1275_find_options (void) */ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); } if (is_qemu) - /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); + { + /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); + + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); + } if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom)) { diff --git a/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c similarity index 100% rename from kern/ieee1275/ieee1275.c rename to grub-core/kern/ieee1275/ieee1275.c diff --git a/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c similarity index 91% rename from kern/ieee1275/init.c rename to grub-core/kern/ieee1275/init.c index 99ce7179b..682a8b5a4 100644 --- a/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -126,8 +127,10 @@ static void grub_claim_heap (void) { unsigned long total = 0; - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type) + 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; @@ -189,31 +192,6 @@ static void grub_claim_heap (void) grub_machine_mmap_iterate (heap_init); } -#ifdef __i386__ - -grub_uint32_t grub_upper_mem; - -/* We need to call this before grub_claim_memory. */ -static void -grub_get_extended_memory (void) -{ - auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type); - int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type) - { - if (type == 1 && addr == 0x100000) - { - grub_upper_mem = len; - return 1; - } - - return 0; - } - - grub_machine_mmap_iterate (find_ext_mem); -} - -#endif - static grub_uint64_t ieee1275_get_time_ms (void); void @@ -225,9 +203,6 @@ grub_machine_init (void) grub_ieee1275_init (); grub_console_init_early (); -#ifdef __i386__ - grub_get_extended_memory (); -#endif grub_claim_heap (); grub_console_init_lately (); grub_ofdisk_init (); diff --git a/kern/ieee1275/mmap.c b/grub-core/kern/ieee1275/mmap.c similarity index 91% rename from kern/ieee1275/mmap.c rename to grub-core/kern/ieee1275/mmap.c index 6f0652770..942e5a354 100644 --- a/kern/ieee1275/mmap.c +++ b/grub-core/kern/ieee1275/mmap.c @@ -16,12 +16,12 @@ * along with GRUB. If not, see . */ -#include +#include #include #include grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t memory; @@ -66,7 +66,7 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin if (size_cells == 2) size = (size << 32) | available[i++]; - if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE)) + if (hook (address, size, GRUB_MEMORY_AVAILABLE)) break; } diff --git a/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c similarity index 92% rename from kern/ieee1275/openfw.c rename to grub-core/kern/ieee1275/openfw.c index 75767d13c..f5dc8efb1 100644 --- a/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -424,13 +424,46 @@ grub_reboot (void) } #endif -void -grub_halt (void) +/* Resolve aliases. */ +char * +grub_ieee1275_canonicalise_devname (const char *path) { - /* Not standardized. We try three known commands. */ + struct canon_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t path; + grub_ieee1275_cell_t buf; + grub_ieee1275_cell_t inlen; + grub_ieee1275_cell_t outlen; + } + args; + char *buf = NULL; + grub_size_t bufsize = 64; + int i; - grub_ieee1275_interpret ("shut-down", 0); - grub_ieee1275_interpret ("power-off", 0); - grub_ieee1275_interpret ("poweroff", 0); - for (;;) ; + for (i = 0; i < 2; i++) + { + grub_free (buf); + + buf = grub_malloc (bufsize); + if (!buf) + return NULL; + + INIT_IEEE1275_COMMON (&args.common, "canon", 3, 1); + args.path = (grub_ieee1275_cell_t) path; + args.buf = (grub_ieee1275_cell_t) buf; + args.inlen = (grub_ieee1275_cell_t) (bufsize - 1); + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return 0; + if (args.outlen > bufsize - 1) + { + bufsize = args.outlen + 2; + continue; + } + return buf; + } + /* Shouldn't reach here. */ + grub_free (buf); + return NULL; } diff --git a/kern/list.c b/grub-core/kern/list.c similarity index 100% rename from kern/list.c rename to grub-core/kern/list.c diff --git a/kern/main.c b/grub-core/kern/main.c similarity index 100% rename from kern/main.c rename to grub-core/kern/main.c diff --git a/kern/mips/cache.S b/grub-core/kern/mips/cache.S similarity index 80% rename from kern/mips/cache.S rename to grub-core/kern/mips/cache.S index 2c35b6da2..999872f6b 100644 --- a/kern/mips/cache.S +++ b/grub-core/kern/mips/cache.S @@ -1,6 +1,9 @@ #include + .set noreorder + .set nomacro + FUNCTION (grub_cpu_flush_cache) FUNCTION (grub_arch_sync_caches) #include "cache_flush.S" diff --git a/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S similarity index 88% rename from kern/mips/cache_flush.S rename to grub-core/kern/mips/cache_flush.S index 5667ee7b4..11096c035 100644 --- a/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -9,15 +9,15 @@ subu $t1, $t3, $t2 1: cache 1, 0($t0) - addiu $t0, $t0, 0x1 addiu $t1, $t1, 0xffff bne $t1, $zero, 1b + addiu $t0, $t0, 0x1 sync move $t0, $t2 subu $t1, $t3, $t2 2: cache 0, 0($t0) - addiu $t0, $t0, 0x1 addiu $t1, $t1, 0xffff bne $t1, $zero, 2b + addiu $t0, $t0, 0x1 sync diff --git a/kern/mips/dl.c b/grub-core/kern/mips/dl.c similarity index 100% rename from kern/mips/dl.c rename to grub-core/kern/mips/dl.c diff --git a/kern/mips/init.c b/grub-core/kern/mips/init.c similarity index 100% rename from kern/mips/init.c rename to grub-core/kern/mips/init.c diff --git a/kern/mips/qemu-mips/init.c b/grub-core/kern/mips/qemu-mips/init.c similarity index 82% rename from kern/mips/qemu-mips/init.c rename to grub-core/kern/mips/qemu-mips/init.c index 866c7a82a..f2bb652a8 100644 --- a/kern/mips/qemu-mips/init.c +++ b/grub-core/kern/mips/qemu-mips/init.c @@ -51,11 +51,8 @@ grub_reboot (void) } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { - hook (0, RAMSIZE, - GRUB_MACHINE_MEMORY_AVAILABLE); + hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S new file mode 100644 index 000000000..ae0e0b187 --- /dev/null +++ b/grub-core/kern/mips/startup.S @@ -0,0 +1,126 @@ +/* startup.S - Startup code for the MIPS. */ +/* + * 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 + +#define BASE_ADDR 8 + + .globl __start, _start, start + .set noreorder + .set nomacro +__start: +_start: +start: +.extern __bss_start +.extern _end + bal cont + nop + + . = _start + GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE +total_module_size: + .long 0 + + . = _start + GRUB_KERNEL_MACHINE_PREFIX + +VARIABLE(grub_prefix) + + /* to be filled by grub-mkimage */ + + /* + * Leave some breathing room for the prefix. + */ + + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END +#ifdef GRUB_MACHINE_MIPS_YEELOONG +VARIABLE (grub_arch_busclock) + .long 0 +VARIABLE (grub_arch_cpuclock) + .long 0 +VARIABLE (grub_arch_memsize) + .long 0 +VARIABLE (grub_arch_highmemsize) + .long 0 +#endif +cont: + /* Save our base. */ + move $s0, $ra + +#ifdef GRUB_MACHINE_MIPS_YEELOONG + lui $t1, %hi(grub_arch_busclock) + addiu $t1, %lo(grub_arch_busclock) + sw $s2, 0($t1) + sw $s3, 4($t1) + sw $s4, 8($t1) + sw $s5, 12($t1) +#endif + + /* Move the modules out of BSS. */ + lui $t2, %hi(__bss_start) + addiu $t2, %lo(__bss_start) + + lui $t1, %hi(_end) + addiu $t1, %lo(_end) + addiu $t1, (GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + li $t3, (GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + nor $t3, $t3, $0 + and $t1, $t1, $t3 + + lw $t3, (GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE - BASE_ADDR)($s0) + + /* Backward copy. */ + add $t1, $t1, $t3 + add $t2, $t2, $t3 + addiu $t1, $t1, -1 + addiu $t2, $t2, -1 + + /* $t2 is source. $t1 is destination. $t3 is size. */ +modulesmovcont: + beq $t3, $0, modulesmovdone + nop + lb $t4, 0($t2) + sb $t4, 0($t1) + addiu $t2, $t2, -1 + addiu $t1, $t1, -1 + b modulesmovcont + addiu $t3, $t3, -1 +modulesmovdone: + + /* Clean BSS. */ + + lui $t1, %hi(__bss_start) + addiu $t1, $t1, %lo(__bss_start) + lui $t2, %hi(_end) + addiu $t2, $t2, %lo(_end) +bsscont: + sb $0,0($t1) + addiu $t1, $t1, 1 + sltu $t3, $t1, $t2 + bne $t3, $0, bsscont + nop + + lui $t1, %hi(grub_main) + addiu $t1, %lo(grub_main) + + lui $sp, %hi(GRUB_MACHINE_MEMORY_STACK_HIGH) + jr $t1 + addiu $sp, $sp, %lo(GRUB_MACHINE_MEMORY_STACK_HIGH) + diff --git a/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c similarity index 97% rename from kern/mips/yeeloong/init.c rename to grub-core/kern/mips/yeeloong/init.c index 523f90282..cc7c16806 100644 --- a/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ extern void grub_gfxterm_init (void); extern void grub_at_keyboard_init (void); extern void grub_serial_init (void); extern void grub_terminfo_init (void); +extern void grub_keylayouts_init (void); /* FIXME: use interrupt to count high. */ grub_uint64_t @@ -57,14 +59,12 @@ grub_get_rtc (void) } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } @@ -205,6 +205,7 @@ grub_machine_init (void) grub_font_init (); grub_gfxterm_init (); + grub_keylayouts_init (); grub_at_keyboard_init (); grub_terminfo_init (); diff --git a/kern/misc.c b/grub-core/kern/misc.c similarity index 97% rename from kern/misc.c rename to grub-core/kern/misc.c index b37ef230c..37ce8decd 100644 --- a/kern/misc.c +++ b/grub-core/kern/misc.c @@ -184,6 +184,7 @@ grub_real_dprintf (const char *file, const int line, const char *condition, va_start (args, fmt); grub_vprintf (fmt, args); va_end (args); + grub_refresh (); } } @@ -195,6 +196,8 @@ grub_vprintf (const char *fmt, va_list args) grub_size_t s; static char buf[PREALLOC_SIZE + 1]; char *curbuf = buf; + va_list ap2; + va_copy (ap2, args); s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args); if (s > PREALLOC_SIZE) @@ -209,7 +212,7 @@ grub_vprintf (const char *fmt, va_list args) buf[PREALLOC_SIZE] = 0; } else - s = grub_vsnprintf_real (curbuf, s, fmt, args); + s = grub_vsnprintf_real (curbuf, s, fmt, ap2); } grub_xputs (curbuf); @@ -946,11 +949,13 @@ grub_xvasprintf (const char *fmt, va_list ap) while (1) { + va_list ap2; + va_copy (ap2, ap); ret = grub_malloc (as + 1); if (!ret) return NULL; - s = grub_vsnprintf_real (ret, as, fmt, ap); + s = grub_vsnprintf_real (ret, as, fmt, ap2); if (s <= as) return ret; @@ -989,12 +994,12 @@ grub_abort (void) grub_exit (); } -#ifndef APPLE_CC +#if ! defined (APPLE_CC) && !defined (GRUB_UTIL) /* GCC emits references to abort(). */ void abort (void) __attribute__ ((alias ("grub_abort"))); #endif -#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL) && !defined(GRUB_MACHINE_EMU) +#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))) @@ -1002,7 +1007,7 @@ void __enable_execute_stack (void *addr __attribute__ ((unused))) } #endif -#if defined (NEED_REGISTER_FRAME_INFO) && !defined(GRUB_UTIL) +#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL) void __register_frame_info (void) { } diff --git a/kern/mm.c b/grub-core/kern/mm.c similarity index 91% rename from kern/mm.c rename to grub-core/kern/mm.c index 47324a662..8d9b5db78 100644 --- a/kern/mm.c +++ b/grub-core/kern/mm.c @@ -65,6 +65,7 @@ #include #include #include +#include #ifdef MM_DEBUG # undef grub_malloc @@ -74,45 +75,9 @@ # undef grub_memalign #endif -/* Magic words. */ -#define GRUB_MM_FREE_MAGIC 0x2d3c2808 -#define GRUB_MM_ALLOC_MAGIC 0x6db08fa4 - -typedef struct grub_mm_header -{ - struct grub_mm_header *next; - grub_size_t size; - grub_size_t magic; -#if GRUB_CPU_SIZEOF_VOID_P == 4 - char padding[4]; -#elif GRUB_CPU_SIZEOF_VOID_P == 8 - char padding[8]; -#else -# error "unknown word size" -#endif -} -*grub_mm_header_t; - -#if GRUB_CPU_SIZEOF_VOID_P == 4 -# define GRUB_MM_ALIGN_LOG2 4 -#elif GRUB_CPU_SIZEOF_VOID_P == 8 -# define GRUB_MM_ALIGN_LOG2 5 -#endif - -#define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2) - -typedef struct grub_mm_region -{ - struct grub_mm_header *first; - struct grub_mm_region *next; - grub_addr_t addr; - grub_size_t size; -} -*grub_mm_region_t; - -static grub_mm_region_t base; +grub_mm_region_t grub_mm_base; /* Get a header from the pointer PTR, and set *P and *R to a pointer to the header and a pointer to its region, respectively. PTR must @@ -123,9 +88,9 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r) if ((grub_addr_t) ptr & (GRUB_MM_ALIGN - 1)) grub_fatal ("unaligned pointer %p", ptr); - for (*r = base; *r; *r = (*r)->next) - if ((grub_addr_t) ptr > (*r)->addr - && (grub_addr_t) ptr <= (*r)->addr + (*r)->size) + for (*r = grub_mm_base; *r; *r = (*r)->next) + if ((grub_addr_t) ptr > (grub_addr_t) ((*r) + 1) + && (grub_addr_t) ptr <= (grub_addr_t) ((*r) + 1) + (*r)->size) break; if (! *r) @@ -156,18 +121,18 @@ grub_mm_init_region (void *addr, grub_size_t size) if (size < GRUB_MM_ALIGN) return; - h = (grub_mm_header_t) ((char *) r + GRUB_MM_ALIGN); + h = (grub_mm_header_t) (r + 1); h->next = h; h->magic = GRUB_MM_FREE_MAGIC; h->size = (size >> GRUB_MM_ALIGN_LOG2); r->first = h; - r->addr = (grub_addr_t) h; + r->pre_size = (grub_addr_t) r - (grub_addr_t) addr; r->size = (h->size << GRUB_MM_ALIGN_LOG2); /* Find where to insert this region. Put a smaller one before bigger ones, to prevent fragmentation. */ - for (p = &base, q = *p; q; p = &(q->next), q = *p) + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) if (q->size > r->size) break; @@ -206,6 +171,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) if (p->size >= n + extra) { + extra += (p->size - extra - n) & (~(align - 1)); if (extra == 0 && p->size == n) { /* There is no special alignment requirement and memory block @@ -284,10 +250,10 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) r = p + extra + n; r->magic = GRUB_MM_FREE_MAGIC; r->size = p->size - extra - n; - r->next = p->next; + r->next = p; p->size = extra; - p->next = r; + q->next = r; p += extra; } @@ -318,13 +284,16 @@ grub_memalign (grub_size_t align, grub_size_t size) grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1; int count = 0; + if (!grub_mm_base) + goto fail; + align = (align >> GRUB_MM_ALIGN_LOG2); if (align == 0) align = 1; again: - for (r = base; r; r = r->next) + for (r = grub_mm_base; r; r = r->next) { void *p; @@ -352,6 +321,7 @@ grub_memalign (grub_size_t align, grub_size_t size) break; } + fail: grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); return 0; } @@ -485,7 +455,7 @@ grub_mm_dump_free (void) { grub_mm_region_t r; - for (r = base; r; r = r->next) + for (r = grub_mm_base; r; r = r->next) { grub_mm_header_t p; @@ -512,13 +482,13 @@ grub_mm_dump (unsigned lineno) grub_mm_region_t r; grub_printf ("called at line %u\n", lineno); - for (r = base; r; r = r->next) + for (r = grub_mm_base; r; r = r->next) { grub_mm_header_t p; - for (p = (grub_mm_header_t) ((r->addr + GRUB_MM_ALIGN - 1) - & (~(GRUB_MM_ALIGN - 1))); - (grub_addr_t) p < r->addr + r->size; + for (p = (grub_mm_header_t) ALIGN_UP ((grub_addr_t) (r + 1), + GRUB_MM_ALIGN); + (grub_addr_t) p < (grub_addr_t) (r+1) + r->size; p++) { switch (p->magic) diff --git a/kern/parser.c b/grub-core/kern/parser.c similarity index 100% rename from kern/parser.c rename to grub-core/kern/parser.c diff --git a/kern/partition.c b/grub-core/kern/partition.c similarity index 100% rename from kern/partition.c rename to grub-core/kern/partition.c diff --git a/include/grub/powerpc/ieee1275/memory.h b/grub-core/kern/powerpc/cache.S similarity index 74% rename from include/grub/powerpc/ieee1275/memory.h rename to grub-core/kern/powerpc/cache.S index f8f2ff08d..d85e68d42 100644 --- a/include/grub/powerpc/ieee1275/memory.h +++ b/grub-core/kern/powerpc/cache.S @@ -1,6 +1,7 @@ +/* cache.S - Flush the processor cache for a specific region. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2004,2007,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 @@ -16,11 +17,10 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MEMORY_MACHINE_HEADER -#define GRUB_MEMORY_MACHINE_HEADER 1 + .text -#include - -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - -#endif + .align 2 + .globl grub_arch_sync_caches +grub_arch_sync_caches: +#include "cache_flush.S" + blr diff --git a/kern/powerpc/cache.S b/grub-core/kern/powerpc/cache_flush.S similarity index 91% rename from kern/powerpc/cache.S rename to grub-core/kern/powerpc/cache_flush.S index da982afa0..1410f78b1 100644 --- a/kern/powerpc/cache.S +++ b/grub-core/kern/powerpc/cache_flush.S @@ -1,7 +1,7 @@ /* cache.S - Flush the processor cache for a specific region. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004,2007 Free Software Foundation, Inc. + * Copyright (C) 2004,2007,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,13 +17,9 @@ * along with GRUB. If not, see . */ +#undef CACHE_LINE_BYTES #define CACHE_LINE_BYTES 32 - .text - - .align 2 - .globl grub_arch_sync_caches -grub_arch_sync_caches: /* `address' may not be CACHE_LINE_BYTES-aligned. */ andi. 6, 3, CACHE_LINE_BYTES - 1 /* Find the misalignment. */ add 4, 4, 6 /* Adjust `size' to compensate. */ @@ -45,4 +41,3 @@ grub_arch_sync_caches: sync /* Force all icbis to complete. */ isync /* Discard partially executed instructions that were loaded from the invalid icache. */ - blr diff --git a/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c similarity index 100% rename from kern/powerpc/dl.c rename to grub-core/kern/powerpc/dl.c diff --git a/kern/powerpc/ieee1275/startup.S b/grub-core/kern/powerpc/ieee1275/startup.S similarity index 95% rename from kern/powerpc/ieee1275/startup.S rename to grub-core/kern/powerpc/ieee1275/startup.S index 96d153778..0b1c23346 100644 --- a/kern/powerpc/ieee1275/startup.S +++ b/grub-core/kern/powerpc/ieee1275/startup.S @@ -33,13 +33,13 @@ _start: . = _start + GRUB_KERNEL_MACHINE_PREFIX VARIABLE(grub_prefix) - /* to be filled by grub-mkelfimage */ + /* to be filled by grub-mkimage */ /* * Leave some breathing room for the prefix. */ - . = _start + GRUB_KERNEL_MACHINE_DATA_END + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END codestart: li 2, 0 diff --git a/kern/rescue_parser.c b/grub-core/kern/rescue_parser.c similarity index 100% rename from kern/rescue_parser.c rename to grub-core/kern/rescue_parser.c diff --git a/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c similarity index 96% rename from kern/rescue_reader.c rename to grub-core/kern/rescue_reader.c index 531fcc8fa..a81008579 100644 --- a/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -39,7 +39,7 @@ grub_rescue_read_line (char **line, int cont) grub_printf ((cont) ? "> " : "grub rescue> "); grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE); - while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r') + while ((c = grub_getkey ()) != '\n' && c != '\r') { if (grub_isprint (c)) { diff --git a/kern/sparc64/cache.S b/grub-core/kern/sparc64/cache.S similarity index 100% rename from kern/sparc64/cache.S rename to grub-core/kern/sparc64/cache.S diff --git a/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c similarity index 100% rename from kern/sparc64/dl.c rename to grub-core/kern/sparc64/dl.c diff --git a/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S similarity index 92% rename from kern/sparc64/ieee1275/crt0.S rename to grub-core/kern/sparc64/ieee1275/crt0.S index f0f47416d..cebdca2b6 100644 --- a/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -42,7 +42,7 @@ VARIABLE(grub_prefix) * Leave some breathing room for the prefix. */ - . = EXT_C(_start) + GRUB_KERNEL_MACHINE_DATA_END + . = EXT_C(_start) + GRUB_KERNEL_MACHINE_PREFIX_END codestart: /* Copy the modules past the end of the kernel image. @@ -61,9 +61,11 @@ codestart: /* Save ieee1275 stack for future use by booter. */ mov %o6, %o1 /* Our future stack. */ - sethi %hi(GRUB_KERNEL_MACHINE_STACK_SIZE - 2047), %o5 - or %o5, %lo(GRUB_KERNEL_MACHINE_STACK_SIZE - 2047), %o5 + sethi %hi(GRUB_KERNEL_MACHINE_STACK_SIZE), %o5 + or %o5, %lo(GRUB_KERNEL_MACHINE_STACK_SIZE), %o5 add %o3, %o5, %o6 + and %o6, ~0xff, %o6 + sub %o6, 2047, %o6 sub %o2, 4, %o2 sub %o3, 4, %o3 diff --git a/kern/sparc64/ieee1275/ieee1275.c b/grub-core/kern/sparc64/ieee1275/ieee1275.c similarity index 100% rename from kern/sparc64/ieee1275/ieee1275.c rename to grub-core/kern/sparc64/ieee1275/ieee1275.c diff --git a/kern/sparc64/ieee1275/init.c b/grub-core/kern/sparc64/ieee1275/init.c similarity index 100% rename from kern/sparc64/ieee1275/init.c rename to grub-core/kern/sparc64/ieee1275/init.c diff --git a/kern/term.c b/grub-core/kern/term.c similarity index 82% rename from kern/term.c rename to grub-core/kern/term.c index 47bd426fd..7b3593161 100644 --- a/kern/term.c +++ b/grub-core/kern/term.c @@ -28,6 +28,8 @@ struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; +void (*grub_term_poll_usb) (void) = NULL; + /* Put a Unicode character. */ static void grub_putcode_dumb (grub_uint32_t code, @@ -76,56 +78,48 @@ grub_xputs_dumb (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_dumb; -int -grub_getkey (void) -{ - grub_term_input_t term; - - grub_refresh (); - - while (1) - { - FOR_ACTIVE_TERM_INPUTS(term) - { - int key = term->checkkey (term); - if (key != -1) - return term->getkey (term); - } - - grub_cpu_idle (); - } -} +static int pending_key = GRUB_TERM_NO_KEY; int grub_checkkey (void) { grub_term_input_t term; + if (pending_key != GRUB_TERM_NO_KEY) + return pending_key; + + if (grub_term_poll_usb) + grub_term_poll_usb (); + FOR_ACTIVE_TERM_INPUTS(term) { - int key = term->checkkey (term); - if (key != -1) - return key; + pending_key = term->getkey (term); + if (pending_key != GRUB_TERM_NO_KEY) + return pending_key; } return -1; } int -grub_getkeystatus (void) +grub_getkey (void) { - int status = 0; - grub_term_input_t term; + int ret; - FOR_ACTIVE_TERM_INPUTS(term) - { - if (term->getkeystatus) - status |= term->getkeystatus (term); - } + grub_refresh (); - return status; + grub_checkkey (); + while (pending_key == GRUB_TERM_NO_KEY) + { + grub_cpu_idle (); + grub_checkkey (); + } + ret = pending_key; + pending_key = GRUB_TERM_NO_KEY; + return ret; } + void grub_refresh (void) { diff --git a/kern/time.c b/grub-core/kern/time.c similarity index 100% rename from kern/time.c rename to grub-core/kern/time.c diff --git a/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c similarity index 100% rename from kern/x86_64/dl.c rename to grub-core/kern/x86_64/dl.c diff --git a/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S similarity index 100% rename from kern/x86_64/efi/callwrap.S rename to grub-core/kern/x86_64/efi/callwrap.S diff --git a/kern/x86_64/efi/startup.S b/grub-core/kern/x86_64/efi/startup.S similarity index 100% rename from kern/x86_64/efi/startup.S rename to grub-core/kern/x86_64/efi/startup.S diff --git a/lib/LzFind.c b/grub-core/lib/LzFind.c similarity index 99% rename from lib/LzFind.c rename to grub-core/lib/LzFind.c index cd7a1cbab..d2bb15c65 100644 --- a/lib/LzFind.c +++ b/grub-core/lib/LzFind.c @@ -24,6 +24,9 @@ * See , for more information about LZMA. */ + +#include + #include #include diff --git a/lib/LzmaDec.c b/grub-core/lib/LzmaDec.c similarity index 100% rename from lib/LzmaDec.c rename to grub-core/lib/LzmaDec.c diff --git a/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c similarity index 99% rename from lib/LzmaEnc.c rename to grub-core/lib/LzmaEnc.c index 842d43ac1..01ffa91f9 100644 --- a/lib/LzmaEnc.c +++ b/grub-core/lib/LzmaEnc.c @@ -24,6 +24,8 @@ * See , for more information about LZMA. */ +#include + #include #include diff --git a/lib/arg.c b/grub-core/lib/arg.c similarity index 79% rename from lib/arg.c rename to grub-core/lib/arg.c index a9b8a520e..75b1dd53c 100644 --- a/lib/arg.c +++ b/grub-core/lib/arg.c @@ -144,6 +144,9 @@ grub_arg_show_help (grub_extcmd_t cmd) } } + if (spacing < 0) + spacing = 3; + while (spacing--) grub_xputs (" "); @@ -209,8 +212,16 @@ parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr) if (found == -1) return -1; - usr[found].set = 1; - usr[found].arg = arg; + if (opt->flags & GRUB_ARG_OPTION_REPEATABLE) + { + usr[found].args[usr[found].set++] = arg; + usr[found].args[usr[found].set] = NULL; + } + else + { + usr[found].set = 1; + usr[found].arg = arg; + } } } @@ -223,17 +234,21 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, { int curarg; int arglen; - int complete = 0; char **argl = 0; int num = 0; auto grub_err_t add_arg (char *s); grub_err_t add_arg (char *s) { - argl = grub_realloc (argl, (++num) * sizeof (char *)); + char **p = argl; + argl = grub_realloc (argl, (++num + 1) * sizeof (char *)); if (! argl) - return grub_errno; + { + grub_free (p); + return grub_errno; + } argl[num - 1] = s; + argl[num] = NULL; return 0; } @@ -245,7 +260,8 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, char *option = 0; /* No option is used. */ - if (arg[0] != '-' || grub_strlen (arg) == 1) + if ((num && (cmd->cmd->flags & GRUB_COMMAND_OPTIONS_AT_START)) + || arg[0] != '-' || grub_strlen (arg) == 1) { if (add_arg (arg) != 0) goto fail; @@ -256,11 +272,28 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, /* One or more short options. */ if (arg[1] != '-') { - char *curshort = arg + 1; + char *curshort; + + if (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH) + { + for (curshort = arg + 1; *curshort; curshort++) + if (!find_short (cmd->options, *curshort)) + break; + + if (*curshort) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + } + + curshort = arg + 1; while (1) { opt = find_short (cmd->options, *curshort); + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -307,13 +340,27 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } option = grub_strchr (arg, '='); - if (option) { - arglen = option - arg - 2; - option++; - } else + if (option) + { + arglen = option - arg - 2; + option++; + } + else arglen = grub_strlen (arg) - 2; opt = find_long (cmd->options, arg + 2, arglen); + + if (!option && argv[curarg + 1] && argv[curarg + 1][0] != '-' + && opt->type != ARG_TYPE_NONE) + option = argv[++curarg]; + + if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg); @@ -382,11 +429,50 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } } - complete = 1; - *args = argl; *argnum = num; + return 1; fail: - return complete; + return 0; +} + +struct grub_arg_list* +grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, + char **argv __attribute__((unused))) +{ + int i; + char **args; + unsigned argcnt; + struct grub_arg_list *list; + const struct grub_arg_option *options; + + options = extcmd->options; + if (! options) + return 0; + + argcnt = 0; + for (i = 0; options[i].doc; i++) + { + if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) + argcnt += (argc + 1) / 2 + 1; /* max possible for any option */ + } + + list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); + if (! list) + return 0; + + args = (char**) (list + i); + for (i = 0; options[i].doc; i++) + { + list[i].set = 0; + list[i].arg = 0; + + if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) + { + list[i].args = args; + args += argc / 2 + 1; + } + } + return list; } diff --git a/lib/cmos_datetime.c b/grub-core/lib/cmos_datetime.c similarity index 100% rename from lib/cmos_datetime.c rename to grub-core/lib/cmos_datetime.c diff --git a/lib/crypto.c b/grub-core/lib/crypto.c similarity index 99% rename from lib/crypto.c rename to grub-core/lib/crypto.c index 6bd038168..f5768b8b5 100644 --- a/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -420,7 +420,7 @@ grub_password_get (char buf[], unsigned buf_size) while (1) { - key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + key = grub_getkey (); if (key == '\n' || key == '\r') break; diff --git a/lib/efi/datetime.c b/grub-core/lib/efi/datetime.c similarity index 100% rename from lib/efi/datetime.c rename to grub-core/lib/efi/datetime.c diff --git a/include/grub/i386/efi/loader.h b/grub-core/lib/efi/halt.c similarity index 59% rename from include/grub/i386/efi/loader.h rename to grub-core/lib/efi/halt.c index 222dae82d..c19536897 100644 --- a/include/grub/i386/efi/loader.h +++ b/grub-core/lib/efi/halt.c @@ -1,6 +1,7 @@ +/* efi.c - generic EFI support */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2006,2007 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -16,7 +17,20 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_LOADER_MACHINE_HEADER -#define GRUB_LOADER_MACHINE_HEADER 1 +#include +#include +#include +#include +#include +#include -#endif /* ! GRUB_LOADER_MACHINE_HEADER */ +void +grub_halt (void) +{ + grub_machine_fini (); + grub_acpi_halt (); + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, + GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); + + while (1); +} diff --git a/grub-core/lib/efi/relocator.c b/grub-core/lib/efi/relocator.c new file mode 100644 index 000000000..fc4de834b --- /dev/null +++ b/grub-core/lib/efi/relocator.c @@ -0,0 +1,104 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) + +unsigned +grub_relocator_firmware_get_max_events (void) +{ + grub_efi_uintn_t mmapsize = 0, descriptor_size = 0; + grub_efi_uint32_t descriptor_version = 0; + grub_efi_uintn_t key; + grub_efi_get_memory_map (&mmapsize, NULL, &key, &descriptor_size, + &descriptor_version); + /* Since grub_relocator_firmware_fill_events uses malloc + we need some reserve. Hence +10. */ + return 2 * (mmapsize / descriptor_size + 10); +} + +unsigned +grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) +{ + grub_efi_uintn_t mmapsize = 0, desc_size = 0; + grub_efi_uint32_t descriptor_version = 0; + grub_efi_memory_descriptor_t *descs = NULL; + grub_efi_uintn_t key; + int counter = 0; + grub_efi_memory_descriptor_t *desc; + + grub_efi_get_memory_map (&mmapsize, NULL, &key, &desc_size, + &descriptor_version); + descs = grub_malloc (mmapsize); + if (!descs) + return 0; + + grub_efi_get_memory_map (&mmapsize, descs, &key, &desc_size, + &descriptor_version); + + for (desc = descs; + (char *) desc < ((char *) descs + mmapsize); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + { + if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) + continue; + events[counter].type = REG_FIRMWARE_START; + events[counter].pos = desc->physical_start; + counter++; + events[counter].type = REG_FIRMWARE_END; + events[counter].pos = desc->physical_start + (desc->num_pages << 12); + counter++; + } + + return counter; +} + +int +grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) +{ + grub_efi_boot_services_t *b; + grub_efi_physical_address_t address = start; + grub_efi_status_t status; + + if (grub_efi_is_finished) + return 1; + + 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); + return (status == GRUB_EFI_SUCCESS); +} + +void +grub_relocator_firmware_free_region (grub_addr_t start, grub_size_t size) +{ + grub_efi_boot_services_t *b; + + if (grub_efi_is_finished) + return; + + b = grub_efi_system_table->boot_services; + efi_call_2 (b->free_pages, start, size >> 12); +} diff --git a/include/grub/i386/pc/efiemu.h b/grub-core/lib/emu/halt.c similarity index 78% rename from include/grub/i386/pc/efiemu.h rename to grub-core/lib/emu/halt.c index f269dd085..620935b5a 100644 --- a/include/grub/i386/pc/efiemu.h +++ b/grub-core/lib/emu/halt.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. + * Copyright (C) 2003,2004,2005,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 @@ -16,9 +16,10 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MACHINE_EFI_EMU_HEADER -#define GRUB_MACHINE_EFI_EMU_HEADER 1 +#include -grub_err_t grub_machine_efiemu_init_tables (void); - -#endif +void +grub_halt (void) +{ + grub_reboot (); +} diff --git a/lib/envblk.c b/grub-core/lib/envblk.c similarity index 100% rename from lib/envblk.c rename to grub-core/lib/envblk.c diff --git a/lib/hexdump.c b/grub-core/lib/hexdump.c similarity index 100% rename from lib/hexdump.c rename to grub-core/lib/hexdump.c diff --git a/kern/i386/halt.c b/grub-core/lib/i386/halt.c similarity index 77% rename from kern/i386/halt.c rename to grub-core/lib/i386/halt.c index 10805e42b..15c4ba0d6 100644 --- a/kern/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -17,16 +17,34 @@ */ #include -#include #include +#include const char bochs_shutdown[] = "Shutdown"; +/* + * This call is special... it never returns... in fact it should simply + * hang at this point! + */ +static inline void __attribute__ ((noreturn)) +stop (void) +{ + asm volatile ("cli"); + while (1) + { + asm volatile ("hlt"); + } +} + void grub_halt (void) { unsigned int i; +#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) + grub_acpi_halt (); +#endif + /* Disable interrupts. */ __asm__ __volatile__ ("cli"); @@ -38,5 +56,5 @@ grub_halt (void) /* In order to return we'd have to check what the previous status of IF flag was. But user most likely doesn't want to return anyway ... */ - grub_stop (); + stop (); } diff --git a/lib/i386/pc/biosnum.c b/grub-core/lib/i386/pc/biosnum.c similarity index 100% rename from lib/i386/pc/biosnum.c rename to grub-core/lib/i386/pc/biosnum.c diff --git a/grub-core/lib/i386/pc/vesa_modes_table.c b/grub-core/lib/i386/pc/vesa_modes_table.c new file mode 100644 index 000000000..6dc4b7d8d --- /dev/null +++ b/grub-core/lib/i386/pc/vesa_modes_table.c @@ -0,0 +1,127 @@ + +#include + +/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt + plus a few more modes based on the table in + http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ +struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1] = + { + { 640, 400, 8 }, /* 0x300 */ + { 640, 480, 8 }, /* 0x301 */ + { 800, 600, 4 }, /* 0x302 */ + { 800, 600, 8 }, /* 0x303 */ + { 1024, 768, 4 }, /* 0x304 */ + { 1024, 768, 8 }, /* 0x305 */ + { 1280, 1024, 4 }, /* 0x306 */ + { 1280, 1024, 8 }, /* 0x307 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 320, 200, 15 }, /* 0x30d */ + { 320, 200, 16 }, /* 0x30e */ + { 320, 200, 24 }, /* 0x30f */ + { 640, 480, 15 }, /* 0x310 */ + { 640, 480, 16 }, /* 0x311 */ + { 640, 480, 24 }, /* 0x312 */ + { 800, 600, 15 }, /* 0x313 */ + { 800, 600, 16 }, /* 0x314 */ + { 800, 600, 24 }, /* 0x315 */ + { 1024, 768, 15 }, /* 0x316 */ + { 1024, 768, 16 }, /* 0x317 */ + { 1024, 768, 24 }, /* 0x318 */ + { 1280, 1024, 15 }, /* 0x319 */ + { 1280, 1024, 16 }, /* 0x31a */ + { 1280, 1024, 24 }, /* 0x31b */ + { 1600, 1200, 8 }, /* 0x31c */ + { 1600, 1200, 15 }, /* 0x31d */ + { 1600, 1200, 16 }, /* 0x31e */ + { 1600, 1200, 24 }, /* 0x31f */ + { 0, 0, 0 }, + { 640, 400, 15 }, /* 0x321 */ + { 640, 400, 16 }, /* 0x322 */ + { 640, 400, 24 }, /* 0x323 */ + { 640, 400, 32 }, /* 0x324 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 640, 480, 32 }, /* 0x329 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 896, 672, 8 }, /* 0x32f */ + { 896, 672, 15 }, /* 0x330 */ + { 896, 672, 16 }, /* 0x331 */ + { 896, 672, 24 }, /* 0x332 */ + { 896, 672, 32 }, /* 0x333 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1600, 1200, 32 }, /* 0x342 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1440, 900, 8 }, /* 0x360 */ + { 1440, 900, 15 }, /* 0x361 */ + { 1440, 900, 16 }, /* 0x362 */ + { 1440, 900, 24 }, /* 0x363 */ + { 1440, 900, 32 }, /* 0x364 */ + { 1152, 720, 8 }, /* 0x365 */ + { 1152, 720, 15 }, /* 0x366 */ + { 1152, 720, 16 }, /* 0x367 */ + { 1152, 720, 24 }, /* 0x368 */ + { 1152, 720, 32 }, /* 0x369 */ + { 1024, 640, 8 }, /* 0x36a */ + { 1024, 640, 15 }, /* 0x36b */ + { 1024, 640, 16 }, /* 0x36c */ + { 1024, 640, 24 }, /* 0x36d */ + { 1024, 640, 32 }, /* 0x36e */ + { 800, 500, 8 }, /* 0x36f */ + { 800, 500, 15 }, /* 0x370 */ + { 800, 500, 16 }, /* 0x371 */ + { 800, 500, 24 }, /* 0x372 */ + { 800, 500, 32 }, /* 0x373 */ + }; diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c new file mode 100644 index 000000000..1bc4240c3 --- /dev/null +++ b/grub-core/lib/i386/relocator.c @@ -0,0 +1,270 @@ +/* + * 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 +#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; +extern grub_uint16_t grub_relocator16_ip; +extern grub_uint16_t grub_relocator16_ds; +extern grub_uint16_t grub_relocator16_es; +extern grub_uint16_t grub_relocator16_fs; +extern grub_uint16_t grub_relocator16_gs; +extern grub_uint16_t grub_relocator16_ss; +extern grub_uint16_t grub_relocator16_sp; +extern grub_uint32_t grub_relocator16_edx; + +extern grub_uint8_t grub_relocator32_start; +extern grub_uint8_t grub_relocator32_end; +extern grub_uint32_t grub_relocator32_eax; +extern grub_uint32_t grub_relocator32_ebx; +extern grub_uint32_t grub_relocator32_ecx; +extern grub_uint32_t grub_relocator32_edx; +extern grub_uint32_t grub_relocator32_eip; +extern grub_uint32_t grub_relocator32_esp; +extern grub_uint32_t grub_relocator32_ebp; +extern grub_uint32_t grub_relocator32_esi; +extern grub_uint32_t grub_relocator32_edi; + +extern grub_uint8_t grub_relocator64_start; +extern grub_uint8_t grub_relocator64_end; +extern grub_uint64_t grub_relocator64_rax; +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; + +#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) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, + (0xffffffff - RELOCATOR_SIZEOF (32)) + + 1, RELOCATOR_SIZEOF (32), 16, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + + grub_relocator32_eax = state.eax; + grub_relocator32_ebx = state.ebx; + grub_relocator32_ecx = state.ecx; + grub_relocator32_edx = state.edx; + grub_relocator32_eip = state.eip; + grub_relocator32_esp = state.esp; + grub_relocator32_ebp = state.ebp; + grub_relocator32_esi = state.esi; + grub_relocator32_edi = state.edi; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator32_start, + RELOCATOR_SIZEOF (32)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + asm volatile ("cli"); + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} + +grub_err_t +grub_relocator16_boot (struct grub_relocator *rel, + struct grub_relocator16_state state) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, + 0xa0000 - RELOCATOR_SIZEOF (16), + RELOCATOR_SIZEOF (16), 16, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + + grub_relocator16_cs = state.cs; + grub_relocator16_ip = state.ip; + + grub_relocator16_ds = state.ds; + grub_relocator16_es = state.es; + grub_relocator16_fs = state.fs; + grub_relocator16_gs = state.gs; + + grub_relocator16_ss = state.ss; + grub_relocator16_sp = state.sp; + + grub_relocator16_edx = state.edx; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start, + RELOCATOR_SIZEOF (16)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + asm volatile ("cli"); + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} + +grub_err_t +grub_relocator64_boot (struct grub_relocator *rel, + struct grub_relocator64_state state, + grub_addr_t min_addr, grub_addr_t max_addr) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr, + max_addr - RELOCATOR_SIZEOF (64), + RELOCATOR_SIZEOF (64), 16, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + + grub_relocator64_rax = state.rax; + grub_relocator64_rbx = state.rbx; + grub_relocator64_rcx = state.rcx; + grub_relocator64_rdx = state.rdx; + grub_relocator64_rip = state.rip; + grub_relocator64_rsp = state.rsp; + grub_relocator64_rsi = state.rsi; + grub_relocator64_cr3 = state.cr3; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator64_start, + RELOCATOR_SIZEOF (64)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + asm volatile ("cli"); + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S new file mode 100644 index 000000000..c3768f4eb --- /dev/null +++ b/grub-core/lib/i386/relocator16.S @@ -0,0 +1,193 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +/* The code segment of the protected mode. */ +#define CODE_SEGMENT 0x08 + +/* The data segment of the protected mode. */ +#define DATA_SEGMENT 0x10 + +#define PSEUDO_REAL_CSEG 0x18 + +#define PSEUDO_REAL_DSEG 0x20 + +#include "relocator_common.S" + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator16_start) + PREAMBLE + + movl %esi, %eax + movw %ax, (LOCAL (cs_base_bytes12) - LOCAL (base)) (RSI, 1) + shrl $16, %eax + movb %al, (LOCAL (cs_base_byte3) - LOCAL (base)) (RSI, 1) + + RELOAD_GDT + .code32 + /* Update other registers. */ + movl $DATA_SEGMENT, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + DISABLE_PAGING + +#ifdef __x86_64__ + /* Disable amd64. */ + movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx + rdmsr + andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax + wrmsr +#endif + + /* Turn off PAE. */ + movl %cr4, %eax + andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax + movl %eax, %cr4 + + /* Update other registers. */ + movl $PSEUDO_REAL_DSEG, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + movl %esi, %eax + shrl $4, %eax + movw %ax, (LOCAL (segment) - LOCAL (base)) (%esi, 1) + + /* jump to a 16 bit segment */ + ljmp $PSEUDO_REAL_CSEG, $(LOCAL (cont2) - LOCAL(base)) +LOCAL(cont2): + .code16 + + /* clear the PE bit of CR0 */ + movl %cr0, %eax + andl $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax + movl %eax, %cr0 + + /* flush prefetch queue, reload %cs */ + /* ljmp */ + .byte 0xea + .word LOCAL(cont3)-LOCAL(base) +LOCAL(segment): + .word 0 + +LOCAL(cont3): + /* we are in real mode now + * set up the real mode segment registers : DS, SS, ES + */ + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_ds) + .word 0 + movw %ax, %ds + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_es) + .word 0 + movw %ax, %es + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_fs) + .word 0 + movw %ax, %fs + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_gs) + .word 0 + movw %ax, %gs + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_ss) + .word 0 + movw %ax, %ss + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_sp) + .word 0 + movw %ax, %ss + + /* movw imm32, %edx. */ + .byte 0x66, 0xba +VARIABLE(grub_relocator16_edx) + .long 0 + + /* Cleared direction flag is of no problem with any current + payload and makes this implementation easier. */ + cld + + /* ljmp */ + .byte 0xea +VARIABLE(grub_relocator16_ip) + .word 0 +VARIABLE(grub_relocator16_cs) + .word 0 + + .code32 + + /* GDT. Copied from loader/i386/linux.c. */ + .p2align 4 +LOCAL(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 + + /* -- 16 bit real mode CS -- + * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present + * type = 16 bit code execute/read only/conforming, DPL = 0 + */ + .word 0xFFFF +LOCAL(cs_base_bytes12): + .word 0 +LOCAL(cs_base_byte3): + .byte 0 + + .byte 0x9E, 0, 0 + + /* -- 16 bit real mode DS -- + * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present + * type = 16 bit data read/write, DPL = 0 + */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0, 0 +LOCAL(gdt_end): + +VARIABLE(grub_relocator16_end) diff --git a/grub-core/lib/i386/relocator32.S b/grub-core/lib/i386/relocator32.S new file mode 100644 index 000000000..09ce56ad0 --- /dev/null +++ b/grub-core/lib/i386/relocator32.S @@ -0,0 +1,134 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +/* The code segment of the protected mode. */ +#define CODE_SEGMENT 0x10 + +/* The data segment of the protected mode. */ +#define DATA_SEGMENT 0x18 + +#include "relocator_common.S" + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator32_start) + PREAMBLE + + RELOAD_GDT + .code32 + /* Update other registers. */ + movl $DATA_SEGMENT, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + DISABLE_PAGING + +#ifdef __x86_64__ + /* Disable amd64. */ + movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx + rdmsr + andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax + wrmsr +#endif + + /* Turn off PAE. */ + movl %cr4, %eax + andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax + movl %eax, %cr4 + + jmp LOCAL(cont2) +LOCAL(cont2): + .code32 + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_esp) + .long 0 + + movl %eax, %esp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_ebp) + .long 0 + + movl %eax, %ebp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_esi) + .long 0 + + movl %eax, %esi + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_edi) + .long 0 + + movl %eax, %edi + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_eax) + .long 0 + + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator32_ebx) + .long 0 + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator32_ecx) + .long 0 + + /* mov imm32, %edx */ + .byte 0xba +VARIABLE(grub_relocator32_edx) + .long 0 + + /* Cleared direction flag is of no problem with any current + payload and makes this implementation easier. */ + cld + + .byte 0xea +VARIABLE(grub_relocator32_eip) + .long 0 + .word CODE_SEGMENT + + /* GDT. Copied from loader/i386/linux.c. */ + .p2align 4 +LOCAL(gdt): + /* NULL. */ + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* Reserved. */ + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* Code segment. */ + .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 + + /* Data segment. */ + .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 +LOCAL(gdt_end): + +VARIABLE(grub_relocator32_end) diff --git a/grub-core/lib/i386/relocator64.S b/grub-core/lib/i386/relocator64.S new file mode 100644 index 000000000..bb086418c --- /dev/null +++ b/grub-core/lib/i386/relocator64.S @@ -0,0 +1,160 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#define CODE32_SEGMENT 0x18 +#define CODE_SEGMENT 0x08 + +/* The data segment of the protected mode. */ +#define DATA_SEGMENT 0x10 + +#include "relocator_common.S" + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator64_start) + PREAMBLE +#ifndef __x86_64__ + DISABLE_PAGING + + /* Turn on PAE. */ + movl %cr4, %eax + orl $(GRUB_MEMORY_CPU_CR4_PAE_ON | GRUB_MEMORY_CPU_CR4_PSE_ON), %eax + movl %eax, %cr4 + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator64_cr3) + .long 0 + movl %eax, %cr3 + + /* Turn on amd64. */ + movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx + rdmsr + orl $GRUB_MEMORY_CPU_AMD64_MSR_ON, %eax + wrmsr + + /* Enable paging. */ + movl %cr0, %eax + orl $GRUB_MEMORY_CPU_CR0_PAGING_ON, %eax + movl %eax, %cr0 + + RELOAD_GDT +#else + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_cr3) + .quad 0 + movq %rax, %cr3 +#endif + + .code64 + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_rsp) + .quad 0 + + movq %rax, %rsp + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_rsi) + .quad 0 + + movq %rax, %rsi + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_rax) + .quad 0 + + /* mov imm64, %rbx */ + .byte 0x48 + .byte 0xbb +VARIABLE(grub_relocator64_rbx) + .quad 0 + + /* mov imm64, %rcx */ + .byte 0x48 + .byte 0xb9 +VARIABLE(grub_relocator64_rcx) + .quad 0 + + /* mov imm64, %rdx */ + .byte 0x48 + .byte 0xba +VARIABLE(grub_relocator64_rdx) + .quad 0 + + /* Cleared direction flag is of no problem with any current + payload and makes this implementation easier. */ + cld + + jmp *LOCAL(jump_addr) (%rip) + +LOCAL(jump_addr): +VARIABLE(grub_relocator64_rip) + .quad 0 + +#ifndef __x86_64__ + .p2align 4 +LOCAL(gdt): + /* NULL. */ + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* 64-bit segment. */ + .word 0xffff /* Limit xffff. */ + .word 0x0000 /* Base xxxx0000. */ + .byte 0x00 /* Base xx00xxxx. */ + .byte (0x8 /* Type 8. */ | (1 << 4) /* Code. */ \ + | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */) + .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \ + | (1 << 5) /* 64-bit. */ | (0 << 6) \ + | (1 << 7) /* 4K granular. */) + .byte 0x00 /* Base 00xxxxxx. */ + + /* Data segment*/ + .word 0xffff /* Limit xffff. */ + .word 0x0000 /* Base xxxx0000. */ + .byte 0x00 /* Base xx00xxxx. */ + .byte (0x0 /* Type 0. */ | (0 << 4) /* Data. */ \ + | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */) + .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \ + | (0 << 5) /* Data. */ | (0 << 6) \ + | (1 << 7) /* 4K granular. */) + .byte 0x00 /* Base 00xxxxxx. */ + + /* Compatibility segment. */ + .word 0xffff /* Limit xffff. */ + .word 0x0000 /* Base xxxx0000. */ + .byte 0x00 /* Base xx00xxxx. */ + .byte (0x8 /* Type 8. */ | (1 << 4) /* Code. */ \ + | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */) + .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \ + | (0 << 5) /* 32-bit. */ | (1 << 6) /* 32-bit. */ \ + | (1 << 7) /* 4K granular. */) + .byte 0x00 /* Base 00xxxxxx. */ + +LOCAL(gdt_end): +#endif + +VARIABLE(grub_relocator64_end) diff --git a/grub-core/lib/i386/relocator_asm.S b/grub-core/lib/i386/relocator_asm.S new file mode 100644 index 000000000..f273586fe --- /dev/null +++ b/grub-core/lib/i386/relocator_asm.S @@ -0,0 +1,80 @@ +/* + * 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 + + .p2align 2 + +VARIABLE(grub_relocator_backward_start) + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_backward_dest) + .long 0 + movl %eax, %edi + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_backward_src) + .long 0 + movl %eax, %esi + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator_backward_chunk_size) + .long 0 + + add %ecx, %esi + add %ecx, %edi + + + /* Backward movsb is implicitly off-by-one. compensate that. */ + sub $1, %esi + sub $1, %edi + + /* Backward copy. */ + std + + rep + movsb +VARIABLE(grub_relocator_backward_end) + + +VARIABLE(grub_relocator_forward_start) + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_forward_dest) + .long 0 + movl %eax, %edi + + /* mov imm32, %rax */ + .byte 0xb8 +VARIABLE(grub_relocator_forward_src) + .long 0 + movl %eax, %esi + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator_forward_chunk_size) + .long 0 + + /* Forward copy. */ + cld + rep + movsb +VARIABLE(grub_relocator_forward_end) diff --git a/lib/i386/relocator_backward.S b/grub-core/lib/i386/relocator_backward.S similarity index 100% rename from lib/i386/relocator_backward.S rename to grub-core/lib/i386/relocator_backward.S diff --git a/grub-core/lib/i386/relocator_common.S b/grub-core/lib/i386/relocator_common.S new file mode 100644 index 000000000..bd5b53f95 --- /dev/null +++ b/grub-core/lib/i386/relocator_common.S @@ -0,0 +1,82 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + +#ifdef __x86_64__ +#define RAX %rax +#define RSI %rsi +#else +#define RAX %eax +#define RSI %esi +#endif + + .macro DISABLE_PAGING +#ifdef GRUB_MACHINE_IEEE1275 +#endif + + movl %cr0, %eax + andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax + movl %eax, %cr0 + .endm + + .macro PREAMBLE +LOCAL(base): + /* %rax contains now our new 'base'. */ + mov RAX, RSI + + add $(LOCAL(cont0) - LOCAL(base)), RAX + jmp *RAX +LOCAL(cont0): + .endm + + .macro RELOAD_GDT + lea (LOCAL(cont1) - LOCAL(base)) (RSI, 1), RAX + movl %eax, (LOCAL(jump_vector) - LOCAL(base)) (RSI, 1) + + lea (LOCAL(gdt) - LOCAL(base)) (RSI, 1), RAX + mov RAX, (LOCAL(gdt_addr) - LOCAL(base)) (RSI, 1) + + /* Switch to compatibility mode. */ + lgdt (LOCAL(gdtdesc) - LOCAL(base)) (RSI, 1) + + /* Update %cs. */ + ljmp *(LOCAL(jump_vector) - LOCAL(base)) (RSI, 1) + + .p2align 4 +LOCAL(gdtdesc): + .word LOCAL(gdt_end) - LOCAL(gdt) +LOCAL(gdt_addr): +#ifdef __x86_64__ + /* Filled by the code. */ + .quad 0 +#else + /* Filled by the code. */ + .long 0 +#endif + + .p2align 4 +LOCAL(jump_vector): + /* Jump location. Is filled by the code */ + .long 0 + .long CODE_SEGMENT + +LOCAL(cont1): + .endm diff --git a/lib/i386/setjmp.S b/grub-core/lib/i386/setjmp.S similarity index 100% rename from lib/i386/setjmp.S rename to grub-core/lib/i386/setjmp.S diff --git a/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c similarity index 100% rename from lib/ieee1275/datetime.c rename to grub-core/lib/ieee1275/datetime.c diff --git a/grub-core/lib/ieee1275/halt.c b/grub-core/lib/ieee1275/halt.c new file mode 100644 index 000000000..7ede29de9 --- /dev/null +++ b/grub-core/lib/ieee1275/halt.c @@ -0,0 +1,33 @@ +/* openfw.c -- Open firmware support functions. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,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 + * 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_halt (void) +{ + /* Not standardized. We try three known commands. */ + + 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 new file mode 100644 index 000000000..c09f1e9c5 --- /dev/null +++ b/grub-core/lib/ieee1275/relocator.c @@ -0,0 +1,95 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include +#include + +unsigned +grub_relocator_firmware_get_max_events (void) +{ + int counter = 0; + auto int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t len __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused))); + int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t len __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused))) + { + counter++; + return 0; + } + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) + return 0; + grub_machine_mmap_iterate (count); + return 2 * counter; +} + +unsigned +grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) +{ + int counter = 0; + auto int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) + { + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) + return 0; + + if (addr < 0x180000) + { + len = addr + len - 0x180000; + addr = 0x180000; + } + } + + events[counter].type = REG_FIRMWARE_START; + events[counter].pos = addr; + counter++; + events[counter].type = REG_FIRMWARE_END; + events[counter].pos = addr + len; + counter++; + + return 0; + } + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) + return 0; + grub_machine_mmap_iterate (fill); + return counter; +} + +int +grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) +{ + return (grub_claimmap (start, size) >= 0); +} + +void +grub_relocator_firmware_free_region (grub_addr_t start, grub_size_t size) +{ + grub_ieee1275_release (start, size); +} diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c new file mode 100644 index 000000000..5a359ff1c --- /dev/null +++ b/grub-core/lib/legacy_parse.c @@ -0,0 +1,819 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 + * 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 legacy_command +{ + const char *name; + const char *map; + const char *suffix; + unsigned suffixarg; + unsigned argc; + enum arg_type { + TYPE_VERBATIM, + TYPE_FORCE_OPTION, + TYPE_NOAPM_OPTION, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_OPTION, + TYPE_FILE, + TYPE_FILE_NO_CONSUME, + TYPE_PARTITION, + TYPE_BOOL, + TYPE_INT, + TYPE_REST_VERBATIM, + TYPE_VBE_MODE + } argt[4]; + enum { + FLAG_IGNORE_REST = 0x001, + FLAG_FALLBACK_AVAILABLE = 0x004, + FLAG_FALLBACK = 0x008, + FLAG_COLOR_INVERT = 0x010, + FLAG_NO_MENUENTRY = 0x020, + FLAG_MENUENTRY_ONLY = 0x040, + FLAG_TERMINAL = 0x080, + FLAG_TITLE = 0x100, + } flags; + const char *shortdesc; + const char *longdesc; +}; + +struct legacy_command legacy_commands[] = + { + {"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."}, + /* FIXME: bootp 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."}, + {"cmp", "cmp '%s' '%s'\n", NULL, 0, + 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, "FILE1 FILE2", + "Compare the file FILE1 with the FILE2 and inform the different values" + " if any."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + 2, {TYPE_VERBATIM, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "NORMAL [HIGHLIGHT]", + "Change the menu colors. The color NORMAL is used for most" + " lines in the menu, and the color HIGHLIGHT is used to highlight the" + " line where the cursor points. If you omit HIGHLIGHT, then the" + " inverted color of NORMAL is used for the highlighted line." + " The format of a color is \"FG/BG\". FG and BG are symbolic color names." + " A symbolic color name must be one of these: black, blue, green," + " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," + " light-green, light-cyan, light-red, light-magenta, yellow and white." + " But only the first eight names can be used for BG. You can prefix" + " \"blink-\" to FG if you want a blinking foreground color."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_COLOR_INVERT, NULL, NULL}, + {"configfile", "legacy_configfile '%s'\n", NULL, 0, 1, {TYPE_FILE}, + 0, "FILE", "Load FILE as the configuration file."}, + {"debug", + "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", NULL, 0, + 0, {}, 0, 0, "Turn on/off the debug mode."}, + {"default", + "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " + "set default=\"$saved_entry\"; fi\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, + "[NUM | `saved']", + "Set the default entry to entry number NUM (if not specified, it is" + " 0, the first entry) or the entry number saved by savedefault."}, + /* FIXME: dhcp unsupported. */ + {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, + "Display APM BIOS information."}, + {"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."}, + /* NOTE: embed unsupported. */ + {"fallback", "set fallback='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, 0, "NUM...", + "Go into unattended boot mode: if the default boot entry has any" + " errors, instead of waiting for the user to do anything, it" + " immediately starts over using the NUM entry (same numbering as the" + " `default' command). This obviously won't help if the machine" + " was rebooted by a kernel that GRUB loaded."}, + {"find", "search -sf '%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: 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", + "Print the information for a drive DRIVE. "}, + {"halt", "halt %s\n", NULL, 0, 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", + "Halt your system. If APM is available on it, turn off the power using" + " the APM BIOS, unless you specify the option `--no-apm'."}, + /* FIXME: help unsupported. */ /* NUL_TERMINATE */ + {"hiddenmenu", NULL, + "if sleep -i $timeout; then timeout=0; else timeout=-1; fi\n", 0, + 0, {}, 0, "", "Hide the menu."}, + {"hide", "parttool '%s' hidden+\n", NULL, 0, 1, {TYPE_PARTITION}, + 0, "PARTITION", + "Hide PARTITION by setting the \"hidden\" bit in" + " its partition type code."}, + /* FIXME: ifconfig unsupported. */ + /* FIXME: impsprobe unsupported. */ + {"initrd", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load an initial ramdisk FILE for a Linux format boot image and set the" + " appropriate parameters in the Linux setup area in memory."}, + /* NOTE: install unsupported. */ + /* FIXME: ioprobe unsupported. */ + /* FIXME: really support --no-mem-option. */ + {"kernel", "legacy_kernel %s %s '%s' %s\n", NULL, 0, + 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "Attempt to load the primary boot image from FILE. The rest of the" + " line is passed verbatim as the \"kernel command line\". Any modules" + " must be reloaded after using this command. The option --type is used" + " to suggest what type of kernel to be loaded. TYPE must be either of" + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" + " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" + " Linux's mem option automatically."}, + {"lock", "if ! authenticate legacy; then return; fi", NULL, 0, 0, {}, 0, + 0, "Break a command execution unless the user is authenticated."}, + {"makeactive", "parttool \"$root\" boot+\n", NULL, 0, 0, {}, 0, 0, + "Set the active partition on the root disk to GRUB's root device." + " This command is limited to _primary_ PC partitions on a hard disk."}, + {"map", "drivemap '%s' '%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_PARTITION}, + FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", + "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" + " when you chain-load some operating systems, such as DOS, if such an" + " OS resides at a non-first drive."}, + /* NOTE: md5crypt unsupported since GRUB has not enough entropy and this + hash shouldn't be used anymore. */ + {"module", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load a boot module FILE for a Multiboot format boot image (no" + " interpretation of the file contents is made, so users of this" + " command must know what the kernel in question expects). The" + " rest of the line is passed as the \"module command line\", like" + " the `kernel' command."}, + {"modulenounzip", "legacy_initrd_nounzip '%s' %s\n", NULL, 0, 2, + {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "The same as `module', except that automatic decompression is" + " disabled."}, + {"pager", "set pager=%s; if [ \"$pager\" = 0 ]; then " + " echo Internal pager is now off; else " + "echo Internal pager is now on; fi\n", NULL, 0, + 1, {TYPE_BOOL}, FLAG_FALLBACK_AVAILABLE, "[FLAG]", + "Toggle pager mode with no argument. If FLAG is given and its value" + " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, + {"pager", + "if [ \"$pager\" = 1 ]; then pager=0; echo Internal pager is now off;" + "else pager=1; echo Internal pager is now on; fi\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL}, + /* FIXME: partnew unsupported. */ + {"parttype", "parttool '%s' type=%s\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "PART TYPE", "Change the type of the partition PART to TYPE."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'\n", + "menuentry \"Superuser menu\" --users \"legacy\" { configfile '%s'; }\n", + 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_NO_MENUENTRY, + "[--md5] PASSWD [FILE]", + "If used in the first section of a menu file, disable all" + " interactive editing control (menu entry editor and" + " command line). If the password PASSWD is entered, it loads the" + " FILE as a new config file and restarts the GRUB Stage 2. If you" + " omit the argument FILE, then GRUB just unlocks privileged" + " instructions. You can also use it in the script section, in" + " which case it will ask for the password, before continuing." + " The option --md5 tells GRUB that PASSWD is encrypted with" + " md5crypt."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'\n", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_NO_MENUENTRY, NULL, NULL}, + {"password", "if legacy_check_password %s '%s'; then configfile '%s'; " + "else return; fi\n", NULL, 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_MENUENTRY_ONLY, + NULL, NULL}, + {"password", "if ! legacy_check_password %s '%s'; then return fi;\n", + NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_MENUENTRY_ONLY, NULL, NULL}, + /* NOTE: GRUB2 has a design principle of not eternally waiting for user + input. 60 seconds should be enough. + */ + {"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."}, + /* 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" + " display it in hex format."}, + {"reboot", "reboot\n", NULL, 0, 0, {}, 0, 0, "Reboot your system."}, + {"root", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, FLAG_FALLBACK_AVAILABLE, + "[DEVICE [HDBIAS]]", + "Set the current \"root device\" to the device DEVICE, then" + " attempt to mount it to get the partition size (for passing the" + " partition descriptor in `ES:ESI', used by some chain-loaded" + " bootloaders), the BSD drive-type (for booting BSD kernels using" + " their native boot format), and correctly determine " + " the PC partition where a BSD sub-partition is located. The" + " optional HDBIAS parameter is a number to tell a BSD kernel" + " how many BIOS drive numbers are on controllers before the current" + " one. For example, if there is an IDE disk and a SCSI disk, and your" + " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, + {"root", "echo \"$root\"\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL}, + {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "[DEVICE [HDBIAS]]", + "Similar to `root', but don't attempt to mount the partition. This" + " is useful for when an OS is outside of the area of the disk that" + " GRUB can read, but setting the correct root device is still" + " desired. Note that the items mentioned in `root' which" + " derived from attempting the mount will NOT work correctly."}, + {"rootnoverify", "echo \"$root\"\n", NULL, 0, + 0, {}, FLAG_FALLBACK, NULL, NULL}, + /* FIXME: support saving NUM and fallback. */ + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", NULL, 0, + 0, {}, 0, "[NUM | `fallback']", + "Save the current entry as the default boot entry if no argument is" + " specified. If a number is specified, this number is saved. If" + " `fallback' is used, next fallback entry is saved."}, + {"serial", "serial %s\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, + "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " + "[--parity=PARITY] [--stop=STOP] [--device=DEV]", + "Initialize a serial device. UNIT is a digit that specifies which serial" + " device is used (e.g. 0 == COM1). If you need to specify the port number," + " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," + " PARITY is the type of parity, which is one of `no', `odd' and `even'." + " 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: setkey unsupported. */ /* NUL_TERMINATE */ + /* NOTE: setup unsupported. */ + /* FIXME: --no-echo, --no-edit, hercules unsupported. */ + /* NOTE: both terminals are activated so --silent and --timeout + are useless. */ + {"terminal", NULL, NULL, 0, 0, {}, FLAG_TERMINAL | FLAG_IGNORE_REST, + "[--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] " + "[--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" + " argument is specified, print current setting. The option --dumb" + " specifies that your terminal is dumb, otherwise, vt100-compatibility" + " is assumed. If you specify --no-echo, input characters won't be echoed." + " If you specify --no-edit, the BASH-like editing feature will be disabled." + " If --timeout is present, this command will wait at most for SECS" + " seconds. The option --lines specifies the maximum number of lines." + " The option --silent is used to suppress messages."}, + /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ + {"testload", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "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" + " step is to try loading a kernel."}, + {"testvbe", "insmod vbe; videotest '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, 0, + "MODE", "Test the VBE mode MODE. Hit any key to return."}, + /* FIXME: tftpserver unsupported. */ + {"timeout", "set timeout=%s\n", NULL, 0, 1, {TYPE_INT}, 0, "SEC", + "Set a timeout, in SEC seconds, before automatically booting the" + " default entry (normally the first entry defined)."}, + {"title", NULL, NULL, 0, 0, {}, FLAG_TITLE, "NAME ...", + "Start a new boot entry, and set its name to the contents of the" + " rest of the line, starting with the first non-space character."}, + {"unhide", "parttool '%s' hidden-\n", NULL, 0, + 1, {TYPE_PARTITION}, 0, "PARTITION", + "Unhide PARTITION by clearing the \"hidden\" bit in its" + " partition type code."}, + /* FIXME: uppermem unsupported. */ + {"uuid", "search --set=root --fs-uuid '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, + 0, "UUID", "Find root by UUID"}, + {"vbeprobe", "insmod vbe; videoinfo '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, + FLAG_FALLBACK_AVAILABLE, "[MODE]", + "Probe VBE information. If the mode number MODE is specified, show only" + " the information about only the mode."}, + {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL} + }; + +char * +grub_legacy_escape (const char *in, grub_size_t len) +{ + const char *ptr; + char *ret, *outptr; + int overhead = 0; + for (ptr = in; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'') + overhead += 3; + ret = grub_malloc (ptr - in + overhead + 1); + if (!ret) + return NULL; + outptr = ret; + for (ptr = in; ptr < in + len && *ptr; ptr++) + { + if (*ptr == '\'') + { + *outptr++ = '\''; + *outptr++ = '\\'; + *outptr++ = '\''; + *outptr++ = '\''; + continue; + } + + *outptr++ = *ptr; + } + *outptr++ = 0; + return ret; +} + +static char * +adjust_file (const char *in, grub_size_t len) +{ + const char *comma, *ptr, *rest; + char *ret, *outptr; + int overhead = 0; + int part = -1, subpart = -1; + if (in[0] != '(') + return grub_legacy_escape (in, len); + for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' + && *ptr != ','; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + comma = ptr; + if (*comma != ',') + return grub_legacy_escape (in, len); + part = grub_strtoull (comma + 1, (char **) &rest, 0); + if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') + { + subpart = rest[1] - 'a'; + rest += 2; + } + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + /* 35 is enough for any 2 numbers. */ + ret = grub_malloc (ptr - in + overhead + 35); + if (!ret) + return NULL; + + outptr = ret; + for (ptr = in; ptr < in + len && ptr <= comma; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + if (subpart != -1) + grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); + else + grub_snprintf (outptr, 35, "%d", part + 1); + while (*outptr) + outptr++; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr = 0; + return ret; +} + +static int +check_option (const char *a, char *b, grub_size_t len) +{ + if (grub_strlen (b) != len) + return 0; + return grub_strncmp (a, b, len) == 0; +} + +static int +is_option (enum arg_type opt, const char *curarg, grub_size_t len) +{ + switch (opt) + { + case TYPE_NOAPM_OPTION: + return check_option (curarg, "--no-apm", len); + case TYPE_FORCE_OPTION: + return check_option (curarg, "--force", len); + case TYPE_TYPE_OR_NOMEM_OPTION: + return check_option (curarg, "--type=netbsd", len) + || check_option (curarg, "--type=freebsd", len) + || check_option (curarg, "--type=openbsd", len) + || check_option (curarg, "--type=linux", len) + || check_option (curarg, "--type=biglinux", len) + || check_option (curarg, "--type=multiboot", len) + || check_option (curarg, "--no-mem-option", len); + case TYPE_OPTION: + return (len >= 2 && curarg[0] == '-' && curarg[1] == '-'); + default: + return 0; + } +} + +char * +grub_legacy_parse (const char *buf, char **entryname, char **suffix) +{ + const char *ptr; + const char *cmdname; + unsigned i, cmdnum; + char *args[ARRAY_SIZE (legacy_commands[0].argt)]; + + *suffix = NULL; + + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); + if (!*ptr || *ptr == '#') + { + char *ret; + int len = grub_strlen (buf); + ret = grub_malloc (len + 2); + grub_memcpy (ret, buf, len); + if (len && ret[len - 1] == '\n') + ret[len] = 0; + else + { + ret[len] = '\n'; + ret[len + 1] = 0; + } + return ret; + } + + cmdname = ptr; + for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); + + for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) + if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 + && legacy_commands[cmdnum].name[ptr - cmdname] == 0 + && (!(*entryname != NULL && (legacy_commands[cmdnum].flags + & FLAG_NO_MENUENTRY))) + && (!(*entryname == NULL && (legacy_commands[cmdnum].flags + & FLAG_MENUENTRY_ONLY)))) + break; + if (cmdnum == ARRAY_SIZE (legacy_commands)) + return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); + + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + + if (legacy_commands[cmdnum].flags & FLAG_TITLE) + { + const char *ptr2; + ptr2 = ptr + grub_strlen (ptr); + while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) + ptr2--; + *entryname = grub_strndup (ptr, ptr2 - ptr); + return NULL; + } + + if (legacy_commands[cmdnum].flags & FLAG_TERMINAL) + { + int dumb = 0, lines = 24; +#ifdef TODO + int no_echo = 0, no_edit = 0; + int hercules = 0; +#endif + int console = 0, serial = 0; + /* Big enough for any possible resulting command. */ + char outbuf[256] = ""; + char *outptr; + while (*ptr) + { + /* "[--timeout=SECS] [--silent]" + " [console] [serial] [hercules]"*/ + if (grub_memcmp (ptr, "--dumb", sizeof ("--dumb") - 1) == 0) + dumb = 1; +#ifdef TODO + if (grub_memcmp (ptr, "--no-echo", sizeof ("--no-echo") - 1) == 0) + no_echo = 1; + + if (grub_memcmp (ptr, "--no-edit", sizeof ("--no-edit") - 1) == 0) + no_edit = 1; +#endif + if (grub_memcmp (ptr, "--lines=", sizeof ("--lines=") - 1) == 0) + { + lines = grub_strtoul (ptr + sizeof ("--lines=") - 1, 0, 0); + if (grub_errno) + { + lines = 24; + grub_errno = GRUB_ERR_NONE; + } + } + + if (grub_memcmp (ptr, "console", sizeof ("console") - 1) == 0) + console = 1; + + if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) + serial = 1; +#ifdef TODO + if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) + hercules = 1; +#endif + while (*ptr && !grub_isspace (*ptr)) + ptr++; + while (*ptr && grub_isspace (*ptr)) + ptr++; + } + + if (!console && !serial) + return grub_strdup ("terminal_input; terminal_output; terminfo\n"); + + grub_strcpy (outbuf, "terminal_input "); + outptr = outbuf + grub_strlen (outbuf); + if (serial) + { + grub_strcpy (outptr, "serial "); + outptr += grub_strlen (outptr); + } + if (console) + { + grub_strcpy (outptr, "console "); + outptr += grub_strlen (outptr); + } + grub_strcpy (outptr, "; terminal_output "); + outptr += grub_strlen (outptr); + 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, + "terminfo serial -g 80x%d %s; ", + lines, dumb ? "dumb" : "vt100"); + outptr += grub_strlen (outptr); + } + + grub_strcpy (outptr, "\n"); + + return grub_strdup (outbuf); + } + + grub_memset (args, 0, sizeof (args)); + + { + int hold_arg = 0; + const char *curarg = NULL; + for (i = 0; i < legacy_commands[cmdnum].argc; i++) + { + grub_size_t curarglen; + if (hold_arg) + { + ptr = curarg; + hold_arg = 0; + } + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + if (!*curarg) + break; + for (; *ptr && !grub_isspace (*ptr); ptr++); + if (i != legacy_commands[cmdnum].argc - 1 + || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) + curarglen = ptr - curarg; + else + { + curarglen = grub_strlen (curarg); + while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) + curarglen--; + } + if (*ptr) + ptr++; + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + hold_arg = 1; + case TYPE_PARTITION: + case TYPE_FILE: + args[i] = adjust_file (curarg, curarglen); + break; + + case TYPE_REST_VERBATIM: + { + char *outptr, *outptr0; + int overhead = 3; + ptr = curarg; + while (*ptr) + { + for (; *ptr && grub_isspace (*ptr); ptr++); + for (; *ptr && !grub_isspace (*ptr); ptr++) + if (*ptr == '\'') + overhead += 3; + if (*ptr) + ptr++; + overhead += 3; + } + + outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); + if (!outptr0) + return NULL; + ptr = curarg; + outptr = outptr0; + while (*ptr) + { + for (; *ptr && grub_isspace (*ptr); ptr++); + if (outptr != outptr0) + *outptr++ = ' '; + *outptr++ = '\''; + for (; *ptr && !grub_isspace (*ptr); ptr++) + { + if (*ptr == '\'') + { + *outptr++ = '\''; + *outptr++ = '\\'; + *outptr++ = '\''; + *outptr++ = '\''; + } + else + *outptr++ = *ptr; + } + *outptr++ = '\''; + if (*ptr) + ptr++; + } + *outptr++ = 0; + } + break; + + case TYPE_VERBATIM: + args[i] = grub_legacy_escape (curarg, curarglen); + break; + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) + { + args[i] = grub_strndup (curarg, curarglen); + break; + } + args[i] = grub_strdup (""); + hold_arg = 1; + break; + case TYPE_INT: + { + const char *brk; + int base = 10; + brk = curarg; + if (brk[0] == '0' && brk[1] == 'x') + base = 16; + else if (brk[0] == '0') + base = 8; + for (; *brk && brk < curarg + curarglen; brk++) + { + if (base == 8 && (*brk == '8' || *brk == '9')) + break; + if (grub_isdigit (*brk)) + continue; + if (base != 16) + break; + if (!(*brk >= 'a' && *brk <= 'f') + && !(*brk >= 'A' && *brk <= 'F')) + break; + } + if (brk == curarg) + args[i] = grub_strdup ("0"); + else + args[i] = grub_strndup (curarg, brk - curarg); + } + break; + case TYPE_VBE_MODE: + { + unsigned mod; + struct grub_vesa_mode_table_entry *modedesc; + + mod = grub_strtoul (curarg, 0, 0); + if (grub_errno) + { + mod = 0; + grub_errno = GRUB_ERR_NONE; + } + if (mod < GRUB_VESA_MODE_TABLE_START + || mod > GRUB_VESA_MODE_TABLE_END) + { + args[i] = grub_strdup ("auto"); + break; + } + modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; + if (!modedesc->width) + { + args[i] = grub_strdup ("auto"); + break; + } + args[i] = grub_xasprintf ("%ux%ux%u", + modedesc->width, modedesc->height, + modedesc->depth); + break; + } + case TYPE_BOOL: + if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') + args[i] = grub_strdup ("1"); + else + args[i] = grub_strdup ("0"); + break; + } + } + } + + while (legacy_commands[cmdnum].argc > 0 + && args[legacy_commands[cmdnum].argc - 1] == NULL + && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) + && args[legacy_commands[cmdnum + 1].argc] == NULL) + cmdnum++; + + for (; i < legacy_commands[cmdnum].argc; i++) + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + case TYPE_PARTITION: + case TYPE_FILE: + case TYPE_REST_VERBATIM: + case TYPE_VERBATIM: + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + args[i] = grub_strdup (""); + break; + case TYPE_BOOL: + case TYPE_INT: + args[i] = grub_strdup ("0"); + break; + case TYPE_VBE_MODE: + args[i] = grub_strdup ("auto"); + break; + } + + if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) + { + char *corig = args[legacy_commands[cmdnum].argc - 1]; + char *slash = grub_strchr (corig, '/'); + char *invert; + grub_size_t len; + + len = grub_strlen (corig); + if (!slash) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "bad color specification %s", + args[0]); + return NULL; + } + invert = grub_malloc (len + 1); + if (!invert) + return NULL; + grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); + invert[len - (slash - args[0]) - 1] = '/'; + grub_memcpy (invert + len - (slash - corig), corig, slash - corig); + invert[len] = 0; + args[legacy_commands[cmdnum].argc] = invert; + } + + if (legacy_commands[cmdnum].suffix) + { + *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, + args[legacy_commands[cmdnum].suffixarg]); + if (*suffix) + return NULL; + } + + { + char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], + args[2], args[3]); + grub_free (args[0]); + grub_free (args[1]); + grub_free (args[2]); + grub_free (args[3]); + return ret; + } +} diff --git a/lib/libgcrypt/cipher/ChangeLog b/grub-core/lib/libgcrypt/cipher/ChangeLog similarity index 100% rename from lib/libgcrypt/cipher/ChangeLog rename to grub-core/lib/libgcrypt/cipher/ChangeLog diff --git a/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c similarity index 100% rename from lib/libgcrypt/cipher/ac.c rename to grub-core/lib/libgcrypt/cipher/ac.c diff --git a/lib/libgcrypt/cipher/arcfour.c b/grub-core/lib/libgcrypt/cipher/arcfour.c similarity index 100% rename from lib/libgcrypt/cipher/arcfour.c rename to grub-core/lib/libgcrypt/cipher/arcfour.c diff --git a/lib/libgcrypt/cipher/bithelp.h b/grub-core/lib/libgcrypt/cipher/bithelp.h similarity index 100% rename from lib/libgcrypt/cipher/bithelp.h rename to grub-core/lib/libgcrypt/cipher/bithelp.h diff --git a/lib/libgcrypt/cipher/blowfish.c b/grub-core/lib/libgcrypt/cipher/blowfish.c similarity index 100% rename from lib/libgcrypt/cipher/blowfish.c rename to grub-core/lib/libgcrypt/cipher/blowfish.c diff --git a/lib/libgcrypt/cipher/camellia-glue.c b/grub-core/lib/libgcrypt/cipher/camellia-glue.c similarity index 100% rename from lib/libgcrypt/cipher/camellia-glue.c rename to grub-core/lib/libgcrypt/cipher/camellia-glue.c diff --git a/lib/libgcrypt/cipher/camellia.c b/grub-core/lib/libgcrypt/cipher/camellia.c similarity index 100% rename from lib/libgcrypt/cipher/camellia.c rename to grub-core/lib/libgcrypt/cipher/camellia.c diff --git a/lib/libgcrypt/cipher/camellia.h b/grub-core/lib/libgcrypt/cipher/camellia.h similarity index 100% rename from lib/libgcrypt/cipher/camellia.h rename to grub-core/lib/libgcrypt/cipher/camellia.h diff --git a/lib/libgcrypt/cipher/cast5.c b/grub-core/lib/libgcrypt/cipher/cast5.c similarity index 100% rename from lib/libgcrypt/cipher/cast5.c rename to grub-core/lib/libgcrypt/cipher/cast5.c diff --git a/lib/libgcrypt/cipher/cipher.c b/grub-core/lib/libgcrypt/cipher/cipher.c similarity index 100% rename from lib/libgcrypt/cipher/cipher.c rename to grub-core/lib/libgcrypt/cipher/cipher.c diff --git a/lib/libgcrypt/cipher/crc.c b/grub-core/lib/libgcrypt/cipher/crc.c similarity index 100% rename from lib/libgcrypt/cipher/crc.c rename to grub-core/lib/libgcrypt/cipher/crc.c diff --git a/lib/libgcrypt/cipher/des.c b/grub-core/lib/libgcrypt/cipher/des.c similarity index 100% rename from lib/libgcrypt/cipher/des.c rename to grub-core/lib/libgcrypt/cipher/des.c diff --git a/lib/libgcrypt/cipher/dsa.c b/grub-core/lib/libgcrypt/cipher/dsa.c similarity index 100% rename from lib/libgcrypt/cipher/dsa.c rename to grub-core/lib/libgcrypt/cipher/dsa.c diff --git a/lib/libgcrypt/cipher/ecc.c b/grub-core/lib/libgcrypt/cipher/ecc.c similarity index 100% rename from lib/libgcrypt/cipher/ecc.c rename to grub-core/lib/libgcrypt/cipher/ecc.c diff --git a/lib/libgcrypt/cipher/elgamal.c b/grub-core/lib/libgcrypt/cipher/elgamal.c similarity index 100% rename from lib/libgcrypt/cipher/elgamal.c rename to grub-core/lib/libgcrypt/cipher/elgamal.c diff --git a/lib/libgcrypt/cipher/hash-common.c b/grub-core/lib/libgcrypt/cipher/hash-common.c similarity index 100% rename from lib/libgcrypt/cipher/hash-common.c rename to grub-core/lib/libgcrypt/cipher/hash-common.c diff --git a/lib/libgcrypt/cipher/hash-common.h b/grub-core/lib/libgcrypt/cipher/hash-common.h similarity index 100% rename from lib/libgcrypt/cipher/hash-common.h rename to grub-core/lib/libgcrypt/cipher/hash-common.h diff --git a/lib/libgcrypt/cipher/hmac-tests.c b/grub-core/lib/libgcrypt/cipher/hmac-tests.c similarity index 100% rename from lib/libgcrypt/cipher/hmac-tests.c rename to grub-core/lib/libgcrypt/cipher/hmac-tests.c diff --git a/lib/libgcrypt/cipher/md.c b/grub-core/lib/libgcrypt/cipher/md.c similarity index 100% rename from lib/libgcrypt/cipher/md.c rename to grub-core/lib/libgcrypt/cipher/md.c diff --git a/lib/libgcrypt/cipher/md4.c b/grub-core/lib/libgcrypt/cipher/md4.c similarity index 100% rename from lib/libgcrypt/cipher/md4.c rename to grub-core/lib/libgcrypt/cipher/md4.c diff --git a/lib/libgcrypt/cipher/md5.c b/grub-core/lib/libgcrypt/cipher/md5.c similarity index 100% rename from lib/libgcrypt/cipher/md5.c rename to grub-core/lib/libgcrypt/cipher/md5.c diff --git a/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c similarity index 100% rename from lib/libgcrypt/cipher/primegen.c rename to grub-core/lib/libgcrypt/cipher/primegen.c diff --git a/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c similarity index 100% rename from lib/libgcrypt/cipher/pubkey.c rename to grub-core/lib/libgcrypt/cipher/pubkey.c diff --git a/lib/libgcrypt/cipher/rfc2268.c b/grub-core/lib/libgcrypt/cipher/rfc2268.c similarity index 100% rename from lib/libgcrypt/cipher/rfc2268.c rename to grub-core/lib/libgcrypt/cipher/rfc2268.c diff --git a/lib/libgcrypt/cipher/rijndael-tables.h b/grub-core/lib/libgcrypt/cipher/rijndael-tables.h similarity index 100% rename from lib/libgcrypt/cipher/rijndael-tables.h rename to grub-core/lib/libgcrypt/cipher/rijndael-tables.h diff --git a/lib/libgcrypt/cipher/rijndael.c b/grub-core/lib/libgcrypt/cipher/rijndael.c similarity index 100% rename from lib/libgcrypt/cipher/rijndael.c rename to grub-core/lib/libgcrypt/cipher/rijndael.c diff --git a/lib/libgcrypt/cipher/rmd.h b/grub-core/lib/libgcrypt/cipher/rmd.h similarity index 100% rename from lib/libgcrypt/cipher/rmd.h rename to grub-core/lib/libgcrypt/cipher/rmd.h diff --git a/lib/libgcrypt/cipher/rmd160.c b/grub-core/lib/libgcrypt/cipher/rmd160.c similarity index 100% rename from lib/libgcrypt/cipher/rmd160.c rename to grub-core/lib/libgcrypt/cipher/rmd160.c diff --git a/lib/libgcrypt/cipher/rsa.c b/grub-core/lib/libgcrypt/cipher/rsa.c similarity index 100% rename from lib/libgcrypt/cipher/rsa.c rename to grub-core/lib/libgcrypt/cipher/rsa.c diff --git a/lib/libgcrypt/cipher/seed.c b/grub-core/lib/libgcrypt/cipher/seed.c similarity index 100% rename from lib/libgcrypt/cipher/seed.c rename to grub-core/lib/libgcrypt/cipher/seed.c diff --git a/lib/libgcrypt/cipher/serpent.c b/grub-core/lib/libgcrypt/cipher/serpent.c similarity index 100% rename from lib/libgcrypt/cipher/serpent.c rename to grub-core/lib/libgcrypt/cipher/serpent.c diff --git a/lib/libgcrypt/cipher/sha1.c b/grub-core/lib/libgcrypt/cipher/sha1.c similarity index 100% rename from lib/libgcrypt/cipher/sha1.c rename to grub-core/lib/libgcrypt/cipher/sha1.c diff --git a/lib/libgcrypt/cipher/sha256.c b/grub-core/lib/libgcrypt/cipher/sha256.c similarity index 100% rename from lib/libgcrypt/cipher/sha256.c rename to grub-core/lib/libgcrypt/cipher/sha256.c diff --git a/lib/libgcrypt/cipher/sha512.c b/grub-core/lib/libgcrypt/cipher/sha512.c similarity index 100% rename from lib/libgcrypt/cipher/sha512.c rename to grub-core/lib/libgcrypt/cipher/sha512.c diff --git a/lib/libgcrypt/cipher/tiger.c b/grub-core/lib/libgcrypt/cipher/tiger.c similarity index 100% rename from lib/libgcrypt/cipher/tiger.c rename to grub-core/lib/libgcrypt/cipher/tiger.c diff --git a/lib/libgcrypt/cipher/twofish.c b/grub-core/lib/libgcrypt/cipher/twofish.c similarity index 100% rename from lib/libgcrypt/cipher/twofish.c rename to grub-core/lib/libgcrypt/cipher/twofish.c diff --git a/lib/libgcrypt/cipher/whirlpool.c b/grub-core/lib/libgcrypt/cipher/whirlpool.c similarity index 100% rename from lib/libgcrypt/cipher/whirlpool.c rename to grub-core/lib/libgcrypt/cipher/whirlpool.c diff --git a/lib/libgcrypt_wrap/cipher_wrap.h b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h similarity index 95% rename from lib/libgcrypt_wrap/cipher_wrap.h rename to grub-core/lib/libgcrypt_wrap/cipher_wrap.h index b4530c112..59febaeb5 100644 --- a/lib/libgcrypt_wrap/cipher_wrap.h +++ b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h @@ -25,6 +25,12 @@ #include #include +#ifdef GRUB_CPU_WORDS_BIGENDIAN +#define WORDS_BIGENDIAN +#else +#undef WORDS_BIGENDIAN +#endif + #define __GNU_LIBRARY__ #define DIM ARRAY_SIZE diff --git a/grub-core/lib/mips/relocator.c b/grub-core/lib/mips/relocator.c new file mode 100644 index 000000000..537b0af2c --- /dev/null +++ b/grub-core/lib/mips/relocator.c @@ -0,0 +1,149 @@ +/* + * 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 + +#include +#include + +/* Do we need mips64? */ + +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; + +#define REGW_SIZEOF (2 * sizeof (grub_uint32_t)) +#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t)) + +#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \ + - &grub_relocator_##x##_start) +#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ + + REGW_SIZEOF * 3) +grub_size_t grub_relocator_align = sizeof (grub_uint32_t); +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF; + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF(forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF(backward); +} + +static void +write_reg (int regn, grub_uint32_t val, void **target) +{ + /* lui $r, (val+0x8000). */ + *(grub_uint32_t *) *target = ((0x3c00 | regn) << 16) | ((val + 0x8000) >> 16); + *target = ((grub_uint32_t *) *target) + 1; + /* addiu $r, $r, val. */ + *(grub_uint32_t *) *target = (((0x2400 | regn << 5 | regn) << 16) + | (val & 0xffff)); + *target = ((grub_uint32_t *) *target) + 1; +} + +static void +write_jump (int regn, void **target) +{ + /* j $r. */ + *(grub_uint32_t *) *target = (regn<<21) | 0x8; + *target = ((grub_uint32_t *) *target) + 1; + /* nop. */ + *(grub_uint32_t *) *target = 0; + *target = ((grub_uint32_t *) *target) + 1; +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + write_reg (1, addr, &rels); + write_jump (1, &rels); +} + +void +grub_cpu_relocator_backward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_backward_start, + RELOCATOR_SRC_SIZEOF (backward)); +} + +void +grub_cpu_relocator_forward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_forward_start, + RELOCATOR_SRC_SIZEOF (forward)); +} + +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state) +{ + grub_relocator_chunk_t ch; + void *ptr; + grub_err_t err; + void *relst; + grub_size_t relsize; + grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF; + unsigned i; + grub_addr_t vtarget; + + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, + (0xffffffff - stateset_size) + + 1, stateset_size, + sizeof (grub_uint32_t), + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + + ptr = get_virtual_current_address (ch); + for (i = 1; i < 32; i++) + write_reg (i, state.gpr[i], &ptr); + write_jump (state.jumpreg, &ptr); + + vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch), + stateset_size); + + err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize); + if (err) + return err; + + grub_arch_sync_caches ((void *) relst, relsize); + + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/lib/mips/relocator_asm.S b/grub-core/lib/mips/relocator_asm.S similarity index 77% rename from lib/mips/relocator_asm.S rename to grub-core/lib/mips/relocator_asm.S index ff4fa31e0..1d142a4f3 100644 --- a/lib/mips/relocator_asm.S +++ b/grub-core/lib/mips/relocator_asm.S @@ -20,39 +20,42 @@ .p2align 4 /* force 16-byte alignment */ -VARIABLE (grub_relocator32_forward_start) + .set noreorder + .set nomacro + +VARIABLE (grub_relocator_forward_start) move $a0, $9 move $a1, $10 copycont1: lb $11,0($8) sb $11,0($9) - addiu $8, $8, 0x1 - addiu $9, $9, 0x1 - addiu $10, $10, 0xffff + addiu $8, $8, 1 + addiu $10, $10, -1 bne $10, $0, copycont1 + addiu $9, $9, 1 #include "../../kern/mips/cache_flush.S" -VARIABLE (grub_relocator32_forward_end) +VARIABLE (grub_relocator_forward_end) -VARIABLE (grub_relocator32_backward_start) +VARIABLE (grub_relocator_backward_start) move $a0, $9 move $a1, $10 addu $9, $9, $10 addu $8, $8, $10 /* Backward movsl is implicitly off-by-one. compensate that. */ - addiu $9, $9, 0xffff - addiu $8, $8, 0xffff + addiu $9, $9, -1 + addiu $8, $8, -1 copycont2: lb $11,0($8) sb $11,0($9) - addiu $8, $8, 0xffff - addiu $9, $9, 0xffff - addiu $10, 0xffff + addiu $8, $8, -1 + addiu $10, $10, -1 bne $10, $0, copycont2 + addiu $9, $9, -1 #include "../../kern/mips/cache_flush.S" -VARIABLE (grub_relocator32_backward_end) +VARIABLE (grub_relocator_backward_end) diff --git a/lib/mips/setjmp.S b/grub-core/lib/mips/setjmp.S similarity index 100% rename from lib/mips/setjmp.S rename to grub-core/lib/mips/setjmp.S diff --git a/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c similarity index 100% rename from lib/pbkdf2.c rename to grub-core/lib/pbkdf2.c diff --git a/lib/posix_wrap/assert.h b/grub-core/lib/posix_wrap/assert.h similarity index 100% rename from lib/posix_wrap/assert.h rename to grub-core/lib/posix_wrap/assert.h diff --git a/lib/posix_wrap/ctype.h b/grub-core/lib/posix_wrap/ctype.h similarity index 100% rename from lib/posix_wrap/ctype.h rename to grub-core/lib/posix_wrap/ctype.h diff --git a/lib/posix_wrap/errno.h b/grub-core/lib/posix_wrap/errno.h similarity index 100% rename from lib/posix_wrap/errno.h rename to grub-core/lib/posix_wrap/errno.h diff --git a/lib/posix_wrap/langinfo.h b/grub-core/lib/posix_wrap/langinfo.h similarity index 96% rename from lib/posix_wrap/langinfo.h rename to grub-core/lib/posix_wrap/langinfo.h index 14833c0b8..72b5b9612 100644 --- a/lib/posix_wrap/langinfo.h +++ b/grub-core/lib/posix_wrap/langinfo.h @@ -29,7 +29,7 @@ nl_langinfo (nl_item item) switch (item) { case CODESET: - return locale_charset (); + return "UTF-8"; default: return ""; } diff --git a/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h similarity index 100% rename from lib/posix_wrap/limits.h rename to grub-core/lib/posix_wrap/limits.h diff --git a/lib/posix_wrap/localcharset.h b/grub-core/lib/posix_wrap/localcharset.h similarity index 96% rename from lib/posix_wrap/localcharset.h rename to grub-core/lib/posix_wrap/localcharset.h index 92eb815ec..502d86066 100644 --- a/lib/posix_wrap/localcharset.h +++ b/grub-core/lib/posix_wrap/localcharset.h @@ -19,7 +19,7 @@ #ifndef GRUB_POSIX_LOCALCHARSET_H #define GRUB_POSIX_LOCALCHARSET_H 1 -static inline char * +static inline const char * locale_charset (void) { return "UTF-8"; diff --git a/lib/posix_wrap/locale.h b/grub-core/lib/posix_wrap/locale.h similarity index 100% rename from lib/posix_wrap/locale.h rename to grub-core/lib/posix_wrap/locale.h diff --git a/lib/posix_wrap/stdint.h b/grub-core/lib/posix_wrap/stdint.h similarity index 100% rename from lib/posix_wrap/stdint.h rename to grub-core/lib/posix_wrap/stdint.h diff --git a/lib/posix_wrap/stdio.h b/grub-core/lib/posix_wrap/stdio.h similarity index 100% rename from lib/posix_wrap/stdio.h rename to grub-core/lib/posix_wrap/stdio.h diff --git a/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h similarity index 98% rename from lib/posix_wrap/stdlib.h rename to grub-core/lib/posix_wrap/stdlib.h index 5ef6159ef..4c725f6e2 100644 --- a/lib/posix_wrap/stdlib.h +++ b/grub-core/lib/posix_wrap/stdlib.h @@ -20,6 +20,7 @@ #define GRUB_POSIX_STDLIB_H 1 #include +#include static inline void free (void *ptr) diff --git a/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h similarity index 97% rename from lib/posix_wrap/string.h rename to grub-core/lib/posix_wrap/string.h index 7bb6f1e6f..4224836e2 100644 --- a/lib/posix_wrap/string.h +++ b/grub-core/lib/posix_wrap/string.h @@ -19,6 +19,8 @@ #ifndef GRUB_POSIX_STRING_H #define GRUB_POSIX_STRING_H 1 +#include + static inline grub_size_t strlen (const char *s) { diff --git a/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h similarity index 77% rename from lib/posix_wrap/sys/types.h rename to grub-core/lib/posix_wrap/sys/types.h index ce3794087..4e8331fdd 100644 --- a/lib/posix_wrap/sys/types.h +++ b/grub-core/lib/posix_wrap/sys/types.h @@ -22,11 +22,20 @@ #include typedef grub_size_t size_t; -typedef int bool; -static const bool true = 1; -static const bool false = 0; +typedef enum { false = 0, true = 1 } bool; #define ULONG_MAX GRUB_ULONG_MAX #define UCHAR_MAX 0xff +typedef grub_uint8_t uint8_t; +typedef grub_uint16_t uint16_t; +typedef grub_uint32_t uint32_t; +typedef grub_uint64_t uint64_t; + +#ifdef GRUB_CPU_WORDS_BIGENDIAN +#define WORDS_BIGENDIAN +#else +#undef WORDS_BIGENDIAN +#endif + #endif diff --git a/lib/posix_wrap/unistd.h b/grub-core/lib/posix_wrap/unistd.h similarity index 100% rename from lib/posix_wrap/unistd.h rename to grub-core/lib/posix_wrap/unistd.h diff --git a/lib/posix_wrap/wchar.h b/grub-core/lib/posix_wrap/wchar.h similarity index 100% rename from lib/posix_wrap/wchar.h rename to grub-core/lib/posix_wrap/wchar.h diff --git a/lib/posix_wrap/wctype.h b/grub-core/lib/posix_wrap/wctype.h similarity index 100% rename from lib/posix_wrap/wctype.h rename to grub-core/lib/posix_wrap/wctype.h diff --git a/grub-core/lib/powerpc/relocator.c b/grub-core/lib/powerpc/relocator.c new file mode 100644 index 000000000..85dfbeaf3 --- /dev/null +++ b/grub-core/lib/powerpc/relocator.c @@ -0,0 +1,142 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + +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; + +#define REGW_SIZEOF (2 * sizeof (grub_uint32_t)) +#define JUMP_SIZEOF (sizeof (grub_uint32_t)) + +#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \ + - &grub_relocator_##x##_start) +#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ + + REGW_SIZEOF * 3) +grub_size_t grub_relocator_align = sizeof (grub_uint32_t); +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF; + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF(forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF(backward); +} + +static void +write_reg (int regn, grub_uint32_t val, void **target) +{ + /* lis r, val >> 16 */ + *(grub_uint32_t *) *target = + ((0x3c00 | (regn << 5)) << 16) | (val >> 16); + *target = ((grub_uint32_t *) *target) + 1; + /* ori r, r, val & 0xffff. */ + *(grub_uint32_t *) *target = (((0x6000 | regn << 5 | regn) << 16) + | (val & 0xffff)); + *target = ((grub_uint32_t *) *target) + 1; +} + +static void +write_jump (void **target) +{ + /* blr. */ + *(grub_uint32_t *) *target = 0x4e800020; + *target = ((grub_uint32_t *) *target) + 1; +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + write_reg (GRUB_PPC_JUMP_REGISTER, addr, &rels); + write_jump (&rels); +} + +void +grub_cpu_relocator_backward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_backward_start, + RELOCATOR_SRC_SIZEOF (backward)); +} + +void +grub_cpu_relocator_forward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_forward_start, + RELOCATOR_SRC_SIZEOF (forward)); +} + +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state) +{ + void *ptr; + grub_err_t err; + void *relst; + grub_size_t relsize; + grub_size_t stateset_size = 32 * REGW_SIZEOF + JUMP_SIZEOF; + unsigned i; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, + (0xffffffff - stateset_size) + + 1, stateset_size, + sizeof (grub_uint32_t), + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + + ptr = get_virtual_current_address (ch); + for (i = 0; i < 32; i++) + write_reg (i, state.gpr[i], &ptr); + write_jump (&ptr); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, &relsize); + if (err) + return err; + + grub_arch_sync_caches ((void *) relst, relsize); + + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/powerpc/relocator_asm.S b/grub-core/lib/powerpc/relocator_asm.S new file mode 100644 index 000000000..355e9c8b4 --- /dev/null +++ b/grub-core/lib/powerpc/relocator_asm.S @@ -0,0 +1,60 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE (grub_relocator_forward_start) + mr 3, 9 + mr 4, 10 + +copycont1: + lbz 11,0(8) + stb 11,0(9) + addi 8, 8, 0x1 + addi 9, 9, 0x1 + addi 10, 10, -1 + cmpwi 10, 0 + bne copycont1 + +#include "../../kern/powerpc/cache_flush.S" + +VARIABLE (grub_relocator_forward_end) + +VARIABLE (grub_relocator_backward_start) + mr 3, 9 + mr 4, 10 + + add 9, 9, 10 + add 8, 8, 10 + /* Backward movsl is implicitly off-by-one. compensate that. */ + addi 9, 9, -1 + addi 8, 8, -1 +copycont2: + lbz 11,0(8) + stb 11,0(9) + addi 8, 8, -1 + addi 9, 9, -1 + addi 10, 10, -1 + cmpwi 10, 0 + bne copycont2 + +#include "../../kern/powerpc/cache_flush.S" + +VARIABLE (grub_relocator_backward_end) diff --git a/lib/powerpc/setjmp.S b/grub-core/lib/powerpc/setjmp.S similarity index 100% rename from lib/powerpc/setjmp.S rename to grub-core/lib/powerpc/setjmp.S diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c new file mode 100644 index 000000000..4c6e160e4 --- /dev/null +++ b/grub-core/lib/reed_solomon.c @@ -0,0 +1,518 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#ifdef TEST +#include +#define xmalloc malloc +#define grub_memset memset +#define grub_memcpy memcpy +#endif + +#ifndef STANDALONE +#ifdef TEST +#include +#include +typedef unsigned int grub_size_t; +typedef unsigned char grub_uint8_t; +typedef unsigned short grub_uint16_t; +#else +#include +#include +#include +#include +#endif +#endif + +#ifdef STANDALONE +#ifdef TEST +typedef unsigned int grub_size_t; +typedef unsigned char grub_uint8_t; +typedef unsigned short grub_uint16_t; +#else +#include +#endif +void +grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs); +#endif + +#define GF_SIZE 8 +typedef grub_uint8_t gf_single_t; +typedef grub_uint16_t gf_double_t; +#define GF_POLYNOMIAL 0x1d +#define GF_INVERT2 0x8e +#if defined (STANDALONE) && !defined (TEST) +static char *gf_invert __attribute__ ((section(".text"))) = (void *) 0x100000; +static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100100; +#else +static char *scratch; +static grub_uint8_t gf_invert[256]; +#endif + +#define SECTOR_SIZE 512 +#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE) + +static gf_single_t +gf_reduce (gf_double_t a) +{ + int i; + for (i = GF_SIZE - 1; i >= 0; i--) + if (a & (1ULL << (i + GF_SIZE))) + a ^= (((gf_double_t) GF_POLYNOMIAL) << i); + return a & ((1ULL << GF_SIZE) - 1); +} + +static gf_single_t +gf_mul (gf_single_t a, gf_single_t b) +{ + gf_double_t res = 0; + int i; + for (i = 0; i < GF_SIZE; i++) + if (b & (1 << i)) + res ^= ((gf_double_t) a) << i; + return gf_reduce (res); +} + +static void +init_inverts (void) +{ + gf_single_t a = 1, ai = 1; + do + { + a = gf_mul (a, 2); + ai = gf_mul (ai, GF_INVERT2); + gf_invert[a] = ai; + } + while (a != 1); +} + +static gf_single_t +pol_evaluate (gf_single_t *pol, grub_size_t degree, gf_single_t x) +{ + int i; + gf_single_t xn = 1, s = 0; + for (i = degree; i >= 0; i--) + { + s ^= gf_mul (pol[i], xn); + xn = gf_mul (x, xn); + } + return s; +} + +#if !defined (STANDALONE) +static void +rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) +{ + gf_single_t *rs_polynomial, a = 1; + int i, j; + gf_single_t *m; + m = xmalloc ((s + rs) * sizeof (gf_single_t)); + grub_memcpy (m, data, s * sizeof (gf_single_t)); + grub_memset (m + s, 0, rs * sizeof (gf_single_t)); + rs_polynomial = xmalloc ((rs + 1) * sizeof (gf_single_t)); + grub_memset (rs_polynomial, 0, (rs + 1) * sizeof (gf_single_t)); + rs_polynomial[rs] = 1; + /* Multiply with X - a^r */ + for (j = 0; j < rs; j++) + { + if (a & (1 << (GF_SIZE - 1))) + { + a <<= 1; + a ^= GF_POLYNOMIAL; + } + else + a <<= 1; + for (i = 0; i < rs; i++) + rs_polynomial[i] = rs_polynomial[i + 1] ^ gf_mul (a, rs_polynomial[i]); + rs_polynomial[rs] = gf_mul (a, rs_polynomial[rs]); + } + for (j = 0; j < s; j++) + if (m[j]) + { + gf_single_t f = m[j]; + for (i = 0; i <= rs; i++) + m[i+j] ^= gf_mul (rs_polynomial[i], f); + } + free (rs_polynomial); + grub_memcpy (data + s, m + s, rs * sizeof (gf_single_t)); + free (m); +} +#endif + +static void +syndroms (gf_single_t *m, grub_size_t s, grub_size_t rs, + gf_single_t *sy) +{ + gf_single_t xn = 1; + unsigned i; + for (i = 0; i < rs; i++) + { + if (xn & (1 << (GF_SIZE - 1))) + { + xn <<= 1; + xn ^= GF_POLYNOMIAL; + } + else + xn <<= 1; + sy[i] = pol_evaluate (m, s + rs - 1, xn); + } +} + +static void +gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen) +{ + int i, j; + + for (i = 0 ; i < n; i++) + { + int nzidx; + int k; + gf_single_t r; + for (nzidx = 0; nzidx < m && (eq[i * (m + 1) + nzidx] == 0); + nzidx++); + if (nzidx == m) + continue; + chosen[i] = nzidx; + r = gf_invert [eq[i * (m + 1) + nzidx]]; + for (j = 0; j < m + 1; j++) + eq[i * (m + 1) + j] = gf_mul (eq[i * (m + 1) + j], r); + for (j = i + 1; j < n; j++) + { + gf_single_t rr = eq[j * (m + 1) + nzidx]; + for (k = 0; k < m + 1; k++) + eq[j * (m + 1) + k] ^= gf_mul (eq[i * (m + 1) + k], rr); + } + } +} + +static void +gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol) +{ + int *chosen; + int i, j; + +#ifndef STANDALONE + chosen = xmalloc (n * sizeof (int)); + grub_memset (chosen, -1, n * sizeof (int)); +#else + chosen = (void *) scratch; + scratch += n; +#endif + for (i = 0; i < m; i++) + sol[i] = 0; + gauss_eliminate (eq, n, m, chosen); + for (i = n - 1; i >= 0; i--) + { + gf_single_t s = 0; + if (chosen[i] == -1) + continue; + for (j = 0; j < m; j++) + s ^= gf_mul (eq[i * (m + 1) + j], sol[j]); + s ^= eq[i * (m + 1) + m]; + sol[chosen[i]] = s; + } +#ifndef STANDALONE + free (chosen); +#else + scratch -= n; +#endif +} + +static void +rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) +{ + grub_size_t rs2 = rs / 2; + gf_single_t *sigma; + gf_single_t *errpot; + int *errpos; + gf_single_t *sy; + int errnum = 0; + int i, j; + +#ifndef STANDALONE + sigma = xmalloc (rs2 * sizeof (gf_single_t)); + errpot = xmalloc (rs2 * sizeof (gf_single_t)); + errpos = xmalloc (rs2 * sizeof (int)); + sy = xmalloc (rs * sizeof (gf_single_t)); +#else + sigma = (void *) scratch; + scratch += rs2 * sizeof (gf_single_t); + errpot = (void *) scratch; + scratch += rs2 * sizeof (gf_single_t); + errpos = (void *) scratch; + scratch += rs2 * sizeof (int); + sy = (void *) scratch; + scratch += rs * sizeof (gf_single_t); +#endif + + syndroms (m, s, rs, sy); + + { + gf_single_t *eq; + +#ifndef STANDALONE + eq = xmalloc (rs2 * (rs2 + 1) * sizeof (gf_single_t)); +#else + eq = (void *) scratch; + scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t); +#endif + + for (i = 0; i < (int) rs; i++) + if (sy[i] != 0) + break; + + /* No error detected. */ + if (i == (int) rs) + return; + + for (i = 0; i < (int) rs2; i++) + for (j = 0; j < (int) rs2 + 1; j++) + eq[i * (rs2 + 1) + j] = sy[i+j]; + + for (i = 0; i < (int) rs2; i++) + sigma[i] = 0; + + gauss_solve (eq, rs2, rs2, sigma); + +#ifndef STANDALONE + free (eq); +#else + scratch -= rs2 * (rs2 + 1) * sizeof (gf_single_t); +#endif + } + + { + gf_single_t xn = 1, yn = 1; + for (i = 0; i < (int) (rs + s); i++) + { + gf_single_t ev = (gf_mul (pol_evaluate (sigma, rs2 - 1, xn), xn) ^ 1); + if (ev == 0) + { + errpot[errnum] = yn; + errpos[errnum++] = s + rs - i - 1; + } + yn = gf_mul (yn, 2); + xn = gf_mul (xn, GF_INVERT2); + } + } + { + gf_single_t *errvals; + gf_single_t *eq; + +#ifndef STANDALONE + eq = xmalloc (rs * (errnum + 1) * sizeof (gf_single_t)); + errvals = xmalloc (errnum * sizeof (int)); +#else + eq = (void *) scratch; + scratch += rs * (errnum + 1) * sizeof (gf_single_t); + errvals = (void *) scratch; + scratch += errnum * sizeof (int); +#endif + + for (j = 0; j < errnum; j++) + eq[j] = errpot[j]; + eq[errnum] = sy[0]; + for (i = 1; i < (int) rs; i++) + { + for (j = 0; j < (int) errnum; j++) + eq[(errnum + 1) * i + j] = gf_mul (errpot[j], + eq[(errnum + 1) * (i - 1) + j]); + eq[(errnum + 1) * i + errnum] = sy[i]; + } + + gauss_solve (eq, rs, errnum, errvals); + + for (i = 0; i < (int) errnum; i++) + m[errpos[i]] ^= errvals[i]; +#ifndef STANDALONE + free (eq); + free (errvals); +#else + scratch -= rs * (errnum + 1) * sizeof (gf_single_t); + scratch -= errnum * sizeof (int); +#endif + } +#ifndef STANDALONE + free (sigma); + free (errpot); + free (errpos); + free (sy); +#else + scratch -= rs2 * sizeof (gf_single_t); + scratch -= rs2 * sizeof (gf_single_t); + scratch -= rs2 * sizeof (int); + scratch -= rs * sizeof (gf_single_t); +#endif +} + +static void +decode_block (gf_single_t *ptr, grub_size_t s, + gf_single_t *rptr, grub_size_t rs) +{ + int i, j; + for (i = 0; i < SECTOR_SIZE; i++) + { + grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + gf_single_t m[ds + rr]; + + for (j = 0; j < (int) ds; j++) + m[j] = ptr[SECTOR_SIZE * j + i]; + for (j = 0; j < (int) rr; j++) + m[j + ds] = rptr[SECTOR_SIZE * j + i]; + + rs_recover (m, ds, rr); + + for (j = 0; j < (int) ds; j++) + ptr[SECTOR_SIZE * j + i] = m[j]; + } +} + +#if !defined (STANDALONE) +static void +encode_block (gf_single_t *ptr, grub_size_t s, + gf_single_t *rptr, grub_size_t rs) +{ + int i, j; + for (i = 0; i < SECTOR_SIZE; i++) + { + grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + gf_single_t m[ds + rr]; + for (j = 0; j < ds; j++) + m[j] = ptr[SECTOR_SIZE * j + i]; + rs_encode (m, ds, rr); + for (j = 0; j < rr; j++) + rptr[SECTOR_SIZE * j + i] = m[j + ds]; + } +} +#endif + +#if !defined (STANDALONE) +void +grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, + grub_size_t redundancy) +{ + grub_size_t s = data_size; + grub_size_t rs = redundancy; + gf_single_t *ptr = buffer; + gf_single_t *rptr = ptr + s; + + while (s > 0) + { + grub_size_t tt; + grub_size_t cs, crs; + cs = s; + crs = rs; + tt = cs + crs; + if (tt > MAX_BLOCK_SIZE) + { + cs = (cs * MAX_BLOCK_SIZE) / tt; + crs = (crs * MAX_BLOCK_SIZE) / tt; + } + encode_block (ptr, cs, rptr, crs); + ptr += cs; + rptr += crs; + s -= cs; + rs -= crs; + } +} +#endif + +void +grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs) +{ + gf_single_t *ptr = ptr_; + gf_single_t *rptr = ptr + s; + +#if defined (STANDALONE) + init_inverts (); +#endif + + while (s > 0) + { + grub_size_t tt; + grub_size_t cs, crs; + cs = s; + crs = rs; + tt = cs + crs; + if (tt > MAX_BLOCK_SIZE) + { + cs = cs * MAX_BLOCK_SIZE / tt; + crs = crs * MAX_BLOCK_SIZE / tt; + } + decode_block (ptr, cs, rptr, crs); + ptr += cs; + rptr += crs; + s -= cs; + rs -= crs; + } +} + +#ifdef TEST +int +main (int argc, char **argv) +{ + FILE *in, *out; + grub_size_t s, rs; + char *buf; + +#ifdef STANDALONE + scratch = xmalloc (1048576); +#endif + +#ifndef STANDALONE + init_inverts (); +#endif + + in = fopen ("tst.bin", "rb"); + if (!in) + return 1; + fseek (in, 0, SEEK_END); + s = ftell (in); + fseek (in, 0, SEEK_SET); + rs = 1024 * ((s + MAX_BLOCK_SIZE - 1) / (MAX_BLOCK_SIZE - 1024)); + buf = xmalloc (s + rs + SECTOR_SIZE); + fread (buf, 1, s, in); + + s = 0x5fbb; + rs = 0x6af9; + +#if 0 + grub_reed_solomon_add_redundancy (buf, s, rs); + + out = fopen ("tst_rs.bin", "wb"); + fwrite (buf, 1, s + rs, out); + fclose (out); + + grub_memset (buf + 512 * 15, 0, 512); + + out = fopen ("tst_dam.bin", "wb"); + fwrite (buf, 1, s + rs, out); + fclose (out); +#endif + s = 0x5fbb; + rs = 0x6af9; + grub_reed_solomon_recover (buf, s, rs); + + out = fopen ("tst_rec.bin", "wb"); + fwrite (buf, 1, s, out); + fclose (out); + + return 0; +} +#endif diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c new file mode 100644 index 000000000..dbd5fe4d0 --- /dev/null +++ b/grub-core/lib/relocator.c @@ -0,0 +1,1616 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + +struct grub_relocator +{ + struct grub_relocator_chunk *chunks; + grub_phys_addr_t postchunks; + grub_phys_addr_t highestaddr; + grub_phys_addr_t highestnonpostaddr; + grub_size_t relocators_size; +}; + +struct grub_relocator_subchunk +{ + enum {CHUNK_TYPE_IN_REGION, CHUNK_TYPE_REGION_START, +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + CHUNK_TYPE_FIRMWARE, CHUNK_TYPE_LEFTOVER +#endif + } type; + grub_mm_region_t reg; + grub_phys_addr_t start; + grub_size_t size; + grub_size_t pre_size; + struct grub_relocator_extra_block *extra; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + struct grub_relocator_fw_leftover *pre, *post; +#endif +}; + +struct grub_relocator_chunk +{ + struct grub_relocator_chunk *next; + grub_phys_addr_t src; + void *srcv; + grub_phys_addr_t target; + grub_size_t size; + struct grub_relocator_subchunk *subchunks; + unsigned nsubchunks; +}; + +struct grub_relocator_extra_block +{ + struct grub_relocator_extra_block *next; + struct grub_relocator_extra_block **prev; + grub_phys_addr_t start; + grub_phys_addr_t end; +}; + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS +struct grub_relocator_fw_leftover +{ + struct grub_relocator_fw_leftover *next; + struct grub_relocator_fw_leftover **prev; + grub_phys_addr_t quantstart; + grub_uint8_t freebytes[GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT / 8]; +}; + +struct grub_relocator_fw_leftover *leftovers; +#endif + +struct grub_relocator_extra_block *extra_blocks; + +void * +get_virtual_current_address (grub_relocator_chunk_t in) +{ + return in->srcv; +} + +grub_phys_addr_t +get_physical_target_address (grub_relocator_chunk_t in) +{ + return in->target; +} + +struct grub_relocator * +grub_relocator_new (void) +{ + struct grub_relocator *ret; + + grub_cpu_relocator_init (); + + ret = grub_zalloc (sizeof (struct grub_relocator)); + if (!ret) + return NULL; + + ret->postchunks = ~(grub_phys_addr_t) 0; + ret->relocators_size = grub_relocator_jumper_size; + grub_dprintf ("relocator", "relocators_size=%lu\n", + (unsigned long) ret->relocators_size); + return ret; +} + +#define DIGITSORT_BITS 8 +#define DIGITSORT_MASK ((1 << DIGITSORT_BITS) - 1) +#define BITS_IN_BYTE 8 + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +static inline int +is_start (int type) +{ + return !(type & 1) && (type != COLLISION_START); +} + +static void +allocate_regstart (grub_phys_addr_t addr, grub_size_t size, grub_mm_region_t rb, + grub_mm_region_t *regancestor, grub_mm_header_t hancestor) +{ + grub_addr_t newreg_start, newreg_raw_start + = (grub_addr_t) rb + (addr - grub_vtop (rb)) + size; + grub_addr_t newreg_size, newreg_presize; + grub_mm_header_t new_header; + grub_mm_header_t hb = (grub_mm_header_t) (rb + 1); + + grub_dprintf ("relocator", "ra = %p, rb = %p\n", regancestor, rb); + + newreg_start = ALIGN_UP (newreg_raw_start, GRUB_MM_ALIGN); + newreg_presize = newreg_start - newreg_raw_start; + newreg_size = rb->size - (newreg_start - (grub_addr_t) rb); + if ((hb->size << GRUB_MM_ALIGN_LOG2) >= newreg_start + - (grub_addr_t) rb) + { + grub_mm_header_t newhnext = hb->next; + grub_size_t newhsize = ((hb->size << GRUB_MM_ALIGN_LOG2) + - (newreg_start + - (grub_addr_t) rb)) >> GRUB_MM_ALIGN_LOG2; + new_header = (void *) (newreg_start + sizeof (*rb)); + if (newhnext == hb) + newhnext = new_header; + new_header->next = newhnext; + new_header->size = newhsize; + new_header->magic = GRUB_MM_FREE_MAGIC; + } + else + { + new_header = hb->next; + if (new_header == hb) + new_header = (void *) (newreg_start + sizeof (*rb)); + } + { + struct grub_mm_header *newregfirst = rb->first; + struct grub_mm_region *newregnext = rb->next; + struct grub_mm_region *newreg = (void *) newreg_start; + hancestor->next = new_header; + if (newregfirst == hb) + newregfirst = new_header; + newreg->first = newregfirst; + newreg->next = newregnext; + newreg->pre_size = newreg_presize; + newreg->size = newreg_size; + *regancestor = newreg; + { + grub_mm_header_t h = newreg->first, hp = NULL; + do + { + if ((void *) h < (void *) (newreg + 1)) + grub_fatal ("Failed to adjust memory region: %p, %p, %p, %p, %p", + newreg, newreg->first, h, hp, hb); + if ((void *) h == (void *) (newreg + 1)) + grub_dprintf ("relocator", + "Free start memory region: %p, %p, %p, %p, %p", + newreg, newreg->first, h, hp, hb); + + hp = h; + h = h->next; + } + while (h != newreg->first); + } + } +} + +static void +allocate_inreg (grub_phys_addr_t paddr, grub_size_t size, + grub_mm_header_t hb, grub_mm_header_t hbp, + grub_mm_region_t rb) +{ + struct grub_mm_header *foll = NULL; + grub_addr_t vaddr = (grub_addr_t) hb + (paddr - grub_vtop (hb)); + + grub_dprintf ("relocator", "inreg paddr = 0x%lx, size = %lu," + " hb = %p, hbp = %p, rb = %p, vaddr = 0x%lx\n", + (unsigned long) paddr, (unsigned long) size, hb, hbp, + rb, (unsigned long) vaddr); + + if (ALIGN_UP (vaddr + size, GRUB_MM_ALIGN) + GRUB_MM_ALIGN + <= (grub_addr_t) (hb + hb->size)) + { + foll = (void *) ALIGN_UP (vaddr + size, GRUB_MM_ALIGN); + foll->magic = GRUB_MM_FREE_MAGIC; + foll->size = hb + hb->size - foll; + grub_dprintf ("relocator", "foll = %p, foll->size = %lu\n", foll, + (unsigned long) foll->size); + } + + if (vaddr - (grub_addr_t) hb >= sizeof (*hb)) + { + hb->size = ((vaddr - (grub_addr_t) hb) >> GRUB_MM_ALIGN_LOG2); + if (foll) + { + foll->next = hb; + hbp->next = foll; + if (rb->first == hb) + { + rb->first = foll; + } + } + } + else + { + if (foll) + { + foll->next = hb->next; + } + else + foll = hb->next; + + hbp->next = foll; + if (rb->first == hb) + { + rb->first = foll; + } + if (rb->first == hb) + { + rb->first = (void *) (rb + 1); + } + } +} + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS +static void +check_leftover (struct grub_relocator_fw_leftover *lo) +{ + unsigned i; + for (i = 0; i < sizeof (lo->freebytes); i++) + if (lo->freebytes[i] != 0xff) + return; + grub_relocator_firmware_free_region (lo->quantstart, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + *lo->prev = lo->next; + if (lo->next) + lo->next->prev = lo->prev; +} +#endif + +static void +free_subchunk (const struct grub_relocator_subchunk *subchu) +{ + switch (subchu->type) + { + case CHUNK_TYPE_REGION_START: + { + grub_mm_region_t r1, r2, *rp; + grub_mm_header_t h; + grub_size_t pre_size; + r1 = subchu->reg; + r2 = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) subchu->reg + + (grub_vtop (subchu->reg) + - subchu->start) + subchu->size, + GRUB_MM_ALIGN); + for (rp = &grub_mm_base; *rp && *rp != r2; rp = &((*rp)->next)); + pre_size = subchu->pre_size; + + if (*rp) + { + grub_mm_header_t h2, *hp; + r1->first = r2->first; + r1->next = r2->next; + r1->pre_size = pre_size; + r1->size = r2->size + (r2 - r1) * sizeof (*r2); + *rp = r1; + h = (grub_mm_header_t) (r1 + 1); + h->next = r2->first; + h->magic = GRUB_MM_FREE_MAGIC; + h->size = (r2 - r1 - 1); + for (hp = &r2->first, h2 = *hp; h2->next != r2->first; + hp = &(h2->next), h2 = *hp) + if (h2 == (grub_mm_header_t) (r2 + 1)) + break; + if (h2 == (grub_mm_header_t) (r2 + 1)) + { + h->size = h2->size + (h2 - h); + h->next = h2->next; + *hp = h; + if (hp == &r2->first) + { + for (h2 = r2->first; h2->next != r2->first; h2 = h2->next); + h2->next = h; + } + } + else + { + h2->next = h; + } + } + else + { + r1->pre_size = pre_size; + r1->size = (r2 - r1) * sizeof (*r2); + /* Find where to insert this region. + Put a smaller one before bigger ones, + to prevent fragmentation. */ + for (rp = &grub_mm_base; *rp; rp = &((*rp)->next)) + if ((*rp)->size > r1->size) + break; + r1->next = *rp; + *rp = r1->next; + h = (grub_mm_header_t) (r1 + 1); + r1->first = h; + h->next = h; + h->magic = GRUB_MM_FREE_MAGIC; + h->size = (r2 - r1 - 1); + } + for (r2 = grub_mm_base; r2; r2 = r2->next) + if ((grub_addr_t) r2 + r2->size == (grub_addr_t) r1) + break; + if (r2) + { + grub_mm_header_t hl2, hl, g; + g = (grub_mm_header_t) ((grub_addr_t) r2 + r2->size); + g->size = (grub_mm_header_t) r1 - g; + r2->size += r1->size; + for (hl = r2->first; hl->next != r2->first; hl = hl->next); + for (hl2 = r1->first; hl2->next != r1->first; hl2 = hl2->next); + hl2->next = r2->first; + r2->first = r1->first; + hl->next = r2->first; + *rp = (*rp)->next; + grub_free (g + 1); + } + break; + } + case CHUNK_TYPE_IN_REGION: + { + grub_mm_header_t h = (grub_mm_header_t) ALIGN_DOWN ((grub_addr_t) subchu->start, + GRUB_MM_ALIGN); + h->size + = ((subchu->start + subchu->size + GRUB_MM_ALIGN - 1) / GRUB_MM_ALIGN) + - (subchu->start / GRUB_MM_ALIGN) - 1; + h->next = h; + h->magic = GRUB_MM_ALLOC_MAGIC; + grub_free (h + 1); + break; + } +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case CHUNK_TYPE_FIRMWARE: + case CHUNK_TYPE_LEFTOVER: + { + grub_addr_t fstart, fend; + fstart = ALIGN_UP (subchu->start, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + fend = ALIGN_DOWN (subchu->start + subchu->size, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + if (fstart < fend) + grub_relocator_firmware_free_region (fstart, fend - fstart); +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + if (subchu->pre) + { + int off = subchu->start - fstart + - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + grub_memset (subchu->pre->freebytes + off / 8 + 1, + 0xff, sizeof (subchu->pre->freebytes) - off / 8 - 1); + subchu->pre->freebytes[off / 8] |= ~((1 << (off % 8)) - 1); + check_leftover (subchu->pre); + } + if (subchu->post) + { + int off = subchu->start + subchu->size - fend; + grub_memset (subchu->pre->freebytes, + 0xff, sizeof (subchu->pre->freebytes) - off / 8); + subchu->pre->freebytes[off / 8] |= ((1 << (8 - (off % 8))) - 1); + check_leftover (subchu->post); + } +#endif + *subchu->extra->prev = subchu->extra->next; + grub_free (subchu->extra); + } + break; +#endif + } +} + +static int +malloc_in_range (struct grub_relocator *rel, + grub_addr_t start, grub_addr_t end, grub_addr_t align, + grub_size_t size, struct grub_relocator_chunk *res, + int from_low_priv, int collisioncheck) +{ + grub_mm_region_t r, *ra, base_saved; + struct grub_relocator_mmap_event *events = NULL, *eventt = NULL, *t; + /* 128 is just in case of additional malloc (shouldn't happen). */ + unsigned maxevents = 2 + 128; + grub_mm_header_t p, pa; + unsigned *counter; + int nallocs = 0; + unsigned j, N = 0; + grub_addr_t target = 0; + + grub_dprintf ("relocator", + "trying to allocate in 0x%lx-0x%lx aligned 0x%lx size 0x%lx\n", + (unsigned long) start, (unsigned long) end, + (unsigned long) align, (unsigned long) size); + + start = ALIGN_UP (start, align); + end = ALIGN_DOWN (end - size, align) + size; + + if (end < start + size) + return 0; + + /* We have to avoid any allocations when filling scanline events. + Hence 2-stages. + */ + for (r = grub_mm_base; r; r = r->next) + { + p = r->first; + do + { + if ((grub_addr_t) p < (grub_addr_t) (r + 1) + || (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size) + grub_fatal ("%d: out of range pointer: %p\n", __LINE__, p); + maxevents += 2; + p = p->next; + } + while (p != r->first); + maxevents += 4; + } + + if (collisioncheck && rel) + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + maxevents += 2; + } + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + { + struct grub_relocator_extra_block *cur; + for (cur = extra_blocks; cur; cur = cur->next) + maxevents += 2; + } + for (r = grub_mm_base; r; r = r->next) + maxevents += 2; + + maxevents += grub_relocator_firmware_get_max_events (); +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + { + struct grub_relocator_fw_leftover *cur; + for (cur = leftovers; cur; cur = cur->next) + { + int l = 0; + unsigned i; + for (i = 0; i < GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; i++) + { + if (l != ((cur->freebytes[i / 8] >> (i % 8)) & 1)) + maxevents++; + l = ((cur->freebytes[i / 8] >> (i % 8)) & 1); + } + if (l) + maxevents++; + } + } +#endif + + events = grub_malloc (maxevents * sizeof (events[0])); + eventt = grub_malloc (maxevents * sizeof (events[0])); + counter = grub_malloc ((DIGITSORT_MASK + 2) * sizeof (counter[0])); + if (!events || !eventt || !counter) + { + grub_dprintf ("relocator", "events or counter allocation failed %d\n", + maxevents); + grub_free (events); + grub_free (eventt); + grub_free (counter); + return 0; + } + + if (collisioncheck && rel) + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + { + events[N].type = COLLISION_START; + events[N].pos = chunk->target; + N++; + events[N].type = COLLISION_END; + events[N].pos = chunk->target + chunk->size; + N++; + } + } + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + for (r = grub_mm_base; r; r = r->next) + { + grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", + (unsigned long) r - r->pre_size, + (unsigned long) (r + 1) + r->size); + events[N].type = FIRMWARE_BLOCK_START; + events[N].pos = (grub_addr_t) r - r->pre_size; + N++; + events[N].type = FIRMWARE_BLOCK_END; + events[N].pos = (grub_addr_t) (r + 1) + r->size; + N++; + } + { + struct grub_relocator_extra_block *cur; + for (cur = extra_blocks; cur; cur = cur->next) + { + grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", + (unsigned long) cur->start, (unsigned long) cur->end); + events[N].type = FIRMWARE_BLOCK_START; + events[N].pos = cur->start; + N++; + events[N].type = FIRMWARE_BLOCK_END; + events[N].pos = cur->end; + N++; + } + } + + N += grub_relocator_firmware_fill_events (events + N); + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + { + struct grub_relocator_fw_leftover *cur; + for (cur = leftovers; cur; cur = cur->next) + { + unsigned i; + int l = 0; + for (i = 0; i < GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; i++) + { + if (l != ((cur->freebytes[i / 8] >> (i % 8)) & 1)) + { + events[N].type = l ? REG_LEFTOVER_END : REG_LEFTOVER_START; + events[N].pos = cur->quantstart + i; + events[N].leftover = cur; + N++; + } + l = ((cur->freebytes[i / 8] >> (i % 8)) & 1); + } + if (l) + { + events[N].type = REG_LEFTOVER_END; + events[N].pos = cur->quantstart + i; + events[N].leftover = cur; + N++; + } + } + } +#endif +#endif + + /* No malloc from this point. */ + base_saved = grub_mm_base; + grub_mm_base = NULL; + + for (ra = &base_saved, r = *ra; r; ra = &(r->next), r = *ra) + { + pa = r->first; + p = pa->next; + if (p->magic == GRUB_MM_ALLOC_MAGIC) + continue; + do + { + if (p->magic != GRUB_MM_FREE_MAGIC) + grub_fatal (__FILE__":%d free magic broken at %p (0x%x)\n", + __LINE__, p, p->magic); + if (p == (grub_mm_header_t) (r + 1)) + { + events[N].type = REG_BEG_START; + events[N].pos = grub_vtop (r) - r->pre_size; + events[N].reg = r; + events[N].regancestor = ra; + events[N].head = p; + events[N].hancestor = pa; + N++; + events[N].type = REG_BEG_END; + events[N].pos = grub_vtop (p + p->size) - sizeof (*r) + - sizeof (struct grub_mm_header); + N++; + } + else + { + events[N].type = IN_REG_START; + events[N].pos = grub_vtop (p); + events[N].head = p; + events[N].hancestor = pa; + events[N].reg = r; + N++; + events[N].type = IN_REG_END; + events[N].pos = grub_vtop (p + p->size); + N++; + } + pa = p; + p = pa->next; + } + while (pa != r->first); + } + + /* Put ending events after starting events. */ + { + int st = 0, e = N / 2; + for (j = 0; j < N; j++) + if (is_start (events[j].type) || events[j].type == COLLISION_START) + eventt[st++] = events[j]; + else + eventt[e++] = events[j]; + t = eventt; + eventt = events; + events = t; + } + + { + unsigned i; + for (i = 0; i < (BITS_IN_BYTE * sizeof (grub_addr_t) / DIGITSORT_BITS); + i++) + { + memset (counter, 0, (1 + (1 << DIGITSORT_BITS)) * sizeof (counter[0])); + for (j = 0; j < N; j++) + counter[((events[j].pos >> (DIGITSORT_BITS * i)) + & DIGITSORT_MASK) + 1]++; + for (j = 0; j <= DIGITSORT_MASK; j++) + counter[j+1] += counter[j]; + for (j = 0; j < N; j++) + eventt[counter[((events[j].pos >> (DIGITSORT_BITS * i)) + & DIGITSORT_MASK)]++] = events[j]; + t = eventt; + eventt = events; + events = t; + } + } + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + retry: +#endif + + /* Now events are nicely sorted. */ + { + int nstarted = 0, ncollisions = 0, nstartedfw = 0, nblockfw = 0; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + int nlefto = 0; +#else + const int nlefto = 0; +#endif + grub_addr_t starta = 0; + for (j = from_low_priv ? 0 : N - 1; from_low_priv ? j < N : (j + 1); + from_low_priv ? j++ : j--) + { + int isinsidebefore, isinsideafter; + isinsidebefore = (!ncollisions && (nstarted || (((nlefto || nstartedfw) + && !nblockfw)))); + switch (events[j].type) + { +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case REG_FIRMWARE_START: + nstartedfw++; + break; + + case REG_FIRMWARE_END: + nstartedfw--; + break; + + case FIRMWARE_BLOCK_START: + nblockfw++; + break; + + case FIRMWARE_BLOCK_END: + nblockfw--; + break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + nlefto++; + break; + + case REG_LEFTOVER_END: + nlefto--; + break; +#endif + + case COLLISION_START: + ncollisions++; + break; + + case COLLISION_END: + ncollisions--; + break; + + case IN_REG_START: + case REG_BEG_START: + nstarted++; + break; + + case IN_REG_END: + case REG_BEG_END: + nstarted--; + break; + } + isinsideafter = (!ncollisions && (nstarted || ((nlefto || nstartedfw) + && !nblockfw))); + if (!isinsidebefore && isinsideafter) + starta = from_low_priv ? ALIGN_UP (events[j].pos, align) + : ALIGN_DOWN (events[j].pos - size, align) + size; + if (isinsidebefore && !isinsideafter && from_low_priv) + { + target = starta; + if (target < start) + target = start; + if (target + size <= end && target + size <= events[j].pos) + /* Found an usable address. */ + goto found; + } + if (isinsidebefore && !isinsideafter && !from_low_priv) + { + target = starta - size; + if (target > end - size) + target = end - size; + if (target >= start && target >= events[j].pos) + goto found; + } + } + } + + grub_mm_base = base_saved; + grub_free (events); + grub_free (eventt); + grub_free (counter); + return 0; + + found: + { + int inreg = 0, regbeg = 0, ncol = 0; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + int fwin = 0, fwb = 0, fwlefto = 0; +#endif + int last_start = 0; + for (j = 0; j < N; j++) + { + int typepre; + if (ncol) + typepre = -1; + else if (regbeg) + typepre = CHUNK_TYPE_REGION_START; + else if (inreg) + typepre = CHUNK_TYPE_IN_REGION; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + else if (fwin && !fwb) + typepre = CHUNK_TYPE_FIRMWARE; + else if (fwlefto && !fwb) + typepre = CHUNK_TYPE_LEFTOVER; +#endif + else + typepre = -1; + + if (j != 0 && events[j - 1].pos != events[j].pos) + { + grub_addr_t alloc_start, alloc_end; + alloc_start = max (events[j - 1].pos, target); + alloc_end = min (events[j].pos, target + size); + if (alloc_end > alloc_start) + { + switch (typepre) + { + case CHUNK_TYPE_REGION_START: + allocate_regstart (alloc_start, alloc_end - alloc_start, + events[last_start].reg, + events[last_start].regancestor, + events[last_start].hancestor); + /* TODO: maintain a reverse lookup tree for hancestor. */ + { + unsigned k; + for (k = 0; k < N; k++) + if (events[k].hancestor == events[last_start].head) + events[k].hancestor = events[last_start].hancestor; + } + break; + case CHUNK_TYPE_IN_REGION: + allocate_inreg (alloc_start, alloc_end - alloc_start, + events[last_start].head, + events[last_start].hancestor, + events[last_start].reg); + { + unsigned k; + for (k = 0; k < N; k++) + if (events[k].hancestor == events[last_start].head) + events[k].hancestor = events[last_start].hancestor; + } + break; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case CHUNK_TYPE_FIRMWARE: + { + grub_addr_t fstart, fend; + fstart + = ALIGN_DOWN (alloc_start, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + fend + = ALIGN_UP (alloc_end, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + grub_dprintf ("relocator", "requesting %lx-%lx\n", + (unsigned long) fstart, + (unsigned long) fend); + /* The failure here can be very expensive. */ + if (!grub_relocator_firmware_alloc_region (fstart, + fend - fstart)) + { + if (from_low_priv) + start = fend; + else + end = fstart; + goto retry; + } + break; + } +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case CHUNK_TYPE_LEFTOVER: + { + unsigned offstart = alloc_start + % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + unsigned offend = alloc_end + % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + struct grub_relocator_fw_leftover *lo + = events[last_start].leftover; + lo->freebytes[offstart / 8] + &= ((1 << (8 - (start % 8))) - 1); + grub_memset (lo->freebytes + (offstart + 7) / 8, 0, + offend / 8 - (offstart + 7) / 8); + lo->freebytes[offend / 8] &= ~((1 << (offend % 8)) - 1); + } + break; +#endif + } + nallocs++; + } + } + + switch (events[j].type) + { + case REG_BEG_START: + case IN_REG_START: + if (events[j].type == REG_BEG_START && + (grub_addr_t) (events[j].reg + 1) > target) + regbeg++; + else + inreg++; + last_start = j; + break; + + case REG_BEG_END: + case IN_REG_END: + if (regbeg) + regbeg--; + else + inreg--; + break; + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case REG_FIRMWARE_START: + fwin++; + break; + + case REG_FIRMWARE_END: + fwin--; + break; + + case FIRMWARE_BLOCK_START: + fwb++; + break; + + case FIRMWARE_BLOCK_END: + fwb--; + break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + fwlefto++; + break; + + case REG_LEFTOVER_END: + fwlefto--; + break; +#endif + case COLLISION_START: + ncol++; + break; + case COLLISION_END: + ncol--; + break; + } + + } + } + + /* Malloc is available again. */ + grub_mm_base = base_saved; + + { + int last_start = 0; + int inreg = 0, regbeg = 0, ncol = 0; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + int fwin = 0, fwlefto = 0, fwb = 0; +#endif + unsigned cural = 0; + int oom = 0; + res->subchunks = grub_malloc (sizeof (res->subchunks[0]) * nallocs); + if (!res->subchunks) + oom = 1; + res->nsubchunks = nallocs; + + for (j = 0; j < N; j++) + { + int typepre; + if (ncol) + typepre = -1; + else if (regbeg) + typepre = CHUNK_TYPE_REGION_START; + else if (inreg) + typepre = CHUNK_TYPE_IN_REGION; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + else if (fwin && !fwb) + typepre = CHUNK_TYPE_FIRMWARE; + else if (fwlefto && !fwb) + typepre = CHUNK_TYPE_LEFTOVER; +#endif + else + typepre = -1; + + if (j != 0 && events[j - 1].pos != events[j].pos) + { + grub_addr_t alloc_start, alloc_end; + struct grub_relocator_subchunk tofree; + struct grub_relocator_subchunk *curschu = &tofree; + if (!oom) + curschu = &res->subchunks[cural]; + alloc_start = max (events[j - 1].pos, target); + alloc_end = min (events[j].pos, target + size); + if (alloc_end > alloc_start) + { + grub_dprintf ("relocator", "subchunk 0x%lx-0x%lx, %d\n", + (unsigned long) alloc_start, + (unsigned long) alloc_end, typepre); + curschu->type = typepre; + curschu->start = alloc_start; + curschu->size = alloc_end - alloc_start; + if (typepre == CHUNK_TYPE_REGION_START + || typepre == CHUNK_TYPE_IN_REGION) + { + curschu->reg = events[last_start].reg; + curschu->pre_size = alloc_start - events[j - 1].pos; + } + if (!oom && (typepre == CHUNK_TYPE_REGION_START +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + || typepre == CHUNK_TYPE_FIRMWARE +#endif + )) + { + struct grub_relocator_extra_block *ne; + ne = grub_malloc (sizeof (*ne)); + if (!ne) + { + oom = 1; + grub_memcpy (&tofree, curschu, sizeof (tofree)); + } + else + { + ne->start = alloc_start; + ne->end = alloc_end; + ne->next = extra_blocks; + ne->prev = &extra_blocks; + if (extra_blocks) + extra_blocks->prev = &(ne->next); + extra_blocks = ne; + curschu->extra = ne; + } + } +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + if (!oom && typepre == CHUNK_TYPE_FIRMWARE) + { + grub_addr_t fstart, fend; + + fstart + = ALIGN_DOWN (alloc_start, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + fend + = ALIGN_UP (alloc_end, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + { + struct grub_relocator_fw_leftover *lo1 = NULL; + struct grub_relocator_fw_leftover *lo2 = NULL; + if (fstart != alloc_start) + lo1 = grub_malloc (sizeof (*lo1)); + if (fend != alloc_end) + lo2 = grub_malloc (sizeof (*lo2)); + if ((!lo1 && fstart != alloc_start) + || (!lo2 && fend != alloc_end)) + { + struct grub_relocator_extra_block *ne; + grub_free (lo1); + grub_free (lo2); + lo1 = NULL; + lo2 = NULL; + oom = 1; + grub_memcpy (&tofree, curschu, sizeof (tofree)); + ne = extra_blocks; + extra_blocks = extra_blocks->next; + grub_free (ne); + } + if (lo1) + { + lo1->quantstart = fstart; + grub_memset (lo1->freebytes, 0xff, + (alloc_start - fstart) / 8); + lo1->freebytes[(alloc_start - fstart) / 8] + = (1 << ((alloc_start - fstart) % 8)) - 1; + grub_memset (lo1->freebytes + + ((alloc_start - fstart) / 8) + 1, 0, + sizeof (lo1->freebytes) + - (alloc_start - fstart) / 8 - 1); + lo1->next = leftovers; + lo1->prev = &leftovers; + if (leftovers) + leftovers->prev = &lo1->next; + leftovers = lo1; + } + if (lo2) + { + lo2->quantstart + = fend - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + grub_memset (lo2->freebytes, 0, + (alloc_end - lo2->quantstart) / 8); + lo2->freebytes[(alloc_end - lo2->quantstart) / 8] + = ~((1 << ((alloc_end - lo2->quantstart) % 8)) - 1); + grub_memset (lo2->freebytes + + ((alloc_end - lo2->quantstart) / 8) + + 1, 0, sizeof (lo2->freebytes) + - (alloc_end - lo2->quantstart) / 8 - 1); + lo2->prev = &leftovers; + if (leftovers) + leftovers->prev = &lo2->next; + lo2->next = leftovers; + leftovers = lo2; + } + curschu->pre = lo1; + curschu->post = lo2; + } +#endif + } + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + if (typepre == CHUNK_TYPE_LEFTOVER) + { + curschu->pre = events[last_start].leftover; + curschu->post = events[last_start].leftover; + } +#endif + +#endif + if (!oom) + cural++; + else + free_subchunk (&tofree); + } + } + + switch (events[j].type) + { + case REG_BEG_START: + case IN_REG_START: + if (events[j].type == REG_BEG_START && + (grub_addr_t) (events[j].reg + 1) > target) + regbeg++; + else + inreg++; + last_start = j; + break; + + case REG_BEG_END: + case IN_REG_END: + inreg = regbeg = 0; + break; + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case REG_FIRMWARE_START: + fwin++; + break; + + case REG_FIRMWARE_END: + fwin--; + break; + + case FIRMWARE_BLOCK_START: + fwb++; + break; + + case FIRMWARE_BLOCK_END: + fwb--; + break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + fwlefto++; + break; + + case REG_LEFTOVER_END: + fwlefto--; + break; +#endif + case COLLISION_START: + ncol++; + break; + case COLLISION_END: + ncol--; + break; + } + } + if (oom) + { + unsigned i; + for (i = 0; i < cural; i++) + free_subchunk (&res->subchunks[i]); + grub_free (res->subchunks); + grub_dprintf ("relocator", "allocation failed with out-of-memory\n"); + return 0; + } + } + + res->src = target; + res->size = size; + grub_dprintf ("relocator", "allocated: 0x%lx+0x%lx\n", (unsigned long) target, + (unsigned long) size); + + return 1; +} + +static void +adjust_limits (struct grub_relocator *rel, + grub_phys_addr_t *min_addr, grub_phys_addr_t *max_addr, + grub_phys_addr_t in_min, grub_phys_addr_t in_max) +{ + struct grub_relocator_chunk *chunk; + + *min_addr = 0; + *max_addr = rel->postchunks; + + /* Keep chunks in memory in the same order as they'll be after relocation. */ + for (chunk = rel->chunks; chunk; chunk = chunk->next) + { + if (chunk->target > in_max && chunk->src < *max_addr + && chunk->src < rel->postchunks) + *max_addr = chunk->src; + if (chunk->target + chunk->size <= in_min + && chunk->src + chunk->size > *min_addr + && chunk->src < rel->postchunks) + *min_addr = chunk->src + chunk->size; + } +} + +grub_err_t +grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t target, grub_size_t size) +{ + struct grub_relocator_chunk *chunk; + grub_phys_addr_t min_addr = 0, max_addr; + + if (target > ~size) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "address is out of range"); + + adjust_limits (rel, &min_addr, &max_addr, target, target); + + for (chunk = rel->chunks; chunk; chunk = chunk->next) + if ((chunk->target <= target && target < chunk->target + chunk->size) + || (target <= chunk->target && chunk->target < target + size)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "overlap detected"); + + chunk = grub_malloc (sizeof (struct grub_relocator_chunk)); + if (!chunk) + return grub_errno; + + grub_dprintf ("relocator", + "min_addr = 0x%llx, max_addr = 0x%llx, target = 0x%llx\n", + (unsigned long long) min_addr, (unsigned long long) max_addr, + (unsigned long long) target); + + do + { + /* A trick to improve Linux allocation. */ +#if defined (__i386__) || defined (__x86_64__) + if (target < 0x100000) + if (malloc_in_range (rel, rel->highestnonpostaddr, ~(grub_addr_t)0, 1, + size, chunk, 0, 1)) + { + if (rel->postchunks > chunk->src) + rel->postchunks = chunk->src; + break; + } +#endif + if (malloc_in_range (rel, target, max_addr, 1, size, chunk, 1, 0)) + break; + + if (malloc_in_range (rel, min_addr, target, 1, size, chunk, 0, 0)) + break; + + if (malloc_in_range (rel, rel->highestnonpostaddr, ~(grub_addr_t)0, 1, + size, chunk, 0, 1)) + { + if (rel->postchunks > chunk->src) + rel->postchunks = chunk->src; + break; + } + + grub_dprintf ("relocator", "not allocated\n"); + grub_free (chunk); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + } + while (0); + + grub_dprintf ("relocator", "allocated 0x%llx/0x%llx\n", + (unsigned long long) chunk->src, (unsigned long long) target); + + if (rel->highestaddr < target + size) + rel->highestaddr = target + size; + + if (rel->highestaddr < chunk->src + size) + rel->highestaddr = chunk->src + size; + + if (chunk->src < rel->postchunks) + { + if (rel->highestnonpostaddr < target + size) + rel->highestnonpostaddr = target + size; + + if (rel->highestnonpostaddr < chunk->src + size) + rel->highestnonpostaddr = chunk->src + size; + } + + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + + if (chunk->src < target) + rel->relocators_size += grub_relocator_backward_size; + if (chunk->src > target) + rel->relocators_size += grub_relocator_forward_size; + + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + + chunk->target = target; + chunk->size = size; + chunk->next = rel->chunks; + rel->chunks = chunk; + grub_dprintf ("relocator", "cur = %p, next = %p\n", rel->chunks, + rel->chunks->next); + + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; +#ifdef DEBUG_RELOCATOR + { + grub_mm_region_t r; + grub_mm_header_t p; + grub_memset (chunk->srcv, 0xfa, chunk->size); + for (r = grub_mm_base; r; r = r->next) + { + p = r->first; + do + { + if ((grub_addr_t) p < (grub_addr_t) (r + 1) + || (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size) + grub_fatal (__FILE__ ":%d: out of range pointer: %p\n", __LINE__, p); + p = p->next; + } + while (p != r->first); + } + } +#endif + return GRUB_ERR_NONE; +} + +grub_err_t +grub_relocator_alloc_chunk_align (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t min_addr, + grub_phys_addr_t max_addr, + grub_size_t size, grub_size_t align, + int preference) +{ + grub_addr_t min_addr2 = 0, max_addr2; + struct grub_relocator_chunk *chunk; + + if (max_addr > ~size) + max_addr = ~size; + +#ifdef GRUB_MACHINE_PCBIOS + if (min_addr < 0x1000) + min_addr = 0x1000; +#endif + + grub_dprintf ("relocator", "chunks = %p\n", rel->chunks); + + chunk = grub_malloc (sizeof (struct grub_relocator_chunk)); + if (!chunk) + return grub_errno; + + if (malloc_in_range (rel, min_addr, max_addr, align, + size, chunk, + preference != GRUB_RELOCATOR_PREFERENCE_HIGH, 1)) + { + grub_dprintf ("relocator", "allocated 0x%llx/0x%llx\n", + (unsigned long long) chunk->src, + (unsigned long long) chunk->src); + grub_dprintf ("relocator", "chunks = %p\n", rel->chunks); + chunk->target = chunk->src; + chunk->size = size; + chunk->next = rel->chunks; + rel->chunks = chunk; + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; + return GRUB_ERR_NONE; + } + + adjust_limits (rel, &min_addr2, &max_addr2, min_addr, max_addr); + grub_dprintf ("relocator", "Adjusted limits from %lx-%lx to %lx-%lx\n", + (unsigned long) min_addr, (unsigned long) max_addr, + (unsigned long) min_addr2, (unsigned long) max_addr2); + + do + { + if (malloc_in_range (rel, min_addr2, max_addr2, align, + size, chunk, 1, 1)) + break; + + if (malloc_in_range (rel, rel->highestnonpostaddr, ~(grub_addr_t)0, 1, + size, chunk, 0, 1)) + { + if (rel->postchunks > chunk->src) + rel->postchunks = chunk->src; + break; + } + + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + } + while (0); + + { + int found = 0; + 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 sz, + grub_memory_type_t type) + { + grub_uint64_t candidate; + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + candidate = ALIGN_UP (addr, align); + if (candidate < min_addr) + candidate = ALIGN_UP (min_addr, align); + if (candidate + size > addr + sz + || candidate > ALIGN_DOWN (max_addr, align)) + return 0; + if (preference == GRUB_RELOCATOR_PREFERENCE_HIGH) + candidate = ALIGN_DOWN (min (addr + sz - size, max_addr), align); + if (!found || (preference == GRUB_RELOCATOR_PREFERENCE_HIGH + && candidate > chunk->target)) + chunk->target = candidate; + if (!found || (preference == GRUB_RELOCATOR_PREFERENCE_LOW + && candidate < chunk->target)) + chunk->target = candidate; + found = 1; + return 0; + } + + grub_machine_mmap_iterate (hook); + if (!found) + return grub_error (GRUB_ERR_BAD_OS, "couldn't find suitable memory target"); + } + while (1) + { + struct grub_relocator_chunk *chunk2; + for (chunk2 = rel->chunks; chunk2; chunk2 = chunk2->next) + if ((chunk2->target <= chunk->target + && chunk->target < chunk2->target + chunk2->size) + || (chunk2->target <= chunk->target + size + && chunk->target + size < chunk2->target + chunk2->size) + || (chunk->target <= chunk2->target && chunk2->target + < chunk->target + size) + || (chunk->target <= chunk2->target + chunk2->size + && chunk2->target + chunk2->size < chunk->target + size)) + { + if (preference == GRUB_RELOCATOR_PREFERENCE_HIGH) + chunk->target = ALIGN_DOWN (chunk2->target, align); + else + chunk->target = ALIGN_UP (chunk2->target + chunk2->size, align); + break; + } + if (!chunk2) + break; + } + + if (chunk->src < chunk->target) + rel->relocators_size += grub_relocator_backward_size; + if (chunk->src > chunk->target) + rel->relocators_size += grub_relocator_forward_size; + + chunk->size = size; + chunk->next = rel->chunks; + rel->chunks = chunk; + grub_dprintf ("relocator", "cur = %p, next = %p\n", rel->chunks, + rel->chunks->next); + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; +#ifdef DEBUG_RELOCATOR + { + grub_mm_region_t r; + grub_mm_header_t p; + + grub_memset (chunk->srcv, 0xfa, chunk->size); + for (r = grub_mm_base; r; r = r->next) + { + p = r->first; + do + { + if ((grub_addr_t) p < (grub_addr_t) (r + 1) + || (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size) + grub_fatal (__FILE__ "%d: out of range pointer: %p\n", __LINE__, p); + p = p->next; + } + while (p != r->first); + } + } +#endif + return GRUB_ERR_NONE; +} + +void +grub_relocator_unload (struct grub_relocator *rel) +{ + struct grub_relocator_chunk *chunk, *next; + if (!rel) + return; + for (chunk = rel->chunks; chunk; chunk = next) + { + unsigned i; + for (i = 0; i < chunk->nsubchunks; i++) + free_subchunk (&chunk->subchunks[i]); + grub_unmap_memory (chunk->srcv, chunk->size); + next = chunk->next; + grub_free (chunk->subchunks); + grub_free (chunk); + } + grub_free (rel); +} + +grub_err_t +grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr, + void **relstart, grub_size_t *relsize) +{ + grub_uint8_t *rels; + grub_uint8_t *rels0; + struct grub_relocator_chunk *sorted; + grub_size_t nchunks = 0; + unsigned j; + struct grub_relocator_chunk movers_chunk; + + grub_dprintf ("relocator", "Preparing relocs (size=%ld)\n", + (unsigned long) rel->relocators_size); + + if (!malloc_in_range (rel, 0, ~(grub_addr_t)0 - rel->relocators_size + 1, + grub_relocator_align, + rel->relocators_size, &movers_chunk, 1, 1)) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + movers_chunk.srcv = rels = rels0 + = grub_map_memory (movers_chunk.src, movers_chunk.size); + + if (relsize) + *relsize = rel->relocators_size; + + grub_dprintf ("relocator", "Relocs allocated at %p\n", movers_chunk.srcv); + + { + unsigned i; + grub_size_t count[257]; + struct grub_relocator_chunk *from, *to, *tmp; + + grub_memset (count, 0, sizeof (count)); + + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + { + grub_dprintf ("relocator", "chunk %p->%p, 0x%lx\n", + (void *) chunk->src, (void *) chunk->target, + (unsigned long) chunk->size); + nchunks++; + count[(chunk->src & 0xff) + 1]++; + } + } + from = grub_malloc (nchunks * sizeof (sorted[0])); + to = grub_malloc (nchunks * sizeof (sorted[0])); + if (!from || !to) + { + grub_free (from); + grub_free (to); + return grub_errno; + } + + for (j = 0; j < 256; j++) + count[j+1] += count[j]; + + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + from[count[chunk->src & 0xff]++] = *chunk; + } + + for (i = 1; i < GRUB_CPU_SIZEOF_VOID_P; i++) + { + grub_memset (count, 0, sizeof (count)); + for (j = 0; j < nchunks; j++) + count[((from[j].src >> (8 * i)) & 0xff) + 1]++; + for (j = 0; j < 256; j++) + count[j+1] += count[j]; + for (j = 0; j < nchunks; j++) + to[count[(from[j].src >> (8 * i)) & 0xff]++] = from[j]; + tmp = to; + to = from; + from = tmp; + } + sorted = from; + grub_free (to); + } + + for (j = 0; j < nchunks; j++) + { + grub_dprintf ("relocator", "sorted chunk %p->%p, 0x%lx\n", + (void *) sorted[j].src, (void *) sorted[j].target, + (unsigned long) sorted[j].size); + if (sorted[j].src < sorted[j].target) + { + grub_cpu_relocator_backward ((void *) rels, + sorted[j].srcv, + grub_map_memory (sorted[j].target, + sorted[j].size), + sorted[j].size); + rels += grub_relocator_backward_size; + } + if (sorted[j].src > sorted[j].target) + { + grub_cpu_relocator_forward ((void *) rels, + sorted[j].srcv, + grub_map_memory (sorted[j].target, + sorted[j].size), + sorted[j].size); + rels += grub_relocator_forward_size; + } + if (sorted[j].src == sorted[j].target) + grub_arch_sync_caches (sorted[j].srcv, sorted[j].size); + } + grub_cpu_relocator_jumper ((void *) rels, (grub_addr_t) addr); + *relstart = rels0; + grub_free (sorted); + return GRUB_ERR_NONE; +} + +void +grub_mm_check_real (char *file, int line) +{ + grub_mm_region_t r; + grub_mm_header_t p, pa; + + for (r = grub_mm_base; r; r = r->next) + { + pa = r->first; + p = pa->next; + if (p->magic == GRUB_MM_ALLOC_MAGIC) + continue; + do + { + if ((grub_addr_t) p < (grub_addr_t) (r + 1) + || (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size) + grub_fatal ("%s:%d: out of range pointer: %p\n", file, line, p); + if (p->magic != GRUB_MM_FREE_MAGIC) + grub_fatal ("%s:%d free magic broken at %p (0x%x)\n", file, + line, p, p->magic); + pa = p; + p = pa->next; + } + while (pa != r->first); + } +} diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S new file mode 100644 index 000000000..c39c91b9c --- /dev/null +++ b/grub-core/lib/setjmp.S @@ -0,0 +1,13 @@ +#if defined(__i386__) +#include "./i386/setjmp.S" +#elif defined(__x86_64__) +#include "./x86_64/setjmp.S" +#elif defined(__sparc__) +#include "./sparc64/setjmp.S" +#elif defined(__mips__) +#include "./mips/setjmp.S" +#elif defined(__powerpc__) +#include "./powerpc/setjmp.S" +#else +#error "Unknwon target cpu type" +#endif diff --git a/lib/sparc64/setjmp.S b/grub-core/lib/sparc64/setjmp.S similarity index 100% rename from lib/sparc64/setjmp.S rename to grub-core/lib/sparc64/setjmp.S diff --git a/grub-core/lib/x86_64/relocator_asm.S b/grub-core/lib/x86_64/relocator_asm.S new file mode 100644 index 000000000..2ab6d8cb7 --- /dev/null +++ b/grub-core/lib/x86_64/relocator_asm.S @@ -0,0 +1,85 @@ +/* + * 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 + + .p2align 2 + +VARIABLE(grub_relocator_backward_start) + /* mov imm32, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_backward_dest) + .long 0, 0 + movq %rax, %rdi + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_backward_src) + .long 0, 0 + movq %rax, %rsi + + /* mov imm64, %rcx */ + .byte 0x48 + .byte 0xb9 +VARIABLE(grub_relocator_backward_chunk_size) + .long 0, 0 + + add %rcx, %rsi + add %rcx, %rdi + + /* Backward movsb is implicitly off-by-one. compensate that. */ + sub $1, %rsi + sub $1, %rdi + + /* Backward copy. */ + std + + rep + movsb +VARIABLE(grub_relocator_backward_end) + + +VARIABLE(grub_relocator_forward_start) + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_forward_dest) + .long 0, 0 + movq %rax, %rdi + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_forward_src) + .long 0, 0 + movq %rax, %rsi + + /* mov imm64, %rcx */ + .byte 0x48 + .byte 0xb9 +VARIABLE(grub_relocator_forward_chunk_size) + .long 0, 0 + + /* Forward copy. */ + cld + rep + movsb +VARIABLE(grub_relocator_forward_end) diff --git a/lib/x86_64/setjmp.S b/grub-core/lib/x86_64/setjmp.S similarity index 100% rename from lib/x86_64/setjmp.S rename to grub-core/lib/x86_64/setjmp.S diff --git a/grub-core/lib/xzembed/xz.h b/grub-core/lib/xzembed/xz.h new file mode 100644 index 000000000..f0a7dbbca --- /dev/null +++ b/grub-core/lib/xzembed/xz.h @@ -0,0 +1,180 @@ +/* xz.h - XZ decompressor */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_H +#define XZ_H + +#include + +/** + * enum xz_ret - Return codes + * @XZ_OK: Everything is OK so far. More input or more output + * space is required to continue. + * @XZ_STREAM_END: Operation finished successfully. + * @XZ_MEMLIMIT_ERROR: Not enough memory was preallocated at decoder + * initialization time. + * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic bytes). + * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested + * compression options. In the decoder this means that + * the header CRC32 matches, but the header itself + * specifies something that we don't support. + * @XZ_DATA_ERROR: Compressed data is corrupt. + * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly + * different between multi-call and single-call mode; + * more information below. + * + * In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls + * to XZ code cannot consume any input and cannot produce any new output. + * This happens when there is no new input available, or the output buffer + * is full while at least one output byte is still pending. Assuming your + * code is not buggy, you can get this error only when decoding a compressed + * stream that is truncated or otherwise corrupt. + * + * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer + * is too small, or the compressed input is corrupt in a way that makes the + * decoder produce more output than the caller expected. When it is + * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR + * is used instead of XZ_BUF_ERROR. + */ +enum xz_ret { + XZ_OK, + XZ_STREAM_END, + XZ_MEMLIMIT_ERROR, + XZ_FORMAT_ERROR, + XZ_OPTIONS_ERROR, + XZ_DATA_ERROR, + XZ_BUF_ERROR +}; + +/** + * struct xz_buf - Passing input and output buffers to XZ code + * @in: Beginning of the input buffer. This may be NULL if and only + * if in_pos is equal to in_size. + * @in_pos: Current position in the input buffer. This must not exceed + * in_size. + * @in_size: Size of the input buffer + * @out: Beginning of the output buffer. This may be NULL if and only + * if out_pos is equal to out_size. + * @out_pos: Current position in the output buffer. This must not exceed + * out_size. + * @out_size: Size of the output buffer + * + * Only the contents of the output buffer from out[out_pos] onward, and + * the variables in_pos and out_pos are modified by the XZ code. + */ +struct xz_buf { + const uint8_t *in; + size_t in_pos; + size_t in_size; + + uint8_t *out; + size_t out_pos; + size_t out_size; +}; + +/** + * struct xz_dec - Opaque type to hold the XZ decoder state + */ +struct xz_dec; + +/** + * xz_dec_init() - Allocate and initialize a XZ decoder state + * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for + * multi-call decoding, or special value of zero to indicate + * single-call decoding mode. + * + * If dict_max > 0, the decoder is initialized to work in multi-call mode. + * dict_max number of bytes of memory is preallocated for the LZMA2 + * dictionary. This way there is no risk that xz_dec_run() could run out + * of memory, since xz_dec_run() will never allocate any memory. Instead, + * if the preallocated dictionary is too small for decoding the given input + * stream, xz_dec_run() will return XZ_MEMLIMIT_ERROR. Thus, it is important + * to know what kind of data will be decoded to avoid allocating excessive + * amount of memory for the dictionary. + * + * LZMA2 dictionary is always 2^n bytes or 2^n + 2^(n-1) bytes (the latter + * sizes are less common in practice). In the kernel, dictionary sizes of + * 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB are probably the only + * reasonable values. + * + * If dict_max == 0, the decoder is initialized to work in single-call mode. + * In single-call mode, xz_dec_run() decodes the whole stream at once. The + * caller must provide enough output space or the decoding will fail. The + * output space is used as the dictionary buffer, which is why there is + * no need to allocate the dictionary as part of the decoder's internal + * state. + * + * Because the output buffer is used as the workspace, streams encoded using + * a big dictionary are not a problem in single-call. It is enough that the + * output buffer is is big enough to hold the actual uncompressed data; it + * can be smaller than the dictionary size stored in the stream headers. + * + * On success, xz_dec_init() returns a pointer to struct xz_dec, which is + * ready to be used with xz_dec_run(). On error, xz_dec_init() returns NULL. + */ +struct xz_dec * xz_dec_init(uint32_t dict_max); + +/** + * xz_dec_run() - Run the XZ decoder + * @s: Decoder state allocated using xz_dec_init() + * @b: Input and output buffers + * + * In multi-call mode, this function may return any of the values listed in + * enum xz_ret. + * + * In single-call mode, this function never returns XZ_OK. If an error occurs + * in single-call mode (return value is not XZ_STREAM_END), b->in_pos and + * b->out_pos are not modified, and the contents of the output buffer from + * b->out[b->out_pos] onward are undefined. + * + * NOTE: In single-call mode, the contents of the output buffer are undefined + * also after XZ_BUF_ERROR. This is because with some filter chains, there + * may be a second pass over the output buffer, and this pass cannot be + * properly done if the output buffer is truncated. Thus, you cannot give + * the single-call decoder a too small buffer and then expect to get that + * amount valid data from the beginning of the stream. You must use the + * multi-call decoder if you don't want to uncompress the whole stream. + */ +enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b); + +/** + * xz_dec_reset() - Reset an already allocated decoder state + * @s: Decoder state allocated using xz_dec_init() + * + * This function can be used to reset the multi-call decoder state without + * freeing and reallocating memory with xz_dec_end() and xz_dec_init(). + * + * In single-call mode, xz_dec_reset() is always called in the beginning of + * xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in + * multi-call mode. + */ +void xz_dec_reset(struct xz_dec *s); + +/** + * xz_dec_end() - Free the memory allocated for the decoder state + * @s: Decoder state allocated using xz_dec_init(). If s is NULL, + * this function does nothing. + */ +void xz_dec_end(struct xz_dec *s); + +#endif diff --git a/grub-core/lib/xzembed/xz_config.h b/grub-core/lib/xzembed/xz_config.h new file mode 100644 index 000000000..0af0d2b81 --- /dev/null +++ b/grub-core/lib/xzembed/xz_config.h @@ -0,0 +1,141 @@ +/* xz_config.h - Private includes and definitions for userspace use */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_CONFIG_H +#define XZ_CONFIG_H + +/* Enable BCJ filter decoders. */ + +#if defined(__i386__) || defined(__x86_64__) + #define XZ_DEC_X86 +#endif + +#ifdef __powerpc__ + #define XZ_DEC_POWERPC +#endif + +#ifdef __ia64__ + #define XZ_DEC_IA64 +#endif + +#ifdef __arm__ + #define XZ_DEC_ARM +#endif + +#ifdef __thumb__ + #define XZ_DEC_ARMTHUMB +#endif + +#ifdef __sparc__ + #define XZ_DEC_SPARC +#endif + + +#include "xz.h" +#include + +#define kmalloc(size, flags) malloc(size) +#define kfree(ptr) free(ptr) +#define vmalloc(size) malloc(size) +#define vfree(ptr) free(ptr) + +#define memeq(a, b, size) (memcmp(a, b, size) == 0) +#define memzero(buf, size) memset(buf, 0, size) + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define min_t(type, x, y) min(x, y) + +/* + * Some functions have been marked with __always_inline to keep the + * performance reasonable even when the compiler is optimizing for + * small code size. You may be able to save a few bytes by #defining + * __always_inline to plain inline, but don't complain if the code + * becomes slow. + * + * NOTE: System headers on GNU/Linux may #define this macro already, + * so if you want to change it, it you need to #undef it first. + */ +#ifndef __always_inline +# ifdef __GNUC__ +# define __always_inline \ + inline __attribute__((__always_inline__)) +# else +# define __always_inline inline +# endif +#endif + +/* + * Some functions are marked to never be inlined to reduce stack usage. + * If you don't care about stack usage, you may want to modify this so + * that noinline_for_stack is #defined to be empty even when using GCC. + * Doing so may save a few bytes in binary size. + */ +#ifndef noinline_for_stack +# ifdef __GNUC__ +# define noinline_for_stack __attribute__((__noinline__)) +# else +# define noinline_for_stack +# endif +#endif + +/* Inline functions to access unaligned unsigned 32-bit integers */ +static inline uint32_t get_unaligned_le32(const uint8_t *buf) +{ + return (uint32_t)buf[0] + | ((uint32_t)buf[1] << 8) + | ((uint32_t)buf[2] << 16) + | ((uint32_t)buf[3] << 24); +} + +static inline uint32_t get_unaligned_be32(const uint8_t *buf) +{ + return (uint32_t)(buf[0] << 24) + | ((uint32_t)buf[1] << 16) + | ((uint32_t)buf[2] << 8) + | (uint32_t)buf[3]; +} + +static inline void put_unaligned_le32(uint32_t val, uint8_t *buf) +{ + buf[0] = (uint8_t)val; + buf[1] = (uint8_t)(val >> 8); + buf[2] = (uint8_t)(val >> 16); + buf[3] = (uint8_t)(val >> 24); +} + +static inline void put_unaligned_be32(uint32_t val, uint8_t *buf) +{ + buf[0] = (uint8_t)(val >> 24); + buf[1] = (uint8_t)(val >> 16); + buf[2] = (uint8_t)(val >> 8); + buf[3] = (uint8_t)val; +} + +/* + * Use get_unaligned_le32() also for aligned access for simplicity. On + * little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr)) + * could save a few bytes in code size. + */ +#define get_le32 get_unaligned_le32 + +#endif diff --git a/grub-core/lib/xzembed/xz_dec_bcj.c b/grub-core/lib/xzembed/xz_dec_bcj.c new file mode 100644 index 000000000..f517b0acc --- /dev/null +++ b/grub-core/lib/xzembed/xz_dec_bcj.c @@ -0,0 +1,578 @@ +/* xz_dec_bcj.c - Branch/Call/Jump (BCJ) filter decoders */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#include "xz_private.h" + +struct xz_dec_bcj { + /* Type of the BCJ filter being used */ + enum { + BCJ_X86 = 4, /* x86 or x86-64 */ + BCJ_POWERPC = 5, /* Big endian only */ + BCJ_IA64 = 6, /* Big or little endian */ + BCJ_ARM = 7, /* Little endian only */ + BCJ_ARMTHUMB = 8, /* Little endian only */ + BCJ_SPARC = 9 /* Big or little endian */ + } type; + + /* + * Return value of the next filter in the chain. We need to preserve + * this information across calls, because we must not call the next + * filter anymore once it has returned XZ_STREAM_END. + */ + enum xz_ret ret; + + /* True if we are operating in single-call mode. */ + bool single_call; + + /* + * Absolute position relative to the beginning of the uncompressed + * data (in a single .xz Block). We care only about the lowest 32 + * bits so this doesn't need to be uint64_t even with big files. + */ + uint32_t pos; + + /* x86 filter state */ + uint32_t x86_prev_mask; + + /* Temporary space to hold the variables from struct xz_buf */ + uint8_t *out; + size_t out_pos; + size_t out_size; + + struct { + /* Amount of already filtered data in the beginning of buf */ + size_t filtered; + + /* Total amount of data currently stored in buf */ + size_t size; + + /* + * Buffer to hold a mix of filtered and unfiltered data. This + * needs to be big enough to hold Alignment + 2 * Look-ahead: + * + * Type Alignment Look-ahead + * x86 1 4 + * PowerPC 4 0 + * IA-64 16 0 + * ARM 4 0 + * ARM-Thumb 2 2 + * SPARC 4 0 + */ + uint8_t buf[16]; + } temp; +}; + +#ifdef XZ_DEC_X86 +/* + * This is macro used to test the most significant byte of a memory address + * in an x86 instruction. + */ +#define bcj_x86_test_msbyte(b) ((b) == 0x00 || (b) == 0xFF) + +static noinline_for_stack size_t bcj_x86( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + static const bool mask_to_allowed_status[8] + = { true, true, true, false, true, false, false, false }; + + static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 }; + + size_t i; + size_t prev_pos = (size_t)-1; + uint32_t prev_mask = s->x86_prev_mask; + uint32_t src; + uint32_t dest; + uint32_t j; + uint8_t b; + + if (size <= 4) + return 0; + + size -= 4; + for (i = 0; i < size; ++i) { + if ((buf[i] & 0xFE) != 0xE8) + continue; + + prev_pos = i - prev_pos; + if (prev_pos > 3) { + prev_mask = 0; + } else { + prev_mask = (prev_mask << (prev_pos - 1)) & 7; + if (prev_mask != 0) { + b = buf[i + 4 - mask_to_bit_num[prev_mask]]; + if (!mask_to_allowed_status[prev_mask] + || bcj_x86_test_msbyte(b)) { + prev_pos = i; + prev_mask = (prev_mask << 1) | 1; + continue; + } + } + } + + prev_pos = i; + + if (bcj_x86_test_msbyte(buf[i + 4])) { + src = get_unaligned_le32(buf + i + 1); + while (true) { + dest = src - (s->pos + (uint32_t)i + 5); + if (prev_mask == 0) + break; + + j = mask_to_bit_num[prev_mask] * 8; + b = (uint8_t)(dest >> (24 - j)); + if (!bcj_x86_test_msbyte(b)) + break; + + src = dest ^ (((uint32_t)1 << (32 - j)) - 1); + } + + dest &= 0x01FFFFFF; + dest |= (uint32_t)0 - (dest & 0x01000000); + put_unaligned_le32(dest, buf + i + 1); + i += 4; + } else { + prev_mask = (prev_mask << 1) | 1; + } + } + + prev_pos = i - prev_pos; + s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1); + return i; +} +#endif + +#ifdef XZ_DEC_POWERPC +static noinline_for_stack size_t bcj_powerpc( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t instr; + + for (i = 0; i + 4 <= size; i += 4) { + instr = get_unaligned_be32(buf + i); + if ((instr & 0xFC000003) == 0x48000001) { + instr &= 0x03FFFFFC; + instr -= s->pos + (uint32_t)i; + instr &= 0x03FFFFFC; + instr |= 0x48000001; + put_unaligned_be32(instr, buf + i); + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_IA64 +static noinline_for_stack size_t bcj_ia64( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + static const uint8_t branch_table[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 6, 0, 0, 7, 7, + 4, 4, 0, 0, 4, 4, 0, 0 + }; + + /* + * The local variables take a little bit stack space, but it's less + * than what LZMA2 decoder takes, so it doesn't make sense to reduce + * stack usage here without doing that for the LZMA2 decoder too. + */ + + /* Loop counters */ + size_t i; + size_t j; + + /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */ + uint32_t slot; + + /* Bitwise offset of the instruction indicated by slot */ + uint32_t bit_pos; + + /* bit_pos split into byte and bit parts */ + uint32_t byte_pos; + uint32_t bit_res; + + /* Address part of an instruction */ + uint32_t addr; + + /* Mask used to detect which instructions to convert */ + uint32_t mask; + + /* 41-bit instruction stored somewhere in the lowest 48 bits */ + uint64_t instr; + + /* Instruction normalized with bit_res for easier manipulation */ + uint64_t norm; + + for (i = 0; i + 16 <= size; i += 16) { + mask = branch_table[buf[i] & 0x1F]; + for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) { + if (((mask >> slot) & 1) == 0) + continue; + + byte_pos = bit_pos >> 3; + bit_res = bit_pos & 7; + instr = 0; + for (j = 0; j < 6; ++j) + instr |= (uint64_t)(buf[i + j + byte_pos]) + << (8 * j); + + norm = instr >> bit_res; + + if (((norm >> 37) & 0x0F) == 0x05 + && ((norm >> 9) & 0x07) == 0) { + addr = (norm >> 13) & 0x0FFFFF; + addr |= ((uint32_t)(norm >> 36) & 1) << 20; + addr <<= 4; + addr -= s->pos + (uint32_t)i; + addr >>= 4; + + norm &= ~((uint64_t)0x8FFFFF << 13); + norm |= (uint64_t)(addr & 0x0FFFFF) << 13; + norm |= (uint64_t)(addr & 0x100000) + << (36 - 20); + + instr &= (1 << bit_res) - 1; + instr |= norm << bit_res; + + for (j = 0; j < 6; j++) + buf[i + j + byte_pos] + = (uint8_t)(instr >> (8 * j)); + } + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_ARM +static noinline_for_stack size_t bcj_arm( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t addr; + + for (i = 0; i + 4 <= size; i += 4) { + if (buf[i + 3] == 0xEB) { + addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) + | ((uint32_t)buf[i + 2] << 16); + addr <<= 2; + addr -= s->pos + (uint32_t)i + 8; + addr >>= 2; + buf[i] = (uint8_t)addr; + buf[i + 1] = (uint8_t)(addr >> 8); + buf[i + 2] = (uint8_t)(addr >> 16); + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_ARMTHUMB +static noinline_for_stack size_t bcj_armthumb( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t addr; + + for (i = 0; i + 4 <= size; i += 2) { + if ((buf[i + 1] & 0xF8) == 0xF0 + && (buf[i + 3] & 0xF8) == 0xF8) { + addr = (((uint32_t)buf[i + 1] & 0x07) << 19) + | ((uint32_t)buf[i] << 11) + | (((uint32_t)buf[i + 3] & 0x07) << 8) + | (uint32_t)buf[i + 2]; + addr <<= 1; + addr -= s->pos + (uint32_t)i + 4; + addr >>= 1; + buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07)); + buf[i] = (uint8_t)(addr >> 11); + buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07)); + buf[i + 2] = (uint8_t)addr; + i += 2; + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_SPARC +static noinline_for_stack size_t bcj_sparc( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t instr; + + for (i = 0; i + 4 <= size; i += 4) { + instr = get_unaligned_be32(buf + i); + if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) { + instr <<= 2; + instr -= s->pos + (uint32_t)i; + instr >>= 2; + instr = ((uint32_t)0x40000000 - (instr & 0x400000)) + | 0x40000000 | (instr & 0x3FFFFF); + put_unaligned_be32(instr, buf + i); + } + } + + return i; +} +#endif + +/* + * Apply the selected BCJ filter. Update *pos and s->pos to match the amount + * of data that got filtered. + * + * NOTE: This is implemented as a switch statement to avoid using function + * pointers, which could be problematic in the kernel boot code, which must + * avoid pointers to static data (at least on x86). + */ +static void bcj_apply(struct xz_dec_bcj *s, + uint8_t *buf, size_t *pos, size_t size) +{ + size_t filtered; + + buf += *pos; + size -= *pos; + + switch (s->type) { +#ifdef XZ_DEC_X86 + case BCJ_X86: + filtered = bcj_x86(s, buf, size); + break; +#endif +#ifdef XZ_DEC_POWERPC + case BCJ_POWERPC: + filtered = bcj_powerpc(s, buf, size); + break; +#endif +#ifdef XZ_DEC_IA64 + case BCJ_IA64: + filtered = bcj_ia64(s, buf, size); + break; +#endif +#ifdef XZ_DEC_ARM + case BCJ_ARM: + filtered = bcj_arm(s, buf, size); + break; +#endif +#ifdef XZ_DEC_ARMTHUMB + case BCJ_ARMTHUMB: + filtered = bcj_armthumb(s, buf, size); + break; +#endif +#ifdef XZ_DEC_SPARC + case BCJ_SPARC: + filtered = bcj_sparc(s, buf, size); + break; +#endif + default: + /* Never reached but silence compiler warnings. */ + filtered = 0; + break; + } + + *pos += filtered; + s->pos += filtered; +} + +/* + * Flush pending filtered data from temp to the output buffer. + * Move the remaining mixture of possibly filtered and unfiltered + * data to the beginning of temp. + */ +static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b) +{ + size_t copy_size; + + copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos); + memcpy(b->out + b->out_pos, s->temp.buf, copy_size); + b->out_pos += copy_size; + + s->temp.filtered -= copy_size; + s->temp.size -= copy_size; + memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size); +} + +/* + * The BCJ filter functions are primitive in sense that they process the + * data in chunks of 1-16 bytes. To hide this issue, this function does + * some buffering. + */ +enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, + struct xz_dec_lzma2 *lzma2, struct xz_buf *b) +{ + size_t out_start; + + /* + * Flush pending already filtered data to the output buffer. Return + * immediatelly if we couldn't flush everything, or if the next + * filter in the chain had already returned XZ_STREAM_END. + */ + if (s->temp.filtered > 0) { + bcj_flush(s, b); + if (s->temp.filtered > 0) + return XZ_OK; + + if (s->ret == XZ_STREAM_END) + return XZ_STREAM_END; + } + + /* + * If we have more output space than what is currently pending in + * temp, copy the unfiltered data from temp to the output buffer + * and try to fill the output buffer by decoding more data from the + * next filter in the chain. Apply the BCJ filter on the new data + * in the output buffer. If everything cannot be filtered, copy it + * to temp and rewind the output buffer position accordingly. + */ + if (s->temp.size < b->out_size - b->out_pos) { + out_start = b->out_pos; + memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); + b->out_pos += s->temp.size; + + s->ret = xz_dec_lzma2_run(lzma2, b); + if (s->ret != XZ_STREAM_END + && (s->ret != XZ_OK || s->single_call)) + return s->ret; + + bcj_apply(s, b->out, &out_start, b->out_pos); + + /* + * As an exception, if the next filter returned XZ_STREAM_END, + * we can do that too, since the last few bytes that remain + * unfiltered are meant to remain unfiltered. + */ + if (s->ret == XZ_STREAM_END) + return XZ_STREAM_END; + + s->temp.size = b->out_pos - out_start; + b->out_pos -= s->temp.size; + memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); + } + + /* + * If we have unfiltered data in temp, try to fill by decoding more + * data from the next filter. Apply the BCJ filter on temp. Then we + * hopefully can fill the actual output buffer by copying filtered + * data from temp. A mix of filtered and unfiltered data may be left + * in temp; it will be taken care on the next call to this function. + */ + if (s->temp.size > 0) { + /* Make b->out{,_pos,_size} temporarily point to s->temp. */ + s->out = b->out; + s->out_pos = b->out_pos; + s->out_size = b->out_size; + b->out = s->temp.buf; + b->out_pos = s->temp.size; + b->out_size = sizeof(s->temp.buf); + + s->ret = xz_dec_lzma2_run(lzma2, b); + + s->temp.size = b->out_pos; + b->out = s->out; + b->out_pos = s->out_pos; + b->out_size = s->out_size; + + if (s->ret != XZ_OK && s->ret != XZ_STREAM_END) + return s->ret; + + bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size); + + /* + * If the next filter returned XZ_STREAM_END, we mark that + * everything is filtered, since the last unfiltered bytes + * of the stream are meant to be left as is. + */ + if (s->ret == XZ_STREAM_END) + s->temp.filtered = s->temp.size; + + bcj_flush(s, b); + if (s->temp.filtered > 0) + return XZ_OK; + } + + return s->ret; +} + +#ifdef GRUB_EMBED_DECOMPRESSOR +struct xz_dec_bcj bcj; +#endif + +struct xz_dec_bcj * xz_dec_bcj_create(bool single_call) +{ + struct xz_dec_bcj *s; +#ifdef GRUB_EMBED_DECOMPRESSOR + s = &bcj; +#else + s = kmalloc(sizeof(*s), GFP_KERNEL); +#endif + if (s != NULL) + s->single_call = single_call; + + return s; +} + +enum xz_ret xz_dec_bcj_reset( + struct xz_dec_bcj *s, uint8_t id) +{ + switch (id) { +#ifdef XZ_DEC_X86 + case BCJ_X86: +#endif +#ifdef XZ_DEC_POWERPC + case BCJ_POWERPC: +#endif +#ifdef XZ_DEC_IA64 + case BCJ_IA64: +#endif +#ifdef XZ_DEC_ARM + case BCJ_ARM: +#endif +#ifdef XZ_DEC_ARMTHUMB + case BCJ_ARMTHUMB: +#endif +#ifdef XZ_DEC_SPARC + case BCJ_SPARC: +#endif + break; + + default: + /* Unsupported Filter ID */ + return XZ_OPTIONS_ERROR; + } + + s->type = id; + s->ret = XZ_OK; + s->pos = 0; + s->x86_prev_mask = 0; + s->temp.filtered = 0; + s->temp.size = 0; + + return XZ_OK; +} diff --git a/grub-core/lib/xzembed/xz_dec_lzma2.c b/grub-core/lib/xzembed/xz_dec_lzma2.c new file mode 100644 index 000000000..7899e9e87 --- /dev/null +++ b/grub-core/lib/xzembed/xz_dec_lzma2.c @@ -0,0 +1,1182 @@ +/* xz_dec_lzma2.c - LZMA2 decoder */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#include "xz_private.h" +#include "xz_lzma2.h" + +/* + * Range decoder initialization eats the first five bytes of each LZMA chunk. + */ +#define RC_INIT_BYTES 5 + +/* + * Minimum number of usable input buffer to safely decode one LZMA symbol. + * The worst case is that we decode 22 bits using probabilities and 26 + * direct bits. This may decode at maximum of 20 bytes of input. However, + * lzma_main() does an extra normalization before returning, thus we + * need to put 21 here. + */ +#define LZMA_IN_REQUIRED 21 + +/* + * Dictionary (history buffer) + * + * These are always true: + * start <= pos <= full <= end + * pos <= limit <= end + * + * In multi-call mode, also these are true: + * end == size + * size <= allocated + * + * Most of these variables are size_t to support single-call mode, + * in which the dictionary variables address the actual output + * buffer directly. + */ +struct dictionary { + /* Beginning of the history buffer */ + uint8_t *buf; + + /* Old position in buf (before decoding more data) */ + size_t start; + + /* Position in buf */ + size_t pos; + + /* + * How full dictionary is. This is used to detect corrupt input that + * would read beyond the beginning of the uncompressed stream. + */ + size_t full; + + /* Write limit; we don't write to buf[limit] or later bytes. */ + size_t limit; + + /* + * End of the dictionary buffer. In multi-call mode, this is + * the same as the dictionary size. In single-call mode, this + * indicates the size of the output buffer. + */ + size_t end; + + /* + * Size of the dictionary as specified in Block Header. This is used + * together with "full" to detect corrupt input that would make us + * read beyond the beginning of the uncompressed stream. + */ + uint32_t size; + + /* + * Amount of memory allocated for the dictionary. A special + * value of zero indicates that we are in single-call mode, + * where the output buffer works as the dictionary. + */ + uint32_t allocated; +}; + +/* Range decoder */ +struct rc_dec { + uint32_t range; + uint32_t code; + + /* + * Number of initializing bytes remaining to be read + * by rc_read_init(). + */ + uint32_t init_bytes_left; + + /* + * Buffer from which we read our input. It can be either + * temp.buf or the caller-provided input buffer. + */ + const uint8_t *in; + size_t in_pos; + size_t in_limit; +}; + +/* Probabilities for a length decoder. */ +struct lzma_len_dec { + /* Probability of match length being at least 10 */ + uint16_t choice; + + /* Probability of match length being at least 18 */ + uint16_t choice2; + + /* Probabilities for match lengths 2-9 */ + uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; + + /* Probabilities for match lengths 10-17 */ + uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; + + /* Probabilities for match lengths 18-273 */ + uint16_t high[LEN_HIGH_SYMBOLS]; +}; + +struct lzma_dec { + /* + * LZMA properties or related bit masks (number of literal + * context bits, a mask dervied from the number of literal + * position bits, and a mask dervied from the number + * position bits) + */ + uint32_t lc; + uint32_t literal_pos_mask; /* (1 << lp) - 1 */ + uint32_t pos_mask; /* (1 << pb) - 1 */ + + /* Types of the most recently seen LZMA symbols */ + enum lzma_state state; + + /* Distances of latest four matches */ + uint32_t rep0; + uint32_t rep1; + uint32_t rep2; + uint32_t rep3; + + /* + * Length of a match. This is updated so that dict_repeat can + * be called again to finish repeating the whole match. + */ + uint32_t len; + + /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ + uint16_t is_match[STATES][POS_STATES_MAX]; + + /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ + uint16_t is_rep[STATES]; + + /* + * If 0, distance of a repeated match is rep0. + * Otherwise check is_rep1. + */ + uint16_t is_rep0[STATES]; + + /* + * If 0, distance of a repeated match is rep1. + * Otherwise check is_rep2. + */ + uint16_t is_rep1[STATES]; + + /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ + uint16_t is_rep2[STATES]; + + /* + * If 1, the repeated match has length of one byte. Otherwise + * the length is decoded from rep_len_decoder. + */ + uint16_t is_rep0_long[STATES][POS_STATES_MAX]; + + /* + * Probability tree for the highest two bits of the match + * distance. There is a separate probability tree for match + * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. + */ + uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; + + /* + * Probility trees for additional bits for match distance + * when the distance is in the range [4, 127]. + */ + uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; + + /* + * Probability tree for the lowest four bits of a match + * distance that is equal to or greater than 128. + */ + uint16_t dist_align[ALIGN_SIZE]; + + /* Length of a normal match */ + struct lzma_len_dec match_len_dec; + + /* Length of a repeated match */ + struct lzma_len_dec rep_len_dec; + + /* Probabilities of literals */ + uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; +}; + +struct xz_dec_lzma2 { + /* LZMA2 */ + struct { + /* Position in xz_dec_lzma2_run(). */ + enum lzma2_seq { + SEQ_CONTROL, + SEQ_UNCOMPRESSED_1, + SEQ_UNCOMPRESSED_2, + SEQ_COMPRESSED_0, + SEQ_COMPRESSED_1, + SEQ_PROPERTIES, + SEQ_LZMA_PREPARE, + SEQ_LZMA_RUN, + SEQ_COPY + } sequence; + + /* + * Next position after decoding the compressed size of + * the chunk. + */ + enum lzma2_seq next_sequence; + + /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ + uint32_t uncompressed; + + /* + * Compressed size of LZMA chunk or compressed/uncompressed + * size of uncompressed chunk (64 KiB at maximum) + */ + uint32_t compressed; + + /* + * True if dictionary reset is needed. This is false before + * the first chunk (LZMA or uncompressed). + */ + bool need_dict_reset; + + /* + * True if new LZMA properties are needed. This is false + * before the first LZMA chunk. + */ + bool need_props; + } lzma2; + + /* + * Temporary buffer which holds small number of input bytes between + * decoder calls. See lzma2_lzma() for details. + */ + struct { + uint32_t size; + uint8_t buf[3 * LZMA_IN_REQUIRED]; + } temp; + + struct dictionary dict; + struct rc_dec rc; + struct lzma_dec lzma; +}; + +/************** + * Dictionary * + **************/ + +/* + * Reset the dictionary state. When in single-call mode, set up the beginning + * of the dictionary to point to the actual output buffer. + */ +static void dict_reset(struct dictionary *dict, struct xz_buf *b) +{ + if (dict->allocated == 0) { + dict->buf = b->out + b->out_pos; + dict->end = b->out_size - b->out_pos; + } + dict->start = 0; + dict->pos = 0; + dict->limit = 0; + dict->full = 0; +} + +/* Set dictionary write limit */ +static void dict_limit(struct dictionary *dict, size_t out_max) +{ + if (dict->end - dict->pos <= out_max) + dict->limit = dict->end; + else + dict->limit = dict->pos + out_max; +} + +/* Return true if at least one byte can be written into the dictionary. */ +static inline bool dict_has_space(const struct dictionary *dict) +{ + return dict->pos < dict->limit; +} + +/* + * Get a byte from the dictionary at the given distance. The distance is + * assumed to valid, or as a special case, zero when the dictionary is + * still empty. This special case is needed for single-call decoding to + * avoid writing a '\0' to the end of the destination buffer. + */ +static inline uint32_t dict_get( + const struct dictionary *dict, uint32_t dist) +{ + size_t offset = dict->pos - dist - 1; + + if (dist >= dict->pos) + offset += dict->end; + + return dict->full > 0 ? dict->buf[offset] : 0; +} + +/* + * Put one byte into the dictionary. It is assumed that there is space for it. + */ +static inline void dict_put(struct dictionary *dict, uint8_t byte) +{ + dict->buf[dict->pos++] = byte; + + if (dict->full < dict->pos) + dict->full = dict->pos; +} + +/* + * Repeat given number of bytes from the given distance. If the distance is + * invalid, false is returned. On success, true is returned and *len is + * updated to indicate how many bytes were left to be repeated. + */ +static bool dict_repeat( + struct dictionary *dict, uint32_t *len, uint32_t dist) +{ + size_t back; + uint32_t left; + + if (dist >= dict->full || dist >= dict->size) + return false; + + left = min_t(size_t, dict->limit - dict->pos, *len); + *len -= left; + + back = dict->pos - dist - 1; + if (dist >= dict->pos) + back += dict->end; + + do { + dict->buf[dict->pos++] = dict->buf[back++]; + if (back == dict->end) + back = 0; + } while (--left > 0); + + if (dict->full < dict->pos) + dict->full = dict->pos; + + return true; +} + +/* Copy uncompressed data as is from input to dictionary and output buffers. */ +static void dict_uncompressed( + struct dictionary *dict, struct xz_buf *b, uint32_t *left) +{ + size_t copy_size; + + while (*left > 0 && b->in_pos < b->in_size + && b->out_pos < b->out_size) { + copy_size = min(b->in_size - b->in_pos, + b->out_size - b->out_pos); + if (copy_size > dict->end - dict->pos) + copy_size = dict->end - dict->pos; + if (copy_size > *left) + copy_size = *left; + + *left -= copy_size; + + memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); + dict->pos += copy_size; + + if (dict->full < dict->pos) + dict->full = dict->pos; + + if (dict->allocated != 0) { + if (dict->pos == dict->end) + dict->pos = 0; + + memcpy(b->out + b->out_pos, b->in + b->in_pos, + copy_size); + } + + dict->start = dict->pos; + + b->out_pos += copy_size; + b->in_pos += copy_size; + + } +} + +/* + * Flush pending data from dictionary to b->out. It is assumed that there is + * enough space in b->out. This is guaranteed because caller uses dict_limit() + * before decoding data into the dictionary. + */ +static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) +{ + size_t copy_size = dict->pos - dict->start; + + if (dict->allocated != 0) { + if (dict->pos == dict->end) + dict->pos = 0; + + memcpy(b->out + b->out_pos, dict->buf + dict->start, + copy_size); + } + + dict->start = dict->pos; + b->out_pos += copy_size; + return copy_size; +} + +/***************** + * Range decoder * + *****************/ + +/* Reset the range decoder. */ +static void rc_reset(struct rc_dec *rc) +{ + rc->range = (uint32_t)-1; + rc->code = 0; + rc->init_bytes_left = RC_INIT_BYTES; +} + +/* + * Read the first five initial bytes into rc->code if they haven't been + * read already. (Yes, the first byte gets completely ignored.) + */ +static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b) +{ + while (rc->init_bytes_left > 0) { + if (b->in_pos == b->in_size) + return false; + + rc->code = (rc->code << 8) + b->in[b->in_pos++]; + --rc->init_bytes_left; + } + + return true; +} + +/* Return true if there may not be enough input for the next decoding loop. */ +static inline bool rc_limit_exceeded(const struct rc_dec *rc) +{ + return rc->in_pos > rc->in_limit; +} + +/* + * Return true if it is possible (from point of view of range decoder) that + * we have reached the end of the LZMA chunk. + */ +static inline bool rc_is_finished(const struct rc_dec *rc) +{ + return rc->code == 0; +} + +/* Read the next input byte if needed. */ +static __always_inline void rc_normalize(struct rc_dec *rc) +{ + if (rc->range < RC_TOP_VALUE) { + rc->range <<= RC_SHIFT_BITS; + rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; + } +} + +/* + * Decode one bit. In some versions, this function has been splitted in three + * functions so that the compiler is supposed to be able to more easily avoid + * an extra branch. In this particular version of the LZMA decoder, this + * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 + * on x86). Using a non-splitted version results in nicer looking code too. + * + * NOTE: This must return an int. Do not make it return a bool or the speed + * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, + * and it generates 10-20 % faster code than GCC 3.x from this file anyway.) + */ +static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob) +{ + uint32_t bound; + int bit; + + rc_normalize(rc); + bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; + if (rc->code < bound) { + rc->range = bound; + *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; + bit = 0; + } else { + rc->range -= bound; + rc->code -= bound; + *prob -= *prob >> RC_MOVE_BITS; + bit = 1; + } + + return bit; +} + +/* Decode a bittree starting from the most significant bit. */ +static __always_inline uint32_t rc_bittree( + struct rc_dec *rc, uint16_t *probs, uint32_t limit) +{ + uint32_t symbol = 1; + + do { + if (rc_bit(rc, &probs[symbol])) + symbol = (symbol << 1) + 1; + else + symbol <<= 1; + } while (symbol < limit); + + return symbol; +} + +/* Decode a bittree starting from the least significant bit. */ +static __always_inline void rc_bittree_reverse(struct rc_dec *rc, + uint16_t *probs, uint32_t *dest, uint32_t limit) +{ + uint32_t symbol = 1; + uint32_t i = 0; + + do { + if (rc_bit(rc, &probs[symbol])) { + symbol = (symbol << 1) + 1; + *dest += 1 << i; + } else { + symbol <<= 1; + } + } while (++i < limit); +} + +/* Decode direct bits (fixed fifty-fifty probability) */ +static inline void rc_direct( + struct rc_dec *rc, uint32_t *dest, uint32_t limit) +{ + uint32_t mask; + + do { + rc_normalize(rc); + rc->range >>= 1; + rc->code -= rc->range; + mask = (uint32_t)0 - (rc->code >> 31); + rc->code += rc->range & mask; + *dest = (*dest << 1) + (mask + 1); + } while (--limit > 0); +} + +/******** + * LZMA * + ********/ + +/* Get pointer to literal coder probability array. */ +static uint16_t * lzma_literal_probs(struct xz_dec_lzma2 *s) +{ + uint32_t prev_byte = dict_get(&s->dict, 0); + uint32_t low = prev_byte >> (8 - s->lzma.lc); + uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; + return s->lzma.literal[low + high]; +} + +/* Decode a literal (one 8-bit byte) */ +static void lzma_literal(struct xz_dec_lzma2 *s) +{ + uint16_t *probs; + uint32_t symbol; + uint32_t match_byte; + uint32_t match_bit; + uint32_t offset; + uint32_t i; + + probs = lzma_literal_probs(s); + + if (lzma_state_is_literal(s->lzma.state)) { + symbol = rc_bittree(&s->rc, probs, 0x100); + } else { + symbol = 1; + match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; + offset = 0x100; + + do { + match_bit = match_byte & offset; + match_byte <<= 1; + i = offset + match_bit + symbol; + + if (rc_bit(&s->rc, &probs[i])) { + symbol = (symbol << 1) + 1; + offset &= match_bit; + } else { + symbol <<= 1; + offset &= ~match_bit; + } + } while (symbol < 0x100); + } + + dict_put(&s->dict, (uint8_t)symbol); + lzma_state_literal(&s->lzma.state); +} + +/* Decode the length of the match into s->lzma.len. */ +static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, + uint32_t pos_state) +{ + uint16_t *probs; + uint32_t limit; + + if (!rc_bit(&s->rc, &l->choice)) { + probs = l->low[pos_state]; + limit = LEN_LOW_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN; + } else { + if (!rc_bit(&s->rc, &l->choice2)) { + probs = l->mid[pos_state]; + limit = LEN_MID_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; + } else { + probs = l->high; + limit = LEN_HIGH_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + + LEN_MID_SYMBOLS; + } + } + + s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; +} + +/* Decode a match. The distance will be stored in s->lzma.rep0. */ +static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) +{ + uint16_t *probs; + uint32_t dist_slot; + uint32_t limit; + + lzma_state_match(&s->lzma.state); + + s->lzma.rep3 = s->lzma.rep2; + s->lzma.rep2 = s->lzma.rep1; + s->lzma.rep1 = s->lzma.rep0; + + lzma_len(s, &s->lzma.match_len_dec, pos_state); + + probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; + dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; + + if (dist_slot < DIST_MODEL_START) { + s->lzma.rep0 = dist_slot; + } else { + limit = (dist_slot >> 1) - 1; + s->lzma.rep0 = 2 + (dist_slot & 1); + + if (dist_slot < DIST_MODEL_END) { + s->lzma.rep0 <<= limit; + probs = s->lzma.dist_special + s->lzma.rep0 + - dist_slot - 1; + rc_bittree_reverse(&s->rc, probs, + &s->lzma.rep0, limit); + } else { + rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); + s->lzma.rep0 <<= ALIGN_BITS; + rc_bittree_reverse(&s->rc, s->lzma.dist_align, + &s->lzma.rep0, ALIGN_BITS); + } + } +} + +/* + * Decode a repeated match. The distance is one of the four most recently + * seen matches. The distance will be stored in s->lzma.rep0. + */ +static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) +{ + uint32_t tmp; + + if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { + if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ + s->lzma.state][pos_state])) { + lzma_state_short_rep(&s->lzma.state); + s->lzma.len = 1; + return; + } + } else { + if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { + tmp = s->lzma.rep1; + } else { + if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { + tmp = s->lzma.rep2; + } else { + tmp = s->lzma.rep3; + s->lzma.rep3 = s->lzma.rep2; + } + + s->lzma.rep2 = s->lzma.rep1; + } + + s->lzma.rep1 = s->lzma.rep0; + s->lzma.rep0 = tmp; + } + + lzma_state_long_rep(&s->lzma.state); + lzma_len(s, &s->lzma.rep_len_dec, pos_state); +} + +/* LZMA decoder core */ +static bool lzma_main(struct xz_dec_lzma2 *s) +{ + uint32_t pos_state; + + /* + * If the dictionary was reached during the previous call, try to + * finish the possibly pending repeat in the dictionary. + */ + if (dict_has_space(&s->dict) && s->lzma.len > 0) + dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); + + /* + * Decode more LZMA symbols. One iteration may consume up to + * LZMA_IN_REQUIRED - 1 bytes. + */ + while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { + pos_state = s->dict.pos & s->lzma.pos_mask; + + if (!rc_bit(&s->rc, &s->lzma.is_match[ + s->lzma.state][pos_state])) { + lzma_literal(s); + } else { + if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) + lzma_rep_match(s, pos_state); + else + lzma_match(s, pos_state); + + if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) + return false; + } + } + + /* + * Having the range decoder always normalized when we are outside + * this function makes it easier to correctly handle end of the chunk. + */ + rc_normalize(&s->rc); + + return true; +} + +/* + * Reset the LZMA decoder and range decoder state. Dictionary is nore reset + * here, because LZMA state may be reset without resetting the dictionary. + */ +static void lzma_reset(struct xz_dec_lzma2 *s) +{ + uint16_t *probs; + size_t i; + + s->lzma.state = STATE_LIT_LIT; + s->lzma.rep0 = 0; + s->lzma.rep1 = 0; + s->lzma.rep2 = 0; + s->lzma.rep3 = 0; + + /* + * All probabilities are initialized to the same value. This hack + * makes the code smaller by avoiding a separate loop for each + * probability array. + * + * This could be optimized so that only that part of literal + * probabilities that are actually required. In the common case + * we would write 12 KiB less. + */ + probs = s->lzma.is_match[0]; + for (i = 0; i < PROBS_TOTAL; ++i) + probs[i] = RC_BIT_MODEL_TOTAL / 2; + + rc_reset(&s->rc); +} + +/* + * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks + * from the decoded lp and pb values. On success, the LZMA decoder state is + * reset and true is returned. + */ +static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props) +{ + if (props > (4 * 5 + 4) * 9 + 8) + return false; + + s->lzma.pos_mask = 0; + while (props >= 9 * 5) { + props -= 9 * 5; + ++s->lzma.pos_mask; + } + + s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; + + s->lzma.literal_pos_mask = 0; + while (props >= 9) { + props -= 9; + ++s->lzma.literal_pos_mask; + } + + s->lzma.lc = props; + + if (s->lzma.lc + s->lzma.literal_pos_mask > 4) + return false; + + s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; + + lzma_reset(s); + + return true; +} + +/********* + * LZMA2 * + *********/ + +/* + * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't + * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This + * wrapper function takes care of making the LZMA decoder's assumption safe. + * + * As long as there is plenty of input left to be decoded in the current LZMA + * chunk, we decode directly from the caller-supplied input buffer until + * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into + * s->temp.buf, which (hopefully) gets filled on the next call to this + * function. We decode a few bytes from the temporary buffer so that we can + * continue decoding from the caller-supplied input buffer again. + */ +static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) +{ + size_t in_avail; + uint32_t tmp; + + in_avail = b->in_size - b->in_pos; + if (s->temp.size > 0 || s->lzma2.compressed == 0) { + tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; + if (tmp > s->lzma2.compressed - s->temp.size) + tmp = s->lzma2.compressed - s->temp.size; + if (tmp > in_avail) + tmp = in_avail; + + memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); + + if (s->temp.size + tmp == s->lzma2.compressed) { + memzero(s->temp.buf + s->temp.size + tmp, + sizeof(s->temp.buf) + - s->temp.size - tmp); + s->rc.in_limit = s->temp.size + tmp; + } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) { + s->temp.size += tmp; + b->in_pos += tmp; + return true; + } else { + s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; + } + + s->rc.in = s->temp.buf; + s->rc.in_pos = 0; + + if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) + return false; + + s->lzma2.compressed -= s->rc.in_pos; + + if (s->rc.in_pos < s->temp.size) { + s->temp.size -= s->rc.in_pos; + memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, + s->temp.size); + return true; + } + + b->in_pos += s->rc.in_pos - s->temp.size; + s->temp.size = 0; + } + + in_avail = b->in_size - b->in_pos; + if (in_avail >= LZMA_IN_REQUIRED) { + s->rc.in = b->in; + s->rc.in_pos = b->in_pos; + + if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) + s->rc.in_limit = b->in_pos + s->lzma2.compressed; + else + s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; + + if (!lzma_main(s)) + return false; + + in_avail = s->rc.in_pos - b->in_pos; + if (in_avail > s->lzma2.compressed) + return false; + + s->lzma2.compressed -= in_avail; + b->in_pos = s->rc.in_pos; + } + + in_avail = b->in_size - b->in_pos; + if (in_avail < LZMA_IN_REQUIRED) { + if (in_avail > s->lzma2.compressed) + in_avail = s->lzma2.compressed; + + memcpy(s->temp.buf, b->in + b->in_pos, in_avail); + s->temp.size = in_avail; + b->in_pos += in_avail; + } + + return true; +} + +/* + * Take care of the LZMA2 control layer, and forward the job of actual LZMA + * decoding or copying of uncompressed chunks to other functions. + */ +enum xz_ret xz_dec_lzma2_run( + struct xz_dec_lzma2 *s, struct xz_buf *b) +{ + uint32_t tmp; + + while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) { + switch (s->lzma2.sequence) { + case SEQ_CONTROL: + /* + * LZMA2 control byte + * + * Exact values: + * 0x00 End marker + * 0x01 Dictionary reset followed by + * an uncompressed chunk + * 0x02 Uncompressed chunk (no dictionary reset) + * + * Highest three bits (s->control & 0xE0): + * 0xE0 Dictionary reset, new properties and state + * reset, followed by LZMA compressed chunk + * 0xC0 New properties and state reset, followed + * by LZMA compressed chunk (no dictionary + * reset) + * 0xA0 State reset using old properties, + * followed by LZMA compressed chunk (no + * dictionary reset) + * 0x80 LZMA chunk (no dictionary or state reset) + * + * For LZMA compressed chunks, the lowest five bits + * (s->control & 1F) are the highest bits of the + * uncompressed size (bits 16-20). + * + * A new LZMA2 stream must begin with a dictionary + * reset. The first LZMA chunk must set new + * properties and reset the LZMA state. + * + * Values that don't match anything described above + * are invalid and we return XZ_DATA_ERROR. + */ + tmp = b->in[b->in_pos++]; + + if (tmp >= 0xE0 || tmp == 0x01) { + s->lzma2.need_props = true; + s->lzma2.need_dict_reset = false; + dict_reset(&s->dict, b); + } else if (s->lzma2.need_dict_reset) { + return XZ_DATA_ERROR; + } + + if (tmp >= 0x80) { + s->lzma2.uncompressed = (tmp & 0x1F) << 16; + s->lzma2.sequence = SEQ_UNCOMPRESSED_1; + + if (tmp >= 0xC0) { + /* + * When there are new properties, + * state reset is done at + * SEQ_PROPERTIES. + */ + s->lzma2.need_props = false; + s->lzma2.next_sequence + = SEQ_PROPERTIES; + + } else if (s->lzma2.need_props) { + return XZ_DATA_ERROR; + + } else { + s->lzma2.next_sequence + = SEQ_LZMA_PREPARE; + if (tmp >= 0xA0) + lzma_reset(s); + } + } else { + if (tmp == 0x00) + return XZ_STREAM_END; + + if (tmp > 0x02) + return XZ_DATA_ERROR; + + s->lzma2.sequence = SEQ_COMPRESSED_0; + s->lzma2.next_sequence = SEQ_COPY; + } + + break; + + case SEQ_UNCOMPRESSED_1: + s->lzma2.uncompressed + += (uint32_t)b->in[b->in_pos++] << 8; + s->lzma2.sequence = SEQ_UNCOMPRESSED_2; + break; + + case SEQ_UNCOMPRESSED_2: + s->lzma2.uncompressed + += (uint32_t)b->in[b->in_pos++] + 1; + s->lzma2.sequence = SEQ_COMPRESSED_0; + break; + + case SEQ_COMPRESSED_0: + s->lzma2.compressed + = (uint32_t)b->in[b->in_pos++] << 8; + s->lzma2.sequence = SEQ_COMPRESSED_1; + break; + + case SEQ_COMPRESSED_1: + s->lzma2.compressed + += (uint32_t)b->in[b->in_pos++] + 1; + s->lzma2.sequence = s->lzma2.next_sequence; + break; + + case SEQ_PROPERTIES: + if (!lzma_props(s, b->in[b->in_pos++])) + return XZ_DATA_ERROR; + + s->lzma2.sequence = SEQ_LZMA_PREPARE; + + case SEQ_LZMA_PREPARE: + if (s->lzma2.compressed < RC_INIT_BYTES) + return XZ_DATA_ERROR; + + if (!rc_read_init(&s->rc, b)) + return XZ_OK; + + s->lzma2.compressed -= RC_INIT_BYTES; + s->lzma2.sequence = SEQ_LZMA_RUN; + + case SEQ_LZMA_RUN: + /* + * Set dictionary limit to indicate how much we want + * to be encoded at maximum. Decode new data into the + * dictionary. Flush the new data from dictionary to + * b->out. Check if we finished decoding this chunk. + * In case the dictionary got full but we didn't fill + * the output buffer yet, we may run this loop + * multiple times without changing s->lzma2.sequence. + */ + dict_limit(&s->dict, min_t(size_t, + b->out_size - b->out_pos, + s->lzma2.uncompressed)); + if (!lzma2_lzma(s, b)) + return XZ_DATA_ERROR; + + s->lzma2.uncompressed -= dict_flush(&s->dict, b); + + if (s->lzma2.uncompressed == 0) { + if (s->lzma2.compressed > 0 || s->lzma.len > 0 + || !rc_is_finished(&s->rc)) + return XZ_DATA_ERROR; + + rc_reset(&s->rc); + s->lzma2.sequence = SEQ_CONTROL; + + } else if (b->out_pos == b->out_size + || (b->in_pos == b->in_size + && s->temp.size + < s->lzma2.compressed)) { + return XZ_OK; + } + + break; + + case SEQ_COPY: + dict_uncompressed(&s->dict, b, &s->lzma2.compressed); + if (s->lzma2.compressed > 0) + return XZ_OK; + + s->lzma2.sequence = SEQ_CONTROL; + break; + } + } + + return XZ_OK; +} + +#ifdef GRUB_EMBED_DECOMPRESSOR +#include +static struct xz_dec_lzma2 lzma2; +#endif + +struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max) +{ + struct xz_dec_lzma2 *s; + +#ifndef GRUB_EMBED_DECOMPRESSOR + /* Maximum supported dictionary by this implementation is 3 GiB. */ + if (dict_max > ((uint32_t)3 << 30)) + return NULL; + + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; + + if (dict_max > 0) { + s->dict.buf = vmalloc(dict_max); + if (s->dict.buf == NULL) { + kfree(s); + return NULL; + } + } + +#else + s = &lzma2; + s->dict.buf = grub_decompressor_scratch; +#endif + + s->dict.allocated = dict_max; + + return s; +} + +enum xz_ret xz_dec_lzma2_reset( + struct xz_dec_lzma2 *s, uint8_t props) +{ + /* This limits dictionary size to 3 GiB (39) to keep parsing simpler. */ + if (props > ( min (DICT_BIT_SIZE,39)) ) + return XZ_OPTIONS_ERROR; + + s->dict.size = 2 + (props & 1); + s->dict.size <<= (props >> 1) + 11; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) + { + /* enlarge dictionary buffer */ + uint8_t * newdict = realloc(s->dict.buf,s->dict.size); + + if (! newdict) + return XZ_MEMLIMIT_ERROR; + + s->dict.buf = newdict; + s->dict.allocated = s->dict.size; + } +#endif + s->dict.end = s->dict.size; + + s->lzma.len = 0; + + s->lzma2.sequence = SEQ_CONTROL; + s->lzma2.need_dict_reset = true; + + s->temp.size = 0; + + return XZ_OK; +} + +void xz_dec_lzma2_end(struct xz_dec_lzma2 *s __attribute__ ((unused))) +{ +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->dict.allocated > 0) + vfree(s->dict.buf); + + kfree(s); +#endif +} diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c new file mode 100644 index 000000000..3bf201d50 --- /dev/null +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -0,0 +1,919 @@ +/* xz_dec_stream.c - .xz Stream decoder */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#include "xz_config.h" +#include "xz_private.h" +#include "xz_stream.h" + +#include + +/* Hash used to validate the Index field */ +struct xz_dec_hash { + vli_type unpadded; + vli_type uncompressed; +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t *crc32_context; +#endif +}; + +struct xz_dec { + /* Position in dec_main() */ + enum { + SEQ_STREAM_HEADER, + SEQ_BLOCK_START, + SEQ_BLOCK_HEADER, + SEQ_BLOCK_UNCOMPRESS, + SEQ_BLOCK_PADDING, + SEQ_BLOCK_CHECK, + SEQ_INDEX, + SEQ_INDEX_PADDING, + SEQ_INDEX_CRC32, + SEQ_STREAM_FOOTER + } sequence; + + /* Position in variable-length integers and Check fields */ + uint32_t pos; + + /* Variable-length integer decoded by dec_vli() */ + vli_type vli; + + /* Saved in_pos and out_pos */ + size_t in_start; + size_t out_start; + + /* CRC32 value in Block or Index */ + uint32_t crc32_temp; /* need for crc32_validate*/ + uint8_t *crc32_context; + + /* True if CRC32 is calculated from uncompressed data */ + bool has_crc32; + + /* True if we are operating in single-call mode. */ + bool single_call; + + /* + * True if the next call to xz_dec_run() is allowed to return + * XZ_BUF_ERROR. + */ + bool allow_buf_error; + + /* Information stored in Block Header */ + struct { + /* + * Value stored in the Compressed Size field, or + * VLI_UNKNOWN if Compressed Size is not present. + */ + vli_type compressed; + + /* + * Value stored in the Uncompressed Size field, or + * VLI_UNKNOWN if Uncompressed Size is not present. + */ + vli_type uncompressed; + + /* Size of the Block Header field */ + uint32_t size; + } block_header; + + /* Information collected when decoding Blocks */ + struct { + /* Observed compressed size of the current Block */ + vli_type compressed; + + /* Observed uncompressed size of the current Block */ + vli_type uncompressed; + + /* Number of Blocks decoded so far */ + vli_type count; + + /* + * Hash calculated from the Block sizes. This is used to + * validate the Index field. + */ + struct xz_dec_hash hash; + } block; + + /* Variables needed when verifying the Index field */ + struct { + /* Position in dec_index() */ + enum { + SEQ_INDEX_COUNT, + SEQ_INDEX_UNPADDED, + SEQ_INDEX_UNCOMPRESSED + } sequence; + + /* Size of the Index in bytes */ + vli_type size; + + /* Number of Records (matches block.count in valid files) */ + vli_type count; + + /* + * Hash calculated from the Records (matches block.hash in + * valid files). + */ + struct xz_dec_hash hash; + } index; + + /* + * Temporary buffer needed to hold Stream Header, Block Header, + * and Stream Footer. The Block Header is the biggest (1 KiB) + * so we reserve space according to that. buf[] has to be aligned + * to a multiple of four bytes; the size_t variables before it + * should guarantee this. + */ + struct { + size_t pos; + size_t size; + uint8_t buf[1024]; + } temp; + + struct xz_dec_lzma2 *lzma2; + +#ifdef XZ_DEC_BCJ + struct xz_dec_bcj *bcj; + bool bcj_active; +#endif +}; + +/* + * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller + * must have set s->temp.pos to indicate how much data we are supposed + * to copy into s->temp.buf. Return true once s->temp.pos has reached + * s->temp.size. + */ +static bool fill_temp(struct xz_dec *s, struct xz_buf *b) +{ + size_t copy_size = min_t(size_t, + b->in_size - b->in_pos, s->temp.size - s->temp.pos); + + memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size); + b->in_pos += copy_size; + s->temp.pos += copy_size; + + if (s->temp.pos == s->temp.size) { + s->temp.pos = 0; + return true; + } + + return false; +} + +/* Decode a variable-length integer (little-endian base-128 encoding) */ +static enum xz_ret dec_vli(struct xz_dec *s, + const uint8_t *in, size_t *in_pos, size_t in_size) +{ + uint8_t byte; + + if (s->pos == 0) + s->vli = 0; + + while (*in_pos < in_size) { + byte = in[*in_pos]; + ++*in_pos; + + s->vli |= (vli_type)(byte & 0x7F) << s->pos; + + if ((byte & 0x80) == 0) { + /* Don't allow non-minimal encodings. */ + if (byte == 0 && s->pos != 0) + return XZ_DATA_ERROR; + + s->pos = 0; + return XZ_STREAM_END; + } + + s->pos += 7; + if (s->pos == 7 * VLI_BYTES_MAX) + return XZ_DATA_ERROR; + } + + return XZ_OK; +} + +/* + * Decode the Compressed Data field from a Block. Update and validate + * the observed compressed and uncompressed sizes of the Block so that + * they don't exceed the values possibly stored in the Block Header + * (validation assumes that no integer overflow occurs, since vli_type + * is normally uint64_t). Update the CRC32 if presence of the CRC32 + * field was indicated in Stream Header. + * + * Once the decoding is finished, validate that the observed sizes match + * the sizes possibly stored in the Block Header. Update the hash and + * Block count, which are later used to validate the Index field. + */ +static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) +{ + enum xz_ret ret; + + s->in_start = b->in_pos; + s->out_start = b->out_pos; + +#ifdef XZ_DEC_BCJ + if (s->bcj_active) + ret = xz_dec_bcj_run(s->bcj, s->lzma2, b); + else +#endif + ret = xz_dec_lzma2_run(s->lzma2, b); + + s->block.compressed += b->in_pos - s->in_start; + s->block.uncompressed += b->out_pos - s->out_start; + + /* + * There is no need to separately check for VLI_UNKNOWN, since + * the observed sizes are always smaller than VLI_UNKNOWN. + */ + if (s->block.compressed > s->block_header.compressed + || s->block.uncompressed + > s->block_header.uncompressed) + return XZ_DATA_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->has_crc32) + GRUB_MD_CRC32->write(s->crc32_context,b->out + s->out_start, + b->out_pos - s->out_start); +#endif + + if (ret == XZ_STREAM_END) { + if (s->block_header.compressed != VLI_UNKNOWN + && s->block_header.compressed + != s->block.compressed) + return XZ_DATA_ERROR; + + if (s->block_header.uncompressed != VLI_UNKNOWN + && s->block_header.uncompressed + != s->block.uncompressed) + return XZ_DATA_ERROR; + + s->block.hash.unpadded += s->block_header.size + + s->block.compressed; + if (s->has_crc32) + s->block.hash.unpadded += 4; + + s->block.hash.uncompressed += s->block.uncompressed; + +#ifndef GRUB_EMBED_DECOMPRESSOR + GRUB_MD_CRC32->write(s->block.hash.crc32_context, + (const uint8_t *)&s->block.hash, 2 * sizeof(vli_type)); +#endif + + ++s->block.count; + } + + return ret; +} + +/* Update the Index size and the CRC32 value. */ +static void index_update(struct xz_dec *s, const struct xz_buf *b) +{ + size_t in_used = b->in_pos - s->in_start; + s->index.size += in_used; +#ifndef GRUB_EMBED_DECOMPRESSOR + GRUB_MD_CRC32->write(s->crc32_context,b->in + s->in_start, in_used); +#endif +} + +/* + * Decode the Number of Records, Unpadded Size, and Uncompressed Size + * fields from the Index field. That is, Index Padding and CRC32 are not + * decoded by this function. + * + * This can return XZ_OK (more input needed), XZ_STREAM_END (everything + * successfully decoded), or XZ_DATA_ERROR (input is corrupt). + */ +static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) +{ + enum xz_ret ret; + + do { + ret = dec_vli(s, b->in, &b->in_pos, b->in_size); + if (ret != XZ_STREAM_END) { + index_update(s, b); + return ret; + } + + switch (s->index.sequence) { + case SEQ_INDEX_COUNT: + s->index.count = s->vli; + + /* + * Validate that the Number of Records field + * indicates the same number of Records as + * there were Blocks in the Stream. + */ + if (s->index.count != s->block.count) + return XZ_DATA_ERROR; + + s->index.sequence = SEQ_INDEX_UNPADDED; + break; + + case SEQ_INDEX_UNPADDED: + s->index.hash.unpadded += s->vli; + s->index.sequence = SEQ_INDEX_UNCOMPRESSED; + break; + + case SEQ_INDEX_UNCOMPRESSED: + s->index.hash.uncompressed += s->vli; + +#ifndef GRUB_EMBED_DECOMPRESSOR + GRUB_MD_CRC32->write(s->index.hash.crc32_context, + (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); +#endif + + --s->index.count; + s->index.sequence = SEQ_INDEX_UNPADDED; + break; + } + } while (s->index.count > 0); + + return XZ_STREAM_END; +} + +/* + * Validate that the next four input bytes match the value of s->crc32. + * s->pos must be zero when starting to validate the first byte. + */ +static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b) +{ +#ifndef GRUB_EMBED_DECOMPRESSOR + if(s->crc32_temp == 0) + { + GRUB_MD_CRC32->final(s->crc32_context); + s->crc32_temp = get_unaligned_be32(GRUB_MD_CRC32->read(s->crc32_context)); + } +#endif + + do { + if (b->in_pos == b->in_size) + return XZ_OK; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (((s->crc32_temp >> s->pos) & 0xFF) != b->in[b->in_pos++]) + return XZ_DATA_ERROR; +#endif + + s->pos += 8; + + } while (s->pos < 32); + +#ifndef GRUB_EMBED_DECOMPRESSOR + GRUB_MD_CRC32->init(s->crc32_context); +#endif + s->crc32_temp = 0; + s->pos = 0; + + return XZ_STREAM_END; +} + +/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ +static enum xz_ret dec_stream_header(struct xz_dec *s) +{ + if (! memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) + return XZ_FORMAT_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + + GRUB_MD_CRC32->init(crc32_context); + GRUB_MD_CRC32->write(crc32_context,s->temp.buf + HEADER_MAGIC_SIZE, 2); + GRUB_MD_CRC32->final(crc32_context); + + uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context)); + uint32_t readcrc = get_unaligned_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2); + + if(resultcrc != readcrc) + return XZ_DATA_ERROR; +#endif + + /* + * Decode the Stream Flags field. Of integrity checks, we support + * only none (Check ID = 0) and CRC32 (Check ID = 1). + */ + if (s->temp.buf[HEADER_MAGIC_SIZE] != 0 + || s->temp.buf[HEADER_MAGIC_SIZE + 1] > 1) + return XZ_OPTIONS_ERROR; + + s->has_crc32 = s->temp.buf[HEADER_MAGIC_SIZE + 1]; + + return XZ_OK; +} + +/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */ +static enum xz_ret dec_stream_footer(struct xz_dec *s) +{ + if (! memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) + return XZ_DATA_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + + GRUB_MD_CRC32->init(crc32_context); + GRUB_MD_CRC32->write(crc32_context, s->temp.buf + 4, 6); + GRUB_MD_CRC32->final(crc32_context); + + uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context)); + uint32_t readcrc = get_unaligned_le32(s->temp.buf); + + if(resultcrc != readcrc) + return XZ_DATA_ERROR; +#endif + + /* + * Validate Backward Size. Note that we never added the size of the + * Index CRC32 field to s->index.size, thus we use s->index.size / 4 + * instead of s->index.size / 4 - 1. + */ + if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) + return XZ_DATA_ERROR; + + if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->has_crc32) + return XZ_DATA_ERROR; + + /* + * Use XZ_STREAM_END instead of XZ_OK to be more convenient + * for the caller. + */ + return XZ_STREAM_END; +} + +/* Decode the Block Header and initialize the filter chain. */ +static enum xz_ret dec_block_header(struct xz_dec *s) +{ + enum xz_ret ret; + + /* + * Validate the CRC32. We know that the temp buffer is at least + * eight bytes so this is safe. + */ + s->temp.size -= 4; +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + + GRUB_MD_CRC32->init(crc32_context); + GRUB_MD_CRC32->write(crc32_context, s->temp.buf, s->temp.size); + GRUB_MD_CRC32->final(crc32_context); + + uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context)); + uint32_t readcrc = get_unaligned_le32(s->temp.buf + s->temp.size); + + if (resultcrc != readcrc) + return XZ_DATA_ERROR; +#endif + + s->temp.pos = 2; + + /* + * Catch unsupported Block Flags. We support only one or two filters + * in the chain, so we catch that with the same test. + */ +#ifdef XZ_DEC_BCJ + if (s->temp.buf[1] & 0x3E) +#else + if (s->temp.buf[1] & 0x3F) +#endif + return XZ_OPTIONS_ERROR; + + /* Compressed Size */ + if (s->temp.buf[1] & 0x40) { + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) + != XZ_STREAM_END) + return XZ_DATA_ERROR; + + s->block_header.compressed = s->vli; + } else { + s->block_header.compressed = VLI_UNKNOWN; + } + + /* Uncompressed Size */ + if (s->temp.buf[1] & 0x80) { + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) + != XZ_STREAM_END) + return XZ_DATA_ERROR; + + s->block_header.uncompressed = s->vli; + } else { + s->block_header.uncompressed = VLI_UNKNOWN; + } + +#ifdef XZ_DEC_BCJ + /* If there are two filters, the first one must be a BCJ filter. */ + s->bcj_active = s->temp.buf[1] & 0x01; + if (s->bcj_active) { + if (s->temp.size - s->temp.pos < 2) + return XZ_OPTIONS_ERROR; + + ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]); + if (ret != XZ_OK) + return ret; + + /* + * We don't support custom start offset, + * so Size of Properties must be zero. + */ + if (s->temp.buf[s->temp.pos++] != 0x00) + return XZ_OPTIONS_ERROR; + } +#endif + + /* Valid Filter Flags always take at least two bytes. */ + if (s->temp.size - s->temp.pos < 2) + return XZ_DATA_ERROR; + + /* Filter ID = LZMA2 */ + if (s->temp.buf[s->temp.pos++] != 0x21) + return XZ_OPTIONS_ERROR; + + /* Size of Properties = 1-byte Filter Properties */ + if (s->temp.buf[s->temp.pos++] != 0x01) + return XZ_OPTIONS_ERROR; + + /* Filter Properties contains LZMA2 dictionary size. */ + if (s->temp.size - s->temp.pos < 1) + return XZ_DATA_ERROR; + + ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]); + if (ret != XZ_OK) + return ret; + + /* The rest must be Header Padding. */ + while (s->temp.pos < s->temp.size) + if (s->temp.buf[s->temp.pos++] != 0x00) + return XZ_OPTIONS_ERROR; + + s->temp.pos = 0; + s->block.compressed = 0; + s->block.uncompressed = 0; + + return XZ_OK; +} + +static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) +{ + enum xz_ret ret; + + /* + * Store the start position for the case when we are in the middle + * of the Index field. + */ + s->in_start = b->in_pos; + + while (true) { + switch (s->sequence) { + case SEQ_STREAM_HEADER: + /* + * Stream Header is copied to s->temp, and then + * decoded from there. This way if the caller + * gives us only little input at a time, we can + * still keep the Stream Header decoding code + * simple. Similar approach is used in many places + * in this file. + */ + if (!fill_temp(s, b)) + return XZ_OK; + + ret = dec_stream_header(s); + if (ret != XZ_OK) + return ret; + + s->sequence = SEQ_BLOCK_START; + + case SEQ_BLOCK_START: + /* We need one byte of input to continue. */ + if (b->in_pos == b->in_size) + return XZ_OK; + + /* See if this is the beginning of the Index field. */ + if (b->in[b->in_pos] == 0) { + s->in_start = b->in_pos++; + s->sequence = SEQ_INDEX; + break; + } + + /* + * Calculate the size of the Block Header and + * prepare to decode it. + */ + s->block_header.size + = ((uint32_t)b->in[b->in_pos] + 1) * 4; + + s->temp.size = s->block_header.size; + s->temp.pos = 0; + s->sequence = SEQ_BLOCK_HEADER; + + case SEQ_BLOCK_HEADER: + if (!fill_temp(s, b)) + return XZ_OK; + + ret = dec_block_header(s); + if (ret != XZ_OK) + return ret; + + s->sequence = SEQ_BLOCK_UNCOMPRESS; + + case SEQ_BLOCK_UNCOMPRESS: + ret = dec_block(s, b); + if (ret != XZ_STREAM_END) + return ret; + + s->sequence = SEQ_BLOCK_PADDING; + + case SEQ_BLOCK_PADDING: + /* + * Size of Compressed Data + Block Padding + * must be a multiple of four. We don't need + * s->block.compressed for anything else + * anymore, so we use it here to test the size + * of the Block Padding field. + */ + while (s->block.compressed & 3) { + if (b->in_pos == b->in_size) + return XZ_OK; + + if (b->in[b->in_pos++] != 0) + return XZ_DATA_ERROR; + + ++s->block.compressed; + } + + s->sequence = SEQ_BLOCK_CHECK; + + case SEQ_BLOCK_CHECK: + if (s->has_crc32) { + ret = crc32_validate(s, b); + if (ret != XZ_STREAM_END) + return ret; + } + + s->sequence = SEQ_BLOCK_START; + break; + + case SEQ_INDEX: + ret = dec_index(s, b); + if (ret != XZ_STREAM_END) + return ret; + + s->sequence = SEQ_INDEX_PADDING; + + case SEQ_INDEX_PADDING: + while ((s->index.size + (b->in_pos - s->in_start)) + & 3) { + if (b->in_pos == b->in_size) { + index_update(s, b); + return XZ_OK; + } + + if (b->in[b->in_pos++] != 0) + return XZ_DATA_ERROR; + } + + /* Finish the CRC32 value and Index size. */ + index_update(s, b); + +#ifndef GRUB_EMBED_DECOMPRESSOR + /* Compare the hashes to validate the Index field. */ + GRUB_MD_CRC32->final(s->block.hash.crc32_context); + GRUB_MD_CRC32->final(s->index.hash.crc32_context); + uint32_t block_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->block.hash.crc32_context); + uint32_t index_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->index.hash.crc32_context); + + if (s->block.hash.unpadded != s->index.hash.unpadded + || s->block.hash.uncompressed != s->index.hash.uncompressed + || block_crc != index_crc) + { + return XZ_DATA_ERROR; + } +#endif + + s->sequence = SEQ_INDEX_CRC32; + + case SEQ_INDEX_CRC32: + ret = crc32_validate(s, b); + if (ret != XZ_STREAM_END) + return ret; + + s->temp.size = STREAM_HEADER_SIZE; + s->sequence = SEQ_STREAM_FOOTER; + + case SEQ_STREAM_FOOTER: + if (!fill_temp(s, b)) + return XZ_OK; + + return dec_stream_footer(s); + } + } + + /* Never reached */ +} + +/* + * xz_dec_run() is a wrapper for dec_main() to handle some special cases in + * multi-call and single-call decoding. + * + * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we + * are not going to make any progress anymore. This is to prevent the caller + * from calling us infinitely when the input file is truncated or otherwise + * corrupt. Since zlib-style API allows that the caller fills the input buffer + * only when the decoder doesn't produce any new output, we have to be careful + * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only + * after the second consecutive call to xz_dec_run() that makes no progress. + * + * In single-call mode, if we couldn't decode everything and no error + * occurred, either the input is truncated or the output buffer is too small. + * Since we know that the last input byte never produces any output, we know + * that if all the input was consumed and decoding wasn't finished, the file + * must be corrupt. Otherwise the output buffer has to be too small or the + * file is corrupt in a way that decoding it produces too big output. + * + * If single-call decoding fails, we reset b->in_pos and b->out_pos back to + * their original values. This is because with some filter chains there won't + * be any valid uncompressed data in the output buffer unless the decoding + * actually succeeds (that's the price to pay of using the output buffer as + * the workspace). + */ +enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) +{ + size_t in_start; + size_t out_start; + enum xz_ret ret; + + if (s->single_call) + xz_dec_reset(s); + + in_start = b->in_pos; + out_start = b->out_pos; + ret = dec_main(s, b); + + if (s->single_call) { + if (ret == XZ_OK) + ret = b->in_pos == b->in_size + ? XZ_DATA_ERROR : XZ_BUF_ERROR; + + if (ret != XZ_STREAM_END) { + b->in_pos = in_start; + b->out_pos = out_start; + } + + } else if (ret == XZ_OK && in_start == b->in_pos + && out_start == b->out_pos) { + if (s->allow_buf_error) + ret = XZ_BUF_ERROR; + + s->allow_buf_error = true; + } else { + s->allow_buf_error = false; + } + + return ret; +} + +#ifdef GRUB_EMBED_DECOMPRESSOR +struct xz_dec decoder; +#endif + +struct xz_dec * xz_dec_init(uint32_t dict_max) +{ + struct xz_dec *s; +#ifdef GRUB_EMBED_DECOMPRESSOR + s = &decoder; +#else + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; +#endif + +#ifndef GRUB_EMBED_DECOMPRESSOR + /* prepare CRC32 calculators */ + if(GRUB_MD_CRC32 == NULL) + { + kfree(s); + return NULL; + } + + s->crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL); + if (s->crc32_context == NULL) + { + kfree(s); + return NULL; + } + + s->index.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL); + if (s->index.hash.crc32_context == NULL) + { + kfree(s->crc32_context); + kfree(s); + return NULL; + } + + s->block.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL); + if (s->block.hash.crc32_context == NULL) + { + kfree(s->index.hash.crc32_context); + kfree(s->crc32_context); + kfree(s); + return NULL; + } + + + GRUB_MD_CRC32->init(s->crc32_context); + GRUB_MD_CRC32->init(s->index.hash.crc32_context); + GRUB_MD_CRC32->init(s->block.hash.crc32_context); +#endif + + s->crc32_temp = 0; + + s->single_call = dict_max == 0; + +#ifdef XZ_DEC_BCJ + s->bcj = xz_dec_bcj_create(s->single_call); + if (s->bcj == NULL) + goto error_bcj; +#endif + + s->lzma2 = xz_dec_lzma2_create(dict_max); + if (s->lzma2 == NULL) + goto error_lzma2; + + xz_dec_reset(s); + return s; + +error_lzma2: +#ifdef XZ_DEC_BCJ + xz_dec_bcj_end(s->bcj); +error_bcj: +#endif +#ifndef GRUB_EMBED_DECOMPRESSOR + kfree(s); +#endif + return NULL; +} + +void xz_dec_reset(struct xz_dec *s) +{ + s->sequence = SEQ_STREAM_HEADER; + s->allow_buf_error = false; + s->pos = 0; + + { +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t *t; + t = s->block.hash.crc32_context; +#endif + memzero(&s->block, sizeof(s->block)); +#ifndef GRUB_EMBED_DECOMPRESSOR + s->block.hash.crc32_context = t; + t = s->index.hash.crc32_context; +#endif + memzero(&s->index, sizeof(s->index)); +#ifndef GRUB_EMBED_DECOMPRESSOR + s->index.hash.crc32_context = t; +#endif + } + s->temp.pos = 0; + s->temp.size = STREAM_HEADER_SIZE; + +#ifndef GRUB_EMBED_DECOMPRESSOR + GRUB_MD_CRC32->init(s->crc32_context); + GRUB_MD_CRC32->init(s->index.hash.crc32_context); + GRUB_MD_CRC32->init(s->block.hash.crc32_context); +#endif + s->crc32_temp = 0; +} + +void xz_dec_end(struct xz_dec *s) +{ + if (s != NULL) { + xz_dec_lzma2_end(s->lzma2); +#ifndef GRUB_EMBED_DECOMPRESSOR + kfree(s->index.hash.crc32_context); + kfree(s->block.hash.crc32_context); + kfree(s->crc32_context); +#endif +#ifdef XZ_DEC_BCJ + xz_dec_bcj_end(s->bcj); +#endif +#ifndef GRUB_EMBED_DECOMPRESSOR + kfree(s); +#endif + } +} diff --git a/grub-core/lib/xzembed/xz_lzma2.h b/grub-core/lib/xzembed/xz_lzma2.h new file mode 100644 index 000000000..15e553dc0 --- /dev/null +++ b/grub-core/lib/xzembed/xz_lzma2.h @@ -0,0 +1,236 @@ +/* xz_lzma2.h - LZMA2 definitions */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_LZMA2_H +#define XZ_LZMA2_H + +/* dictionary size hard limit + * actual size limit is calculated as shown in 5.3.1 + * http://tukaani.org/xz/xz-file-format.txt + * + * if bits > 39 dictionary_size = UINT32_MAX + * else + * dictionary_size = 2 | (bits & 1); + * dictionary_size <<= bits / 2 + 11; + * + * i.e. + * 0 - 4 KiB + * 6 - 32 KiB + * 30 - 128MiB + * 39 - 3072 MiB + * 40 - 4096 MiB - 1 B + * note: implementation supports 39 at maximum + */ +#define DICT_BIT_SIZE 30 + +/* Range coder constants */ +#define RC_SHIFT_BITS 8 +#define RC_TOP_BITS 24 +#define RC_TOP_VALUE (1 << RC_TOP_BITS) +#define RC_BIT_MODEL_TOTAL_BITS 11 +#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS) +#define RC_MOVE_BITS 5 + +/* + * Maximum number of position states. A position state is the lowest pb + * number of bits of the current uncompressed offset. In some places there + * are different sets of probabilities for different position states. + */ +#define POS_STATES_MAX (1 << 4) + +/* + * This enum is used to track which LZMA symbols have occurred most recently + * and in which order. This information is used to predict the next symbol. + * + * Symbols: + * - Literal: One 8-bit byte + * - Match: Repeat a chunk of data at some distance + * - Long repeat: Multi-byte match at a recently seen distance + * - Short repeat: One-byte repeat at a recently seen distance + * + * The symbol names are in from STATE_oldest_older_previous. REP means + * either short or long repeated match, and NONLIT means any non-literal. + */ +enum lzma_state { + STATE_LIT_LIT, + STATE_MATCH_LIT_LIT, + STATE_REP_LIT_LIT, + STATE_SHORTREP_LIT_LIT, + STATE_MATCH_LIT, + STATE_REP_LIT, + STATE_SHORTREP_LIT, + STATE_LIT_MATCH, + STATE_LIT_LONGREP, + STATE_LIT_SHORTREP, + STATE_NONLIT_MATCH, + STATE_NONLIT_REP +}; + +/* Total number of states */ +#define STATES 12 + +/* The lowest 7 states indicate that the previous state was a literal. */ +#define LIT_STATES 7 + +/* Indicate that the latest symbol was a literal. */ +static inline void lzma_state_literal(enum lzma_state *state) +{ + if (*state <= STATE_SHORTREP_LIT_LIT) + *state = STATE_LIT_LIT; + else if (*state <= STATE_LIT_SHORTREP) + *state -= 3; + else + *state -= 6; +} + +/* Indicate that the latest symbol was a match. */ +static inline void lzma_state_match(enum lzma_state *state) +{ + *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; +} + +/* Indicate that the latest state was a long repeated match. */ +static inline void lzma_state_long_rep(enum lzma_state *state) +{ + *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; +} + +/* Indicate that the latest symbol was a short match. */ +static inline void lzma_state_short_rep(enum lzma_state *state) +{ + *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; +} + +/* Test if the previous symbol was a literal. */ +static inline bool lzma_state_is_literal(enum lzma_state state) +{ + return state < LIT_STATES; +} + +/* Each literal coder is divided in three sections: + * - 0x001-0x0FF: Without match byte + * - 0x101-0x1FF: With match byte; match bit is 0 + * - 0x201-0x2FF: With match byte; match bit is 1 + * + * Match byte is used when the previous LZMA symbol was something else than + * a literal (that is, it was some kind of match). + */ +#define LITERAL_CODER_SIZE 0x300 + +/* Maximum number of literal coders */ +#define LITERAL_CODERS_MAX (1 << 4) + +/* Minimum length of a match is two bytes. */ +#define MATCH_LEN_MIN 2 + +/* Match length is encoded with 4, 5, or 10 bits. + * + * Length Bits + * 2-9 4 = Choice=0 + 3 bits + * 10-17 5 = Choice=1 + Choice2=0 + 3 bits + * 18-273 10 = Choice=1 + Choice2=1 + 8 bits + */ +#define LEN_LOW_BITS 3 +#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS) +#define LEN_MID_BITS 3 +#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS) +#define LEN_HIGH_BITS 8 +#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS) +#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS) + +/* + * Maximum length of a match is 273 which is a result of the encoding + * described above. + */ +#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1) + +/* + * Different sets of probabilities are used for match distances that have + * very short match length: Lengths of 2, 3, and 4 bytes have a separate + * set of probabilities for each length. The matches with longer length + * use a shared set of probabilities. + */ +#define DIST_STATES 4 + +/* + * Get the index of the appropriate probability array for decoding + * the distance slot. + */ +static inline uint32_t lzma_get_dist_state(uint32_t len) +{ + return len < DIST_STATES + MATCH_LEN_MIN + ? len - MATCH_LEN_MIN : DIST_STATES - 1; +} + +/* + * The highest two bits of a 32-bit match distance are encoded using six bits. + * This six-bit value is called a distance slot. This way encoding a 32-bit + * value takes 6-36 bits, larger values taking more bits. + */ +#define DIST_SLOT_BITS 6 +#define DIST_SLOTS (1 << DIST_SLOT_BITS) + +/* Match distances up to 127 are fully encoded using probabilities. Since + * the highest two bits (distance slot) are always encoded using six bits, + * the distances 0-3 don't need any additional bits to encode, since the + * distance slot itself is the same as the actual distance. DIST_MODEL_START + * indicates the first distance slot where at least one additional bit is + * needed. + */ +#define DIST_MODEL_START 4 + +/* + * Match distances greater than 127 are encoded in three pieces: + * - distance slot: the highest two bits + * - direct bits: 2-26 bits below the highest two bits + * - alignment bits: four lowest bits + * + * Direct bits don't use any probabilities. + * + * The distance slot value of 14 is for distances 128-191. + */ +#define DIST_MODEL_END 14 + +/* Distance slots that indicate a distance <= 127. */ +#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2) +#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS) + +/* + * For match distances greater than 127, only the highest two bits and the + * lowest four bits (alignment) is encoded using probabilities. + */ +#define ALIGN_BITS 4 +#define ALIGN_SIZE (1 << ALIGN_BITS) +#define ALIGN_MASK (ALIGN_SIZE - 1) + +/* Total number of all probability variables */ +#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE) + +/* + * LZMA remembers the four most recent match distances. Reusing these + * distances tends to take less space than re-encoding the actual + * distance value. + */ +#define REPS 4 + +#endif diff --git a/grub-core/lib/xzembed/xz_private.h b/grub-core/lib/xzembed/xz_private.h new file mode 100644 index 000000000..fc845c92d --- /dev/null +++ b/grub-core/lib/xzembed/xz_private.h @@ -0,0 +1,96 @@ +/* xz_private.h - Private includes and definitions */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_PRIVATE_H +#define XZ_PRIVATE_H + +/* + * For userspace builds, use a separate header to define the required + * macros and functions. This makes it easier to adapt the code into + * different environments and avoids clutter in the Linux kernel tree. + */ +#include "xz_config.h" + +/* + * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. + * XZ_DEC_BCJ is used to enable generic support for BCJ decoders. + */ +#ifndef XZ_DEC_BCJ +# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \ + || defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \ + || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \ + || defined(XZ_DEC_SPARC) +# define XZ_DEC_BCJ +# endif +#endif + +/* + * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used + * before calling xz_dec_lzma2_run(). + */ +struct xz_dec_lzma2 * xz_dec_lzma2_create( + uint32_t dict_max); + +/* + * Decode the LZMA2 properties (one byte) and reset the decoder. Return + * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not + * big enough, and XZ_OPTIONS_ERROR if props indicates something that this + * decoder doesn't support. + */ +enum xz_ret xz_dec_lzma2_reset( + struct xz_dec_lzma2 *s, uint8_t props); + +/* Decode raw LZMA2 stream from b->in to b->out. */ +enum xz_ret xz_dec_lzma2_run( + struct xz_dec_lzma2 *s, struct xz_buf *b); + +/* Free the memory allocated for the LZMA2 decoder. */ +void xz_dec_lzma2_end(struct xz_dec_lzma2 *s); + +/* + * Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before + * calling xz_dec_bcj_run(). + */ +struct xz_dec_bcj * xz_dec_bcj_create(bool single_call); + +/* + * Decode the Filter ID of a BCJ filter. This implementation doesn't + * support custom start offsets, so no decoding of Filter Properties + * is needed. Returns XZ_OK if the given Filter ID is supported. + * Otherwise XZ_OPTIONS_ERROR is returned. + */ +enum xz_ret xz_dec_bcj_reset( + struct xz_dec_bcj *s, uint8_t id); + +/* + * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is + * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run() + * must be called directly. + */ +enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, + struct xz_dec_lzma2 *lzma2, struct xz_buf *b); + +/* Free the memory allocated for the BCJ filters. */ +#define xz_dec_bcj_end(s) kfree(s) + +#endif diff --git a/grub-core/lib/xzembed/xz_stream.h b/grub-core/lib/xzembed/xz_stream.h new file mode 100644 index 000000000..f58397a15 --- /dev/null +++ b/grub-core/lib/xzembed/xz_stream.h @@ -0,0 +1,53 @@ +/* xz_stream.h - Definitions for handling the .xz file format */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_STREAM_H +#define XZ_STREAM_H + +/* + * See the .xz file format specification at + * http://tukaani.org/xz/xz-file-format.txt + * to understand the container format. + */ + +#define STREAM_HEADER_SIZE 12 + +#define HEADER_MAGIC "\3757zXZ\0" +#define HEADER_MAGIC_SIZE 6 + +#define FOOTER_MAGIC "YZ" +#define FOOTER_MAGIC_SIZE 2 + +/* + * Variable-length integer can hold a 63-bit unsigned integer, or a special + * value to indicate that the value is unknown. + */ +typedef uint64_t vli_type; + +#define VLI_MAX ((vli_type)-1 / 2) +#define VLI_UNKNOWN ((vli_type)-1) + +/* Maximum encoded size of a VLI */ +#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7) + +#endif diff --git a/loader/aout.c b/grub-core/loader/aout.c similarity index 84% rename from loader/aout.c rename to grub-core/loader/aout.c index 0254b6ae0..611960f92 100644 --- a/loader/aout.c +++ b/grub-core/loader/aout.c @@ -39,9 +39,8 @@ grub_aout_get_type (union grub_aout_header *header) grub_err_t grub_aout_load (grub_file_t file, int offset, - grub_addr_t load_addr, - int load_size, - grub_addr_t bss_end_addr) + void *load_addr, + int load_size, grub_size_t bss_size) { if ((grub_file_seek (file, offset)) == (grub_off_t) - 1) return grub_errno; @@ -49,14 +48,13 @@ grub_aout_load (grub_file_t file, int offset, if (!load_size) load_size = file->size - offset; - grub_file_read (file, (void *) load_addr, load_size); + grub_file_read (file, load_addr, load_size); if (grub_errno) return grub_errno; - if (bss_end_addr) - grub_memset ((char *) load_addr + load_size, 0, - bss_end_addr - load_addr - load_size); + if (bss_size) + grub_memset ((char *) load_addr + load_size, 0, bss_size); return GRUB_ERR_NONE; } diff --git a/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c similarity index 100% rename from loader/efi/appleloader.c rename to grub-core/loader/efi/appleloader.c diff --git a/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c similarity index 100% rename from loader/efi/chainloader.c rename to grub-core/loader/efi/chainloader.c diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c new file mode 100644 index 000000000..b7cf115d9 --- /dev/null +++ b/grub-core/loader/i386/bsd.c @@ -0,0 +1,1987 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif +#ifdef GRUB_MACHINE_EFI +#include +#define NETBSD_DEFAULT_VIDEO_MODE "800x600" +#else +#define NETBSD_DEFAULT_VIDEO_MODE "text" +#include +#endif +#include + +#include +#include +#include +#include +#include + +#define ALIGN_DWORD(a) ALIGN_UP (a, 4) +#define ALIGN_QWORD(a) ALIGN_UP (a, 8) +#define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a))) +#define ALIGN_PAGE(a) ALIGN_UP (a, 4096) + +static int kernel_type = KERNEL_TYPE_NONE; +static grub_dl_t my_mod; +static grub_addr_t entry, entry_hi, kern_start, kern_end; +static void *kern_chunk_src; +static grub_uint32_t bootflags; +static int is_elf_kernel, is_64bit; +static grub_uint32_t openbsd_root; +struct grub_relocator *relocator = NULL; +static struct grub_openbsd_ramdisk_descriptor openbsd_ramdisk; + +struct bsd_tag +{ + struct bsd_tag *next; + grub_size_t len; + grub_uint32_t type; + union { + grub_uint8_t a; + grub_uint16_t b; + grub_uint32_t c; + } data[0]; +}; + +static struct bsd_tag *tags, *tags_last; + +struct netbsd_module +{ + struct netbsd_module *next; + struct grub_netbsd_btinfo_module mod; +}; + +static struct netbsd_module *netbsd_mods, *netbsd_mods_last; + +static const struct grub_arg_option freebsd_opts[] = + { + {"dual", 'D', 0, N_("Display output on all consoles."), 0, 0}, + {"serial", 'h', 0, N_("Use serial console."), 0, 0}, + {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0}, + {"cdrom", 'C', 0, N_("Use CDROM as root."), 0, 0}, + {"config", 'c', 0, N_("Invoke user configuration routing."), 0, 0}, + {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, + {"gdb", 'g', 0, N_("Use GDB remote debugger instead of DDB."), 0, 0}, + {"mute", 'm', 0, N_("Disable all boot output."), 0, 0}, + {"nointr", 'n', 0, "", 0, 0}, + {"pause", 'p', 0, N_("Wait for keypress after every line of output."), 0, 0}, + {"quiet", 'q', 0, "", 0, 0}, + {"dfltroot", 'r', 0, N_("Use compiled-in rootdev."), 0, 0}, + {"single", 's', 0, N_("Boot into single mode."), 0, 0}, + {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static const grub_uint32_t freebsd_flags[] = +{ + FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME, + FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB, + FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR, + FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT, + FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE, 0 +}; + +static const struct grub_arg_option openbsd_opts[] = + { + {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0}, + {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0}, + {"config", 'c', 0, N_("Change configured devices."), 0, 0}, + {"single", 's', 0, N_("Boot into single mode."), 0, 0}, + {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, + {"root", 'r', 0, N_("Set root device."), "wdXY", ARG_TYPE_STRING}, + {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL, + N_("Use serial console."), N_("comUNIT[,SPEED]"), ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +static const grub_uint32_t openbsd_flags[] = +{ + OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG, + OPENBSD_RB_SINGLE, OPENBSD_RB_KDB, 0 +}; + +#define OPENBSD_ROOT_ARG (ARRAY_SIZE (openbsd_flags) - 1) +#define OPENBSD_SERIAL_ARG (ARRAY_SIZE (openbsd_flags)) + +static const struct grub_arg_option netbsd_opts[] = + { + {"no-smp", '1', 0, N_("Disable SMP."), 0, 0}, + {"no-acpi", '2', 0, N_("Disable ACPI."), 0, 0}, + {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0}, + {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0}, + {"config", 'c', 0, N_("Change configured devices."), 0, 0}, + {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, + {"miniroot", 'm', 0, "", 0, 0}, + {"quiet", 'q', 0, N_("Don't display boot diagnostic messages."), 0, 0}, + {"single", 's', 0, N_("Boot into single mode."), 0, 0}, + {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0}, + {"debug", 'x', 0, N_("Boot with debug messages."), 0, 0}, + {"silent", 'z', 0, N_("Supress normal output (warnings remain)."), 0, 0}, + {"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING}, + {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL, + N_("Use serial console."), N_("[ADDR|comUNIT][,SPEED]"), ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +static const grub_uint32_t netbsd_flags[] = +{ + NETBSD_AB_NOSMP, NETBSD_AB_NOACPI, NETBSD_RB_ASKNAME, + NETBSD_RB_HALT, NETBSD_RB_USERCONFIG, NETBSD_RB_KDB, + NETBSD_RB_MINIROOT, NETBSD_AB_QUIET, NETBSD_RB_SINGLE, + NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG, NETBSD_AB_SILENT, 0 +}; + +#define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1) +#define NETBSD_SERIAL_ARG (ARRAY_SIZE (netbsd_flags)) + +static void +grub_bsd_get_device (grub_uint32_t * biosdev, + grub_uint32_t * unit, + grub_uint32_t * slice, grub_uint32_t * part) +{ + grub_device_t dev; + +#ifdef GRUB_MACHINE_PCBIOS + *biosdev = grub_get_root_biosnumber () & 0xff; +#else + *biosdev = 0xff; +#endif + *unit = (*biosdev & 0x7f); + *slice = 0xff; + *part = 0xff; + dev = grub_device_open (0); + if (dev && dev->disk && dev->disk->partition) + { + if (dev->disk->partition->parent) + { + *part = dev->disk->partition->number; + *slice = dev->disk->partition->parent->number + 1; + } + else + *slice = dev->disk->partition->number + 1; + } + if (dev) + grub_device_close (dev); +} + +grub_err_t +grub_bsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len) +{ + struct bsd_tag *newtag; + + newtag = grub_malloc (len + sizeof (struct bsd_tag)); + if (!newtag) + return grub_errno; + newtag->len = len; + newtag->type = type; + newtag->next = NULL; + if (len) + grub_memcpy (newtag->data, data, len); + + if (kernel_type == KERNEL_TYPE_FREEBSD + && type == (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SMAP)) + { + struct bsd_tag *p; + for (p = tags; + p->type != (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_KERNEND); + p = p->next); + + if (p) + { + newtag->next = p->next; + p->next = newtag; + if (newtag->next == NULL) + tags_last = newtag; + return GRUB_ERR_NONE; + } + } + + if (tags_last) + tags_last->next = newtag; + else + tags = newtag; + tags_last = newtag; + + return GRUB_ERR_NONE; +} + +struct grub_e820_mmap +{ + grub_uint64_t addr; + grub_uint64_t size; + grub_uint32_t type; +} __attribute__((packed)); +#define GRUB_E820_RAM 1 +#define GRUB_E820_RESERVED 2 +#define GRUB_E820_ACPI 3 +#define GRUB_E820_NVS 4 +#define GRUB_E820_EXEC_CODE 5 + +static void +generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf) +{ + int count = 0; + struct grub_e820_mmap *mmap = buf; + struct grub_e820_mmap prev, cur; + + 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) + { + cur.addr = addr; + cur.size = size; + switch (type) + { + case GRUB_MEMORY_AVAILABLE: + cur.type = GRUB_E820_RAM; + break; + + case GRUB_MEMORY_ACPI: + cur.type = GRUB_E820_ACPI; + break; + + case GRUB_MEMORY_NVS: + cur.type = GRUB_E820_NVS; + break; + + default: + case GRUB_MEMORY_CODE: + case GRUB_MEMORY_RESERVED: + cur.type = GRUB_E820_RESERVED; + break; + } + + /* Merge regions if possible. */ + if (count && cur.type == prev.type && cur.addr == prev.addr + prev.size) + { + prev.size += cur.size; + if (mmap) + mmap[-1] = prev; + } + else + { + if (mmap) + *mmap++ = cur; + prev = cur; + count++; + } + + if (kernel_type == KERNEL_TYPE_OPENBSD && prev.addr < 0x100000 + && prev.addr + prev.size > 0x100000) + { + cur.addr = 0x100000; + cur.size = prev.addr + prev.size - 0x100000; + cur.type = prev.type; + prev.size = 0x100000 - prev.addr; + if (mmap) + { + mmap[-1] = prev; + mmap[0] = cur; + mmap++; + } + prev = cur; + count++; + } + + return 0; + } + + grub_mmap_iterate (hook); + + if (len) + *len = count * sizeof (struct grub_e820_mmap); + *cnt = count; + + return; +} + +static grub_err_t +grub_bsd_add_mmap (void) +{ + grub_size_t len, cnt; + void *buf = NULL, *buf0; + + generate_e820_mmap (&len, &cnt, buf); + + if (kernel_type == KERNEL_TYPE_NETBSD) + len += sizeof (grub_uint32_t); + + if (kernel_type == KERNEL_TYPE_OPENBSD) + len += sizeof (struct grub_e820_mmap); + + buf = grub_malloc (len); + if (!buf) + return grub_errno; + + buf0 = buf; + if (kernel_type == KERNEL_TYPE_NETBSD) + { + *(grub_uint32_t *) buf = cnt; + buf = ((grub_uint32_t *) buf + 1); + } + + generate_e820_mmap (NULL, &cnt, buf); + + if (kernel_type == KERNEL_TYPE_OPENBSD) + grub_memset ((grub_uint8_t *) buf + len - sizeof (struct grub_e820_mmap), 0, + sizeof (struct grub_e820_mmap)); + + grub_dprintf ("bsd", "%u entries in smap\n", (unsigned) cnt); + if (kernel_type == KERNEL_TYPE_NETBSD) + grub_bsd_add_meta (NETBSD_BTINFO_MEMMAP, buf0, len); + else if (kernel_type == KERNEL_TYPE_OPENBSD) + grub_bsd_add_meta (OPENBSD_BOOTARG_MMAP, buf0, len); + else + grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_SMAP, buf0, len); + + grub_free (buf0); + + return grub_errno; +} + +grub_err_t +grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv, + grub_addr_t addr, grub_uint32_t size) +{ + char *name; + name = grub_strrchr (filename, '/'); + if (name) + name++; + else + name = filename; + if (grub_strcmp (type, "/boot/zfs/zpool.cache") == 0) + name = "/boot/zfs/zpool.cache"; + + if (grub_bsd_add_meta (FREEBSD_MODINFO_NAME, name, grub_strlen (name) + 1)) + return grub_errno; + + if (is_64bit) + { + grub_uint64_t addr64 = addr, size64 = size; + if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1) + || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64, sizeof (addr64)) + || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size64, sizeof (size64))) + return grub_errno; + } + else + { + if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1) + || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr)) + || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size))) + return grub_errno; + } + + if (argc) + { + int i, n; + + n = 0; + for (i = 0; i < argc; i++) + { + n += grub_strlen (argv[i]) + 1; + } + + if (n) + { + char cmdline[n], *p; + + p = cmdline; + for (i = 0; i < argc; i++) + { + grub_strcpy (p, argv[i]); + p += grub_strlen (argv[i]); + *(p++) = ' '; + } + *p = 0; + + if (grub_bsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n)) + return grub_errno; + } + } + + return GRUB_ERR_NONE; +} + +static void +grub_freebsd_list_modules (void) +{ + struct bsd_tag *tag; + + grub_printf (" %-18s %-18s%14s%14s\n", "name", "type", "addr", "size"); + + for (tag = tags; tag; tag = tag->next) + { + switch (tag->type) + { + case FREEBSD_MODINFO_NAME: + case FREEBSD_MODINFO_TYPE: + grub_printf (" %-18s", (char *) tag->data); + break; + case FREEBSD_MODINFO_ADDR: + { + grub_uint32_t addr; + + addr = *((grub_uint32_t *) tag->data); + grub_printf (" 0x%08x", addr); + break; + } + case FREEBSD_MODINFO_SIZE: + { + grub_uint32_t len; + + len = *((grub_uint32_t *) tag->data); + grub_printf (" 0x%08x\n", len); + } + } + } +} + +static grub_err_t +grub_netbsd_add_meta_module (char *filename, grub_uint32_t type, + grub_addr_t addr, grub_uint32_t size) +{ + char *name; + struct netbsd_module *mod; + name = grub_strrchr (filename, '/'); + + if (name) + name++; + else + name = filename; + + mod = grub_zalloc (sizeof (*mod)); + if (!mod) + return grub_errno; + + grub_strncpy (mod->mod.name, name, sizeof (mod->mod.name) - 1); + mod->mod.addr = addr; + mod->mod.type = type; + mod->mod.size = size; + + if (netbsd_mods_last) + netbsd_mods_last->next = mod; + else + netbsd_mods = mod; + netbsd_mods_last = mod; + + return GRUB_ERR_NONE; +} + +static void +grub_netbsd_list_modules (void) +{ + struct netbsd_module *mod; + + grub_printf (" %-18s%14s%14s%14s\n", "name", "type", "addr", "size"); + + for (mod = netbsd_mods; mod; mod = mod->next) + grub_printf (" %-18s 0x%08x 0x%08x 0x%08x", mod->mod.name, + mod->mod.type, mod->mod.addr, mod->mod.size); +} + +/* This function would be here but it's under different license. */ +#include "bsd_pagetable.c" + +static grub_err_t +grub_freebsd_boot (void) +{ + struct grub_freebsd_bootinfo bi; + grub_uint8_t *p, *p0; + grub_addr_t p_target; + grub_size_t p_size = 0; + grub_uint32_t bootdev, biosdev, unit, slice, part; + grub_err_t err; + grub_size_t tag_buf_len = 0; + + auto int iterate_env (struct grub_env_var *var); + int iterate_env (struct grub_env_var *var) + { + if ((!grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1)) && (var->name[sizeof("kFreeBSD.") - 1])) + { + grub_strcpy ((char *) p, &var->name[sizeof("kFreeBSD.") - 1]); + p += grub_strlen ((char *) p); + *(p++) = '='; + grub_strcpy ((char *) p, var->value); + p += grub_strlen ((char *) p) + 1; + } + + return 0; + } + + auto int iterate_env_count (struct grub_env_var *var); + int iterate_env_count (struct grub_env_var *var) + { + if ((!grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1)) && (var->name[sizeof("kFreeBSD.") - 1])) + { + p_size += grub_strlen (&var->name[sizeof("kFreeBSD.") - 1]); + p_size++; + p_size += grub_strlen (var->value) + 1; + } + + return 0; + } + + grub_memset (&bi, 0, sizeof (bi)); + bi.version = FREEBSD_BOOTINFO_VERSION; + bi.length = sizeof (bi); + + grub_bsd_get_device (&biosdev, &unit, &slice, &part); + bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) + + (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT)); + + bi.boot_device = biosdev; + + p_size = 0; + grub_env_iterate (iterate_env_count); + + if (p_size) + p_size = ALIGN_PAGE (kern_end + p_size + 1) - kern_end; + + if (is_elf_kernel) + { + struct bsd_tag *tag; + + err = grub_bsd_add_mmap (); + if (err) + return err; + + err = grub_bsd_add_meta (FREEBSD_MODINFO_END, 0, 0); + if (err) + return err; + + tag_buf_len = 0; + for (tag = tags; tag; tag = tag->next) + tag_buf_len = ALIGN_VAR (tag_buf_len + + sizeof (struct freebsd_tag_header) + + tag->len); + p_size = ALIGN_PAGE (kern_end + p_size + tag_buf_len) - kern_end; + } + + if (is_64bit) + p_size += 4096 * 3; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + kern_end, p_size); + if (err) + return err; + p = get_virtual_current_address (ch); + } + p_target = kern_end; + p0 = p; + kern_end += p_size; + + grub_env_iterate (iterate_env); + + if (p != p0) + { + *(p++) = 0; + + bi.environment = p_target; + } + + if (is_elf_kernel) + { + grub_uint8_t *p_tag = p; + struct bsd_tag *tag; + + for (tag = tags; tag; tag = tag->next) + { + struct freebsd_tag_header *head + = (struct freebsd_tag_header *) p_tag; + head->type = tag->type; + head->len = tag->len; + p_tag += sizeof (struct freebsd_tag_header); + switch (tag->type) + { + case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_HOWTO: + if (is_64bit) + *(grub_uint64_t *) p_tag = bootflags; + else + *(grub_uint32_t *) p_tag = bootflags; + break; + + case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ENVP: + if (is_64bit) + *(grub_uint64_t *) p_tag = bi.environment; + else + *(grub_uint32_t *) p_tag = bi.environment; + break; + + case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_KERNEND: + if (is_64bit) + *(grub_uint64_t *) p_tag = kern_end; + else + *(grub_uint32_t *) p_tag = kern_end; + break; + + default: + grub_memcpy (p_tag, tag->data, tag->len); + break; + } + p_tag += tag->len; + p_tag = ALIGN_VAR (p_tag - p) + p; + } + + bi.tags = (p - p0) + p_target; + + p = (ALIGN_PAGE ((p_tag - p0) + p_target) - p_target) + p0; + } + + bi.kern_end = kern_end; + + grub_video_set_mode ("text", 0, 0); + + if (is_64bit) + { + struct grub_relocator64_state state; + grub_uint8_t *pagetable; + grub_uint32_t *stack; + grub_addr_t stack_target; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + 0x10000, 0x90000, + 3 * sizeof (grub_uint32_t) + + sizeof (bi), 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + stack = get_virtual_current_address (ch); + stack_target = get_physical_target_address (ch); + } + +#ifdef GRUB_MACHINE_EFI + err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); + if (err) + return err; +#endif + + pagetable = p; + fill_bsd64_pagetable (pagetable, (pagetable - p0) + p_target); + + state.cr3 = (pagetable - p0) + p_target; + state.rsp = stack_target; + state.rip = (((grub_uint64_t) entry_hi) << 32) | entry; + + stack[0] = entry; + stack[1] = bi.tags; + stack[2] = kern_end; + return grub_relocator64_boot (relocator, state, 0, 0x40000000); + } + else + { + struct grub_relocator32_state state; + grub_uint32_t *stack; + grub_addr_t stack_target; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + 0x10000, 0x90000, + 9 * sizeof (grub_uint32_t) + + sizeof (bi), 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + stack = get_virtual_current_address (ch); + stack_target = get_physical_target_address (ch); + } + +#ifdef GRUB_MACHINE_EFI + err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); + if (err) + return err; +#endif + + grub_memcpy (&stack[9], &bi, sizeof (bi)); + state.eip = entry; + state.esp = stack_target; + state.ebp = stack_target; + stack[0] = entry; /* "Return" address. */ + stack[1] = bootflags | FREEBSD_RB_BOOTINFO; + stack[2] = bootdev; + stack[3] = 0; + stack[4] = 0; + stack[5] = 0; + stack[6] = stack_target + 9 * sizeof (grub_uint32_t); + stack[7] = bi.tags; + stack[8] = kern_end; + return grub_relocator32_boot (relocator, state); + } + + /* Not reached. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_openbsd_boot (void) +{ + grub_uint32_t *stack; + struct grub_relocator32_state state; + void *curarg, *buf0, *arg0; + grub_addr_t buf_target; + grub_err_t err; + grub_size_t tag_buf_len; + + err = grub_bsd_add_mmap (); + if (err) + return err; + + { + struct bsd_tag *tag; + tag_buf_len = 0; + for (tag = tags; tag; tag = tag->next) + tag_buf_len = ALIGN_VAR (tag_buf_len + + sizeof (struct grub_openbsd_bootargs) + + tag->len); + } + + buf_target = GRUB_BSD_TEMP_BUFFER - 9 * sizeof (grub_uint32_t); + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, buf_target, + tag_buf_len + + sizeof (struct grub_openbsd_bootargs) + + 9 * sizeof (grub_uint32_t)); + if (err) + return err; + buf0 = get_virtual_current_address (ch); + } + + stack = (grub_uint32_t *) buf0; + arg0 = curarg = stack + 9; + + { + struct bsd_tag *tag; + struct grub_openbsd_bootargs *head; + + for (tag = tags; tag; tag = tag->next) + { + head = curarg; + head->ba_type = tag->type; + head->ba_size = tag->len + sizeof (*head); + curarg = head + 1; + grub_memcpy (curarg, tag->data, tag->len); + curarg = (grub_uint8_t *) curarg + tag->len; + head->ba_next = (grub_uint8_t *) curarg - (grub_uint8_t *) buf0 + + buf_target; + } + head = curarg; + head->ba_type = OPENBSD_BOOTARG_END; + head->ba_size = 0; + head->ba_next = 0; + } + + grub_video_set_mode ("text", 0, 0); + +#ifdef GRUB_MACHINE_EFI + err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); + if (err) + return err; +#endif + + state.eip = entry; + state.ebp = state.esp + = ((grub_uint8_t *) stack - (grub_uint8_t *) buf0) + buf_target; + stack[0] = entry; + stack[1] = bootflags; + stack[2] = openbsd_root; + stack[3] = OPENBSD_BOOTARG_APIVER; + stack[4] = 0; + stack[5] = grub_mmap_get_upper () >> 10; + stack[6] = grub_mmap_get_lower () >> 10; + stack[7] = (grub_uint8_t *) curarg - (grub_uint8_t *) arg0; + stack[8] = ((grub_uint8_t *) arg0 - (grub_uint8_t *) buf0) + buf_target; + + return grub_relocator32_boot (relocator, state); +} + +static grub_err_t +grub_netbsd_setup_video (void) +{ + struct grub_video_mode_info mode_info; + void *framebuffer; + const char *modevar; + struct grub_netbsd_btinfo_framebuf params; + grub_err_t err; + grub_video_driver_id_t driv_id; + + modevar = grub_env_get ("gfxpayload"); + + /* Now all graphical modes are acceptable. + May change in future if we have modes without framebuffer. */ + if (modevar && *modevar != 0) + { + char *tmp; + tmp = grub_xasprintf ("%s;" NETBSD_DEFAULT_VIDEO_MODE, modevar); + if (! tmp) + return grub_errno; + err = grub_video_set_mode (tmp, 0, 0); + grub_free (tmp); + } + else + err = grub_video_set_mode (NETBSD_DEFAULT_VIDEO_MODE, 0, 0); + + if (err) + return err; + + driv_id = grub_video_get_driver_id (); + if (driv_id == GRUB_VIDEO_DRIVER_NONE) + return GRUB_ERR_NONE; + + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); + + if (err) + return err; + + params.width = mode_info.width; + params.height = mode_info.height; + params.bpp = mode_info.bpp; + params.pitch = mode_info.pitch; + params.flags = 0; + + params.fbaddr = (grub_addr_t) framebuffer; + + params.red_mask_size = mode_info.red_mask_size; + params.red_field_pos = mode_info.red_field_pos; + params.green_mask_size = mode_info.green_mask_size; + params.green_field_pos = mode_info.green_field_pos; + params.blue_mask_size = mode_info.blue_mask_size; + params.blue_field_pos = mode_info.blue_field_pos; + +#ifdef GRUB_MACHINE_PCBIOS + /* VESA packed modes may come with zeroed mask sizes, which need + to be set here according to DAC Palette width. If we don't, + this results in Linux displaying a black screen. */ + if (mode_info.bpp <= 8 && driv_id == GRUB_VIDEO_DRIVER_VBE) + { + struct grub_vbe_info_block controller_info; + int status; + int width = 8; + + status = grub_vbe_bios_get_controller_info (&controller_info); + + if (status == GRUB_VBE_STATUS_OK && + (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH)) + status = grub_vbe_bios_set_dac_palette_width (&width); + + if (status != GRUB_VBE_STATUS_OK) + /* 6 is default after mode reset. */ + width = 6; + + params.red_mask_size = params.green_mask_size + = params.blue_mask_size = width; + } +#endif + + err = grub_bsd_add_meta (NETBSD_BTINFO_FRAMEBUF, ¶ms, sizeof (params)); + return err; +} + +static grub_err_t +grub_netbsd_add_modules (void) +{ + struct netbsd_module *mod; + unsigned modcnt = 0; + struct grub_netbsd_btinfo_modules *mods; + unsigned i; + grub_err_t err; + + for (mod = netbsd_mods; mod; mod = mod->next) + modcnt++; + + mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt); + if (!mods) + return grub_errno; + + mods->num = modcnt; + mods->last_addr = kern_end; + for (mod = netbsd_mods, i = 0; mod; i++, mod = mod->next) + mods->mods[i] = mod->mod; + + err = grub_bsd_add_meta (NETBSD_BTINFO_MODULES, mods, + sizeof (*mods) + sizeof (mods->mods[0]) * modcnt); + grub_free (mods); + return err; +} + +static grub_err_t +grub_netbsd_boot (void) +{ + struct grub_netbsd_bootinfo *bootinfo; + void *curarg, *arg0; + grub_addr_t arg_target, stack_target; + grub_uint32_t *stack; + grub_err_t err; + struct grub_relocator32_state state; + grub_size_t tag_buf_len = 0; + int tag_count = 0; + + err = grub_bsd_add_mmap (); + if (err) + return err; + + err = grub_netbsd_setup_video (); + if (err) + { + grub_print_error (); + grub_printf ("Booting however\n"); + grub_errno = GRUB_ERR_NONE; + } + + err = grub_netbsd_add_modules (); + if (err) + return err; + + { + struct bsd_tag *tag; + tag_buf_len = 0; + for (tag = tags; tag; tag = tag->next) + { + tag_buf_len = ALIGN_VAR (tag_buf_len + + sizeof (struct grub_netbsd_btinfo_common) + + tag->len); + tag_count++; + } + } + + arg_target = kern_end; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + arg_target, tag_buf_len + + sizeof (struct grub_netbsd_bootinfo) + + tag_count * sizeof (grub_uint32_t)); + if (err) + return err; + curarg = get_virtual_current_address (ch); + } + + arg0 = curarg; + bootinfo = (void *) ((grub_uint8_t *) arg0 + tag_buf_len); + + { + struct bsd_tag *tag; + unsigned i; + + bootinfo->bi_count = tag_count; + for (tag = tags, i = 0; tag; i++, tag = tag->next) + { + struct grub_netbsd_btinfo_common *head = curarg; + bootinfo->bi_data[i] = ((grub_uint8_t *) curarg - (grub_uint8_t *) arg0) + + arg_target; + head->type = tag->type; + head->len = tag->len + sizeof (*head); + curarg = head + 1; + grub_memcpy (curarg, tag->data, tag->len); + curarg = (grub_uint8_t *) curarg + tag->len; + } + } + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x10000, 0x90000, + 7 * sizeof (grub_uint32_t), 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + stack = get_virtual_current_address (ch); + stack_target = get_physical_target_address (ch); + } + +#ifdef GRUB_MACHINE_EFI + err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); + if (err) + return err; +#endif + + state.eip = entry; + state.esp = stack_target; + state.ebp = stack_target; + stack[0] = entry; + stack[1] = bootflags; + stack[2] = 0; + stack[3] = ((grub_uint8_t *) bootinfo - (grub_uint8_t *) arg0) + arg_target; + stack[4] = 0; + stack[5] = grub_mmap_get_upper () >> 10; + stack[6] = grub_mmap_get_lower () >> 10; + + return grub_relocator32_boot (relocator, state); +} + +static grub_err_t +grub_bsd_unload (void) +{ + struct bsd_tag *tag, *next; + for (tag = tags; tag; tag = next) + { + next = tag->next; + grub_free (tag); + } + tags = NULL; + tags_last = NULL; + + kernel_type = KERNEL_TYPE_NONE; + grub_dl_unref (my_mod); + + grub_relocator_unload (relocator); + relocator = NULL; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_bsd_load_aout (grub_file_t file) +{ + grub_addr_t load_addr, load_end; + int ofs, align_page; + union grub_aout_header ah; + grub_err_t err; + grub_size_t bss_size; + + if ((grub_file_seek (file, 0)) == (grub_off_t) - 1) + return grub_errno; + + if (grub_file_read (file, &ah, sizeof (ah)) != sizeof (ah)) + return grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header"); + + if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32) + return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header"); + + entry = ah.aout32.a_entry & 0xFFFFFF; + + if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC) + { + load_addr = entry; + ofs = 0x1000; + align_page = 0; + } + else + { + load_addr = entry & 0xF00000; + ofs = sizeof (struct grub_aout32_header); + align_page = 1; + } + + if (load_addr < 0x100000) + return grub_error (GRUB_ERR_BAD_OS, "load address below 1M"); + + kern_start = load_addr; + load_end = kern_end = load_addr + ah.aout32.a_text + ah.aout32.a_data; + if (align_page) + kern_end = ALIGN_PAGE (kern_end); + + if (ah.aout32.a_bss) + { + kern_end += ah.aout32.a_bss; + if (align_page) + kern_end = ALIGN_PAGE (kern_end); + + bss_size = kern_end - load_end; + } + else + bss_size = 0; + + { + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + kern_start, kern_end - kern_start); + if (err) + return err; + kern_chunk_src = get_virtual_current_address (ch); + } + + return grub_aout_load (file, ofs, kern_chunk_src, + ah.aout32.a_text + ah.aout32.a_data, + bss_size); +} + +static int NESTED_FUNC_ATTR +grub_bsd_elf32_size_hook (grub_elf_t elf __attribute__ ((unused)), + Elf32_Phdr *phdr, void *arg __attribute__ ((unused))) +{ + Elf32_Addr paddr; + + if (phdr->p_type != PT_LOAD + && phdr->p_type != PT_DYNAMIC) + return 0; + + paddr = phdr->p_paddr & 0xFFFFFF; + + if (paddr < kern_start) + kern_start = paddr; + + if (paddr + phdr->p_memsz > kern_end) + kern_end = paddr + phdr->p_memsz; + + return 0; +} + +static grub_err_t +grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load) +{ + Elf32_Addr paddr; + + if (phdr->p_type != PT_LOAD + && phdr->p_type != PT_DYNAMIC) + { + *do_load = 0; + return 0; + } + + *do_load = 1; + phdr->p_paddr &= 0xFFFFFF; + paddr = phdr->p_paddr; + + *addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src); + + return GRUB_ERR_NONE; +} + +static int NESTED_FUNC_ATTR +grub_bsd_elf64_size_hook (grub_elf_t elf __attribute__ ((unused)), + Elf64_Phdr *phdr, void *arg __attribute__ ((unused))) +{ + Elf64_Addr paddr; + + if (phdr->p_type != PT_LOAD + && phdr->p_type != PT_DYNAMIC) + return 0; + + paddr = phdr->p_paddr & 0xffffff; + + if (paddr < kern_start) + kern_start = paddr; + + if (paddr + phdr->p_memsz > kern_end) + kern_end = paddr + phdr->p_memsz; + + return 0; +} + +static grub_err_t +grub_bsd_elf64_hook (Elf64_Phdr * phdr, grub_addr_t * addr, int *do_load) +{ + Elf64_Addr paddr; + + if (phdr->p_type != PT_LOAD + && phdr->p_type != PT_DYNAMIC) + { + *do_load = 0; + return 0; + } + + *do_load = 1; + paddr = phdr->p_paddr & 0xffffff; + + *addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_bsd_load_elf (grub_elf_t elf) +{ + grub_err_t err; + + kern_end = 0; + kern_start = ~0; + + if (grub_elf_is_elf32 (elf)) + { + grub_relocator_chunk_t ch; + + entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; + err = grub_elf32_phdr_iterate (elf, grub_bsd_elf32_size_hook, NULL); + if (err) + return err; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + kern_start, kern_end - kern_start); + if (err) + return err; + + kern_chunk_src = get_virtual_current_address (ch); + + err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0); + if (err) + return err; + if (kernel_type != KERNEL_TYPE_OPENBSD) + return GRUB_ERR_NONE; + return grub_openbsd_find_ramdisk32 (elf->file, kern_start, + kern_chunk_src, &openbsd_ramdisk); + } + else if (grub_elf_is_elf64 (elf)) + { + is_64bit = 1; + + if (! grub_cpuid_has_longmode) + return grub_error (GRUB_ERR_BAD_OS, "your CPU does not implement AMD64 architecture"); + + /* FreeBSD has 64-bit entry point. */ + if (kernel_type == KERNEL_TYPE_FREEBSD) + { + entry = elf->ehdr.ehdr64.e_entry & 0xffffffff; + entry_hi = (elf->ehdr.ehdr64.e_entry >> 32) & 0xffffffff; + } + else + { + entry = elf->ehdr.ehdr64.e_entry & 0x0fffffff; + entry_hi = 0; + } + + err = grub_elf64_phdr_iterate (elf, grub_bsd_elf64_size_hook, NULL); + if (err) + return err; + + grub_dprintf ("bsd", "kern_start = %lx, kern_end = %lx\n", + (unsigned long) kern_start, (unsigned long) kern_end); + { + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start, + kern_end - kern_start); + if (err) + return err; + kern_chunk_src = get_virtual_current_address (ch); + } + + err = grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0); + if (err) + return err; + if (kernel_type != KERNEL_TYPE_OPENBSD) + return GRUB_ERR_NONE; + return grub_openbsd_find_ramdisk64 (elf->file, kern_start, + kern_chunk_src, &openbsd_ramdisk); + } + else + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); +} + +static grub_err_t +grub_bsd_load (int argc, char *argv[]) +{ + grub_file_t file; + grub_elf_t elf; + + grub_dl_ref (my_mod); + + grub_loader_unset (); + + grub_memset (&openbsd_ramdisk, 0, sizeof (openbsd_ramdisk)); + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + goto fail; + } + + file = grub_file_open (argv[0]); + if (!file) + goto fail; + + relocator = grub_relocator_new (); + + elf = grub_elf_file (file); + if (elf) + { + is_elf_kernel = 1; + grub_bsd_load_elf (elf); + grub_elf_close (elf); + } + else + { + is_elf_kernel = 0; + grub_errno = 0; + grub_bsd_load_aout (file); + grub_file_close (file); + } + + kern_end = ALIGN_PAGE (kern_end); + +fail: + + if (grub_errno != GRUB_ERR_NONE) + grub_dl_unref (my_mod); + + return grub_errno; +} + +static grub_uint32_t +grub_bsd_parse_flags (const struct grub_arg_list *state, + const grub_uint32_t * flags) +{ + grub_uint32_t result = 0; + unsigned i; + + for (i = 0; flags[i]; i++) + if (state[i].set) + result |= flags[i]; + + return result; +} + +static grub_err_t +grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) +{ + kernel_type = KERNEL_TYPE_FREEBSD; + bootflags = grub_bsd_parse_flags (ctxt->state, freebsd_flags); + + if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) + { + kern_end = ALIGN_PAGE (kern_end); + if (is_elf_kernel) + { + grub_err_t err; + grub_uint64_t data = 0; + grub_file_t file; + int len = is_64bit ? 8 : 4; + + err = grub_freebsd_add_meta_module (argv[0], is_64bit + ? FREEBSD_MODTYPE_KERNEL64 + : FREEBSD_MODTYPE_KERNEL, + argc - 1, argv + 1, + kern_start, + kern_end - kern_start); + if (err) + return err; + + file = grub_file_open (argv[0]); + if (! file) + return grub_errno; + + if (is_64bit) + err = grub_freebsd_load_elf_meta64 (relocator, file, &kern_end); + else + err = grub_freebsd_load_elf_meta32 (relocator, file, &kern_end); + if (err) + return err; + + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_HOWTO, &data, 4); + if (err) + return err; + + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_ENVP, &data, len); + if (err) + return err; + + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_KERNEND, &data, len); + if (err) + return err; + } + grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0); + } + + return grub_errno; +} + +static grub_err_t +grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) +{ + grub_uint32_t bootdev; + + kernel_type = KERNEL_TYPE_OPENBSD; + bootflags = grub_bsd_parse_flags (ctxt->state, openbsd_flags); + + if (ctxt->state[OPENBSD_ROOT_ARG].set) + { + const char *arg = ctxt->state[OPENBSD_ROOT_ARG].arg; + int unit, part; + if (*(arg++) != 'w' || *(arg++) != 'd') + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only device specifications of form " + "wd are supported"); + + unit = grub_strtoul (arg, (char **) &arg, 10); + if (! (arg && *arg >= 'a' && *arg <= 'z')) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only device specifications of form " + "wd are supported"); + + part = *arg - 'a'; + + bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) + + (part << OPENBSD_B_PARTSHIFT)); + } + else + bootdev = 0; + + if (ctxt->state[OPENBSD_SERIAL_ARG].set) + { + struct grub_openbsd_bootarg_console serial; + char *ptr; + unsigned port = 0; + unsigned speed = 9600; + + grub_memset (&serial, 0, sizeof (serial)); + + if (ctxt->state[OPENBSD_SERIAL_ARG].arg) + { + ptr = ctxt->state[OPENBSD_SERIAL_ARG].arg; + if (grub_memcmp (ptr, "com", sizeof ("com") - 1) != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only com0-com3 are supported"); + ptr += sizeof ("com") - 1; + port = grub_strtoul (ptr, &ptr, 0); + if (port >= 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only com0-com3 are supported"); + if (*ptr == ',') + { + ptr++; + speed = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + } + } + + serial.device = (GRUB_OPENBSD_COM_MAJOR << 8) | port; + serial.speed = speed; + + grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial)); + bootflags |= OPENBSD_RB_SERCONS; + } + else + { + struct grub_openbsd_bootarg_console serial; + + grub_memset (&serial, 0, sizeof (serial)); + serial.device = (GRUB_OPENBSD_VGA_MAJOR << 8); + grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial)); + bootflags &= ~OPENBSD_RB_SERCONS; + } + + if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) + { + grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 0); + openbsd_root = bootdev; + } + + return grub_errno; +} + +static grub_err_t +grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) +{ + grub_err_t err; + kernel_type = KERNEL_TYPE_NETBSD; + bootflags = grub_bsd_parse_flags (ctxt->state, netbsd_flags); + + if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) + { + if (is_elf_kernel) + { + grub_file_t file; + + file = grub_file_open (argv[0]); + if (! file) + return grub_errno; + + if (is_64bit) + err = grub_netbsd_load_elf_meta64 (relocator, file, &kern_end); + else + err = grub_netbsd_load_elf_meta32 (relocator, file, &kern_end); + if (err) + return err; + } + + { + char bootpath[GRUB_NETBSD_MAX_BOOTPATH_LEN]; + char *name; + name = grub_strrchr (argv[0], '/'); + if (name) + name++; + else + name = argv[0]; + grub_memset (bootpath, 0, sizeof (bootpath)); + grub_strncpy (bootpath, name, sizeof (bootpath) - 1); + grub_bsd_add_meta (NETBSD_BTINFO_BOOTPATH, bootpath, sizeof (bootpath)); + } + + if (ctxt->state[NETBSD_ROOT_ARG].set) + { + char root[GRUB_NETBSD_MAX_ROOTDEVICE_LEN]; + grub_memset (root, 0, sizeof (root)); + grub_strncpy (root, ctxt->state[NETBSD_ROOT_ARG].arg, + sizeof (root) - 1); + grub_bsd_add_meta (NETBSD_BTINFO_ROOTDEVICE, root, sizeof (root)); + } + if (ctxt->state[NETBSD_SERIAL_ARG].set) + { + struct grub_netbsd_btinfo_serial serial; + char *ptr; + + grub_memset (&serial, 0, sizeof (serial)); + grub_strcpy (serial.devname, "com"); + + serial.addr = grub_ns8250_hw_get_port (0); + serial.speed = 9600; + + if (ctxt->state[NETBSD_SERIAL_ARG].arg) + { + ptr = ctxt->state[NETBSD_SERIAL_ARG].arg; + if (grub_memcmp (ptr, "com", sizeof ("com") - 1) == 0) + { + ptr += sizeof ("com") - 1; + serial.addr + = grub_ns8250_hw_get_port (grub_strtoul (ptr, &ptr, 0)); + } + else + serial.addr = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + + if (*ptr == ',') + { + ptr++; + serial.speed = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + } + } + + grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &serial, sizeof (serial)); + } + else + { + struct grub_netbsd_btinfo_serial cons; + + grub_memset (&cons, 0, sizeof (cons)); + grub_strcpy (cons.devname, "pc"); + + grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons)); + } + + grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0); + } + + return grub_errno; +} + +static grub_err_t +grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + char *buf = 0, *curr, *next; + int len; + + if (kernel_type == KERNEL_TYPE_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "you need to load the kernel first"); + + if (kernel_type != KERNEL_TYPE_FREEBSD) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only FreeBSD supports environment"); + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename"); + goto fail; + } + + file = grub_file_open (argv[0]); + if ((!file) || (!file->size)) + goto fail; + + len = file->size; + buf = grub_malloc (len + 1); + if (!buf) + goto fail; + + if (grub_file_read (file, buf, len) != len) + goto fail; + + buf[len] = 0; + + next = buf; + while (next) + { + char *p; + + curr = next; + next = grub_strchr (curr, '\n'); + if (next) + { + + p = next - 1; + while (p > curr) + { + if ((*p != '\r') && (*p != ' ') && (*p != '\t')) + break; + p--; + } + + if ((p > curr) && (*p == '"')) + p--; + + *(p + 1) = 0; + next++; + } + + if (*curr == '#') + continue; + + p = grub_strchr (curr, '='); + if (!p) + continue; + + *(p++) = 0; + + if (*curr) + { + char *name; + + if (*p == '"') + p++; + + name = grub_xasprintf ("kFreeBSD.%s", curr); + if (!name) + goto fail; + if (grub_env_set (name, p)) + { + grub_free (name); + goto fail; + } + grub_free (name); + } + } + +fail: + grub_free (buf); + + if (file) + grub_file_close (file); + + return grub_errno; +} + +static grub_err_t +grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + int modargc; + char **modargv; + char *type; + grub_err_t err; + void *src; + + if (kernel_type != KERNEL_TYPE_FREEBSD) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no FreeBSD loaded"); + + if (!is_elf_kernel) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only ELF kernel supports module"); + + /* List the current modules if no parameter. */ + if (!argc) + { + grub_freebsd_list_modules (); + return 0; + } + + file = grub_file_open (argv[0]); + if ((!file) || (!file->size)) + goto fail; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_end, + file->size); + if (err) + goto fail; + src = get_virtual_current_address (ch); + } + + + grub_file_read (file, src, file->size); + if (grub_errno) + goto fail; + + modargc = argc - 1; + modargv = argv + 1; + + if (modargc && (! grub_memcmp (modargv[0], "type=", 5))) + { + type = &modargv[0][5]; + modargc--; + modargv++; + } + else + type = FREEBSD_MODTYPE_RAW; + + err = grub_freebsd_add_meta_module (argv[0], type, modargc, modargv, + kern_end, file->size); + if (err) + goto fail; + + kern_end = ALIGN_PAGE (kern_end + file->size); + +fail: + if (file) + grub_file_close (file); + + return grub_errno; +} + +static grub_err_t +grub_netbsd_module_load (char *filename, grub_uint32_t type) +{ + grub_file_t file = 0; + void *src; + grub_err_t err; + + file = grub_file_open (filename); + if ((!file) || (!file->size)) + goto fail; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_end, + file->size); + if (err) + goto fail; + + src = get_virtual_current_address (ch); + } + + grub_file_read (file, src, file->size); + if (grub_errno) + goto fail; + + err = grub_netbsd_add_meta_module (filename, type, kern_end, file->size); + + if (err) + goto fail; + + kern_end = ALIGN_PAGE (kern_end + file->size); + +fail: + if (file) + grub_file_close (file); + + return grub_errno; +} + +static grub_err_t +grub_cmd_netbsd_module (grub_command_t cmd, + int argc, char *argv[]) +{ + grub_uint32_t type; + + if (kernel_type != KERNEL_TYPE_NETBSD) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no NetBSD loaded"); + + if (!is_elf_kernel) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only ELF kernel supports module"); + + /* List the current modules if no parameter. */ + if (!argc) + { + grub_netbsd_list_modules (); + return 0; + } + + if (grub_strcmp (cmd->name, "knetbsd_module_elf") == 0) + type = GRUB_NETBSD_MODULE_ELF; + else + type = GRUB_NETBSD_MODULE_RAW; + + return grub_netbsd_module_load (argv[0], type); +} + +static grub_err_t +grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_err_t err; + + if (kernel_type == KERNEL_TYPE_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "you need to load the kernel first"); + + if (kernel_type != KERNEL_TYPE_FREEBSD) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only FreeBSD supports module"); + + if (! is_elf_kernel) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "only ELF kernel supports module"); + + /* List the current modules if no parameter. */ + if (! argc) + { + grub_freebsd_list_modules (); + return 0; + } + + file = grub_file_open (argv[0]); + if (!file) + return grub_errno; + if (!file->size) + { + grub_file_close (file); + return grub_errno; + } + + if (is_64bit) + err = grub_freebsd_load_elfmodule_obj64 (relocator, file, + argc, argv, &kern_end); + else + err = grub_freebsd_load_elfmodule32 (relocator, file, + argc, argv, &kern_end); + grub_file_close (file); + + return err; +} + +static grub_err_t +grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)), + int argc, char *args[]) +{ + grub_file_t file; + grub_size_t size; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + if (kernel_type != KERNEL_TYPE_OPENBSD) + return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded"); + + if (!openbsd_ramdisk.max_size) + return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD doesn't support ramdisk"); + + file = grub_file_open (args[0]); + if (! file) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "couldn't load ramdisk"); + + size = grub_file_size (file); + + if (size > openbsd_ramdisk.max_size) + { + grub_file_close (file); + return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD supports ramdisk only" + " up to %u bytes, however you supplied a %u bytes one", + openbsd_ramdisk.max_size, size); + } + + if (grub_file_read (file, openbsd_ramdisk.target, size) + != (grub_ssize_t) (size)) + { + grub_file_close (file); + grub_error_push (); + return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); + } + grub_memset (openbsd_ramdisk.target + size, 0, + openbsd_ramdisk.max_size - size); + *openbsd_ramdisk.size = ALIGN_UP (size, 512); + + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd_freebsd, cmd_openbsd, cmd_netbsd; +static grub_command_t cmd_freebsd_loadenv, cmd_freebsd_module; +static grub_command_t cmd_netbsd_module, cmd_freebsd_module_elf; +static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk; + +GRUB_MOD_INIT (bsd) +{ + /* Net and OpenBSD kernels are often compressed. */ + grub_dl_load ("gzio"); + + cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, 0, + N_("FILE"), N_("Load kernel of FreeBSD."), + freebsd_opts); + cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, 0, + N_("FILE"), N_("Load kernel of OpenBSD."), + openbsd_opts); + cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, 0, + N_("FILE"), N_("Load kernel of NetBSD."), + netbsd_opts); + cmd_freebsd_loadenv = + grub_register_command ("kfreebsd_loadenv", grub_cmd_freebsd_loadenv, + 0, N_("Load FreeBSD env.")); + cmd_freebsd_module = + grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module, + 0, N_("Load FreeBSD kernel module.")); + cmd_netbsd_module = + grub_register_command ("knetbsd_module", grub_cmd_netbsd_module, + 0, N_("Load NetBSD kernel module.")); + cmd_netbsd_module_elf = + grub_register_command ("knetbsd_module_elf", grub_cmd_netbsd_module, + 0, N_("Load NetBSD kernel module (ELF).")); + cmd_freebsd_module_elf = + grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf, + 0, N_("Load FreeBSD kernel module (ELF).")); + + cmd_openbsd_ramdisk = grub_register_command ("kopenbsd_ramdisk", + grub_cmd_openbsd_ramdisk, 0, + "Load kOpenBSD ramdisk. "); + + my_mod = mod; +} + +GRUB_MOD_FINI (bsd) +{ + grub_unregister_extcmd (cmd_freebsd); + grub_unregister_extcmd (cmd_openbsd); + grub_unregister_extcmd (cmd_netbsd); + + grub_unregister_command (cmd_freebsd_loadenv); + grub_unregister_command (cmd_freebsd_module); + grub_unregister_command (cmd_netbsd_module); + grub_unregister_command (cmd_freebsd_module_elf); + grub_unregister_command (cmd_netbsd_module_elf); + grub_unregister_command (cmd_openbsd_ramdisk); + + grub_bsd_unload (); +} diff --git a/loader/i386/bsd32.c b/grub-core/loader/i386/bsd32.c similarity index 100% rename from loader/i386/bsd32.c rename to grub-core/loader/i386/bsd32.c diff --git a/loader/i386/bsd64.c b/grub-core/loader/i386/bsd64.c similarity index 100% rename from loader/i386/bsd64.c rename to grub-core/loader/i386/bsd64.c diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c new file mode 100644 index 000000000..29892e5fb --- /dev/null +++ b/grub-core/loader/i386/bsdXX.c @@ -0,0 +1,616 @@ +#include +#include +#include +#include +#include +#include + +#define ALIGN_PAGE(a) ALIGN_UP (a, 4096) + +static inline grub_err_t +load (grub_file_t file, void *where, grub_off_t off, grub_size_t size) +{ + if (grub_file_seek (file, off) == (grub_off_t) -1) + return grub_errno; + if (grub_file_read (file, where, size) != (grub_ssize_t) size) + { + if (grub_errno) + return grub_errno; + else + return grub_error (GRUB_ERR_BAD_OS, "file is truncated"); + } + return GRUB_ERR_NONE; +} + +static inline grub_err_t +read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr) +{ + if (grub_file_seek (file, 0) == (grub_off_t) -1) + return grub_errno; + + if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e)) + { + if (grub_errno) + return grub_errno; + else + return grub_error (GRUB_ERR_BAD_OS, "file is too short"); + } + + if (e->e_ident[EI_MAG0] != ELFMAG0 + || e->e_ident[EI_MAG1] != ELFMAG1 + || e->e_ident[EI_MAG2] != ELFMAG2 + || e->e_ident[EI_MAG3] != ELFMAG3 + || e->e_ident[EI_VERSION] != EV_CURRENT + || e->e_version != EV_CURRENT) + return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic"); + + if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS)) + return grub_error (GRUB_ERR_BAD_OS, "invalid arch dependent ELF magic"); + + *shdr = grub_malloc (e->e_shnum * e->e_shentsize); + if (! *shdr) + return grub_errno; + + if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1) + return grub_errno; + + if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize) + != e->e_shnum * e->e_shentsize) + { + if (grub_errno) + return grub_errno; + else + return grub_error (GRUB_ERR_BAD_OS, "file is truncated"); + } + + return GRUB_ERR_NONE; +} + +/* On i386 FreeBSD uses "elf module" approarch for 32-bit variant + and "elf obj module" for 64-bit variant. However it may differ on other + platforms. So I keep both versions. */ +#if OBJSYM +grub_err_t +SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, + grub_file_t file, int argc, + char *argv[], grub_addr_t *kern_end) +{ + Elf_Ehdr e; + Elf_Shdr *s; + char *shdr = 0; + grub_addr_t curload, module; + grub_err_t err; + grub_size_t chunk_size = 0; + void *chunk_src; + + err = read_headers (file, &e, &shdr); + if (err) + return err; + + curload = module = ALIGN_PAGE (*kern_end); + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + { + if (s->sh_size == 0) + continue; + + if (s->sh_addralign) + chunk_size = ALIGN_UP (chunk_size + *kern_end, s->sh_addralign) + - *kern_end; + + chunk_size += s->sh_size; + } + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + module, chunk_size); + if (err) + return err; + chunk_src = get_virtual_current_address (ch); + } + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + { + if (s->sh_size == 0) + continue; + + if (s->sh_addralign) + curload = ALIGN_UP (curload, s->sh_addralign); + s->sh_addr = curload; + + grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", + (unsigned) curload, (int) s->sh_size, + (int) s->sh_addralign); + + switch (s->sh_type) + { + default: + case SHT_PROGBITS: + err = load (file, (grub_uint8_t *) chunk_src + curload - *kern_end, + s->sh_offset, s->sh_size); + if (err) + return err; + break; + case SHT_NOBITS: + grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0, + s->sh_size); + break; + } + curload += s->sh_size; + } + + *kern_end = ALIGN_PAGE (curload); + + err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ, + argc - 1, argv + 1, module, + curload - module); + if (! err) + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA + | FREEBSD_MODINFOMD_ELFHDR, + &e, sizeof (e)); + if (! err) + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA + | FREEBSD_MODINFOMD_SHDR, + shdr, e.e_shnum * e.e_shentsize); + + return err; +} + +#else + +grub_err_t +SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, + grub_file_t file, int argc, char *argv[], + grub_addr_t *kern_end) +{ + Elf_Ehdr e; + Elf_Shdr *s; + char *shdr = 0; + grub_addr_t curload, module; + grub_err_t err; + grub_size_t chunk_size = 0; + void *chunk_src; + + err = read_headers (file, &e, &shdr); + if (err) + return err; + + curload = module = ALIGN_PAGE (*kern_end); + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + { + if (s->sh_size == 0) + continue; + + if (! (s->sh_flags & SHF_ALLOC)) + continue; + if (chunk_size < s->sh_addr + s->sh_size) + chunk_size = s->sh_addr + s->sh_size; + } + + { + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + module, chunk_size); + if (err) + return err; + + chunk_src = get_virtual_current_address (ch); + } + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + { + if (s->sh_size == 0) + continue; + + if (! (s->sh_flags & SHF_ALLOC)) + continue; + + grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", + (unsigned) curload, (int) s->sh_size, + (int) s->sh_addralign); + + switch (s->sh_type) + { + default: + case SHT_PROGBITS: + err = load (file, (grub_uint8_t *) chunk_src + module + + s->sh_addr - *kern_end, + s->sh_offset, s->sh_size); + if (err) + return err; + break; + case SHT_NOBITS: + grub_memset ((grub_uint8_t *) chunk_src + module + + s->sh_addr - *kern_end, 0, s->sh_size); + break; + } + if (curload < module + s->sh_addr + s->sh_size) + curload = module + s->sh_addr + s->sh_size; + } + + load (file, UINT_TO_PTR (module), 0, sizeof (e)); + if (curload < module + sizeof (e)) + curload = module + sizeof (e); + + load (file, UINT_TO_PTR (curload), e.e_shoff, + e.e_shnum * e.e_shentsize); + e.e_shoff = curload - module; + curload += e.e_shnum * e.e_shentsize; + + load (file, UINT_TO_PTR (curload), e.e_phoff, + e.e_phnum * e.e_phentsize); + e.e_phoff = curload - module; + curload += e.e_phnum * e.e_phentsize; + + *kern_end = curload; + + grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, + argc - 1, argv + 1, module, + curload - module); + return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, kern_end); +} + +#endif + +grub_err_t +SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, + grub_file_t file, grub_addr_t *kern_end) +{ + grub_err_t err; + Elf_Ehdr e; + Elf_Shdr *s; + char *shdr = 0; + unsigned symoff, stroff, symsize, strsize; + grub_freebsd_addr_t symstart, symend, symentsize, dynamic; + Elf_Sym *sym; + void *sym_chunk; + grub_uint8_t *curload; + grub_freebsd_addr_t symtarget; + const char *str; + unsigned i; + grub_size_t chunk_size; + + err = read_headers (file, &e, &shdr); + if (err) + return err; + + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_ELFHDR, &e, + sizeof (e)); + if (err) + return err; + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + if (s >= (Elf_Shdr *) ((char *) shdr + + e.e_shnum * e.e_shentsize)) + return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); + symoff = s->sh_offset; + symsize = s->sh_size; + symentsize = s->sh_entsize; + s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); + stroff = s->sh_offset; + strsize = s->sh_size; + + chunk_size = ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t)) + + 2 * sizeof (grub_freebsd_addr_t); + + symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + symtarget, chunk_size); + if (err) + return err; + sym_chunk = get_virtual_current_address (ch); + } + + symstart = symtarget; + symend = symstart + chunk_size; + + curload = sym_chunk; + *((grub_freebsd_addr_t *) curload) = symsize; + curload += sizeof (grub_freebsd_addr_t); + + if (grub_file_seek (file, symoff) == (grub_off_t) -1) + return grub_errno; + sym = (Elf_Sym *) curload; + if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) + { + if (! grub_errno) + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_errno; + } + curload += symsize; + + *((grub_freebsd_addr_t *) curload) = strsize; + curload += sizeof (grub_freebsd_addr_t); + if (grub_file_seek (file, stroff) == (grub_off_t) -1) + return grub_errno; + str = (char *) curload; + if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) + { + if (! grub_errno) + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_errno; + } + + for (i = 0; + i * symentsize < symsize; + i++, sym = (Elf_Sym *) ((char *) sym + symentsize)) + { + const char *name = str + sym->st_name; + if (grub_strcmp (name, "_DYNAMIC") == 0) + break; + } + + if (i * symentsize < symsize) + { + dynamic = sym->st_value; + grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic); + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_DYNAMIC, &dynamic, + sizeof (dynamic)); + if (err) + return err; + } + + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_SSYM, &symstart, + sizeof (symstart)); + if (err) + return err; + + err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA | + FREEBSD_MODINFOMD_ESYM, &symend, + sizeof (symend)); + if (err) + return err; + + *kern_end = ALIGN_PAGE (symend); + + return GRUB_ERR_NONE; +} + +grub_err_t +SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, + grub_file_t file, grub_addr_t *kern_end) +{ + grub_err_t err; + Elf_Ehdr e; + Elf_Shdr *s, *symsh, *strsh; + char *shdr; + unsigned symsize, strsize; + void *sym_chunk; + grub_uint8_t *curload; + grub_size_t chunk_size; + Elf_Ehdr *e2; + struct grub_netbsd_btinfo_symtab symtab; + grub_addr_t symtarget; + + err = read_headers (file, &e, &shdr); + if (err) + return err; + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + if (s >= (Elf_Shdr *) ((char *) shdr + + e.e_shnum * e.e_shentsize)) + return GRUB_ERR_NONE; + symsize = s->sh_size; + symsh = s; + s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); + strsize = s->sh_size; + strsh = s; + + chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)) + + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t)) + + sizeof (e) + e.e_shnum * e.e_shentsize; + + symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + symtarget, chunk_size); + if (err) + return err; + sym_chunk = get_virtual_current_address (ch); + } + + symtab.nsyms = 1; + symtab.ssyms = symtarget; + symtab.esyms = symtarget + chunk_size; + + curload = sym_chunk; + + e2 = (Elf_Ehdr *) curload; + grub_memcpy (curload, &e, sizeof (e)); + e2->e_phoff = 0; + e2->e_phnum = 0; + e2->e_phentsize = 0; + e2->e_shstrndx = 0; + e2->e_shoff = sizeof (e); + + curload += sizeof (e); + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + { + Elf_Shdr *s2; + s2 = (Elf_Shdr *) curload; + grub_memcpy (curload, s, e.e_shentsize); + if (s == symsh) + s2->sh_offset = sizeof (e) + e.e_shnum * e.e_shentsize; + else if (s == strsh) + s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)) + + sizeof (e) + e.e_shnum * e.e_shentsize; + else + s2->sh_offset = 0; + s2->sh_addr = s2->sh_offset; + curload += e.e_shentsize; + } + + if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1) + return grub_errno; + if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) + { + if (! grub_errno) + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_errno; + } + curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)); + + if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1) + return grub_errno; + if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) + { + if (! grub_errno) + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_errno; + } + + err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB, + &symtab, + sizeof (symtab)); + if (err) + return err; + + *kern_end = ALIGN_PAGE (symtarget + chunk_size); + + return GRUB_ERR_NONE; +} + +grub_err_t +SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, + grub_addr_t kern_start, + void *kern_chunk_src, + struct grub_openbsd_ramdisk_descriptor *desc) +{ + unsigned symoff, stroff, symsize, strsize, symentsize; + + { + grub_err_t err; + Elf_Ehdr e; + Elf_Shdr *s; + char *shdr; + + err = read_headers (file, &e, &shdr); + if (err) + return err; + + for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr + + e.e_shnum * e.e_shentsize); + s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) + { + grub_free (shdr); + return GRUB_ERR_NONE; + } + + symsize = s->sh_size; + symentsize = s->sh_entsize; + symoff = s->sh_offset; + + s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); + stroff = s->sh_offset; + strsize = s->sh_size; + grub_free (shdr); + } + { + Elf_Sym *syms, *sym, *imagesym = NULL, *sizesym = NULL; + unsigned i; + char *strs; + + syms = grub_malloc (symsize); + if (!syms) + return grub_errno; + + if (grub_file_seek (file, symoff) == (grub_off_t) -1) + { + grub_free (syms); + return grub_errno; + } + if (grub_file_read (file, syms, symsize) != (grub_ssize_t) symsize) + { + grub_free (syms); + if (! grub_errno) + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_errno; + } + + strs = grub_malloc (strsize); + if (!strs) + { + grub_free (syms); + return grub_errno; + } + + if (grub_file_seek (file, stroff) == (grub_off_t) -1) + return grub_errno; + if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize) + { + grub_free (syms); + grub_free (strs); + if (! grub_errno) + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_errno; + } + + for (i = 0, sym = syms; i < symsize / symentsize; + i++, sym = (Elf_Sym *) ((char *) sym + symentsize)) + { + if (ELF_ST_TYPE (sym->st_info) != STT_OBJECT) + continue; + if (!sym->st_name) + continue; + if (grub_strcmp (strs + sym->st_name, "rd_root_image") == 0) + imagesym = sym; + if (grub_strcmp (strs + sym->st_name, "rd_root_size") == 0) + sizesym = sym; + if (imagesym && sizesym) + break; + } + if (!imagesym || !sizesym) + { + grub_free (syms); + grub_free (strs); + return GRUB_ERR_NONE; + } + if (sizeof (*desc->size) != sizesym->st_size) + { + grub_free (syms); + grub_free (strs); + return grub_error (GRUB_ERR_BAD_OS, "unexpected size of rd_root_size"); + } + desc->max_size = imagesym->st_size; + desc->target = (imagesym->st_value & 0xFFFFFF) - kern_start + + (grub_uint8_t *) kern_chunk_src; + desc->size = (grub_uint32_t *) ((sizesym->st_value & 0xFFFFFF) - kern_start + + (grub_uint8_t *) kern_chunk_src); + grub_free (syms); + grub_free (strs); + + return GRUB_ERR_NONE; + } +} diff --git a/loader/i386/bsd_pagetable.c b/grub-core/loader/i386/bsd_pagetable.c similarity index 89% rename from loader/i386/bsd_pagetable.c rename to grub-core/loader/i386/bsd_pagetable.c index 0fd393707..9ec5abffc 100644 --- a/loader/i386/bsd_pagetable.c +++ b/grub-core/loader/i386/bsd_pagetable.c @@ -50,9 +50,10 @@ static void -fill_bsd64_pagetable (grub_uint8_t *target) +fill_bsd64_pagetable (grub_uint8_t *src, grub_addr_t target) { grub_uint64_t *pt2, *pt3, *pt4; + grub_addr_t pt2t, pt3t; int i; #define PG_V 0x001 @@ -60,11 +61,14 @@ fill_bsd64_pagetable (grub_uint8_t *target) #define PG_U 0x004 #define PG_PS 0x080 - pt4 = (grub_uint64_t *) target; - pt3 = (grub_uint64_t *) (target + 4096); - pt2 = (grub_uint64_t *) (target + 8192); + pt4 = (grub_uint64_t *) src; + pt3 = (grub_uint64_t *) (src + 4096); + pt2 = (grub_uint64_t *) (src + 8192); - grub_memset ((char *) target, 0, 4096 * 3); + pt3t = target + 4096; + pt2t = target + 8192; + + grub_memset (src, 0, 4096 * 3); /* * This is kinda brutal, but every single 1GB VM memory segment points to @@ -74,11 +78,11 @@ fill_bsd64_pagetable (grub_uint8_t *target) for (i = 0; i < 512; i++) { /* Each slot of the level 4 pages points to the same level 3 page */ - pt4[i] = (grub_addr_t) &pt3[0]; + pt4[i] = (grub_addr_t) pt3t; pt4[i] |= PG_V | PG_RW | PG_U; /* Each slot of the level 3 pages points to the same level 2 page */ - pt3[i] = (grub_addr_t) &pt2[0]; + pt3[i] = (grub_addr_t) pt2t; pt3[i] |= PG_V | PG_RW | PG_U; /* The level 2 page slots are mapped with 2MB pages for 1GB. */ diff --git a/loader/i386/linux.c b/grub-core/loader/i386/linux.c similarity index 70% rename from loader/i386/linux.c rename to grub-core/loader/i386/linux.c index d3d935182..de4bec106 100644 --- a/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -17,8 +17,7 @@ */ #include -#include -#include +#include #include #include #include @@ -32,9 +31,27 @@ #include #include #include +#include +#include + +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif + +#ifdef GRUB_MACHINE_EFI +#include +#define HAS_VGA_TEXT 0 +#define DEFAULT_VIDEO_MODE "auto" +#elif defined (GRUB_MACHINE_IEEE1275) +#include +#define HAS_VGA_TEXT 0 +#define DEFAULT_VIDEO_MODE "text" +#else #include #include -#include +#define HAS_VGA_TEXT 1 +#define DEFAULT_VIDEO_MODE "text" +#endif #define GRUB_LINUX_CL_OFFSET 0x1000 #define GRUB_LINUX_CL_END_OFFSET 0x2000 @@ -44,36 +61,24 @@ static grub_dl_t my_mod; static grub_size_t linux_mem_size; static int loaded; static void *real_mode_mem; +static grub_addr_t real_mode_target; static void *prot_mode_mem; +static grub_addr_t prot_mode_target; static void *initrd_mem; +static grub_addr_t initrd_mem_target; static grub_uint32_t real_mode_pages; static grub_uint32_t prot_mode_pages; static grub_uint32_t initrd_pages; +static struct grub_relocator *relocator = NULL; +static void *efi_mmap_buf; +#ifdef GRUB_MACHINE_EFI +static grub_efi_uintn_t efi_mmap_size; +#else +static const grub_size_t efi_mmap_size = 0; +#endif -static grub_uint8_t gdt[] __attribute__ ((aligned(16))) = - { - /* NULL. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Reserved. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Code segment. */ - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, - /* Data segment. */ - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 - }; - -struct gdt_descriptor -{ - grub_uint16_t limit; - void *base; -} __attribute__ ((packed)); - -static struct gdt_descriptor gdt_desc = - { - sizeof (gdt) - 1, - gdt - }; - +/* FIXME */ +#if 0 struct idt_descriptor { grub_uint16_t limit; @@ -85,174 +90,6 @@ static struct idt_descriptor idt_desc = 0, 0 }; - -#ifdef GRUB_MACHINE_PCBIOS -struct linux_vesafb_res -{ - grub_uint16_t width; - grub_uint16_t height; -}; - -struct linux_vesafb_mode -{ - grub_uint8_t res_index; - grub_uint8_t depth; -}; - -enum vga_modes - { - VGA_320_200, - VGA_640_400, - VGA_640_480, - VGA_800_500, - VGA_800_600, - VGA_896_672, - VGA_1024_640, - VGA_1024_768, - VGA_1152_720, - VGA_1280_1024, - VGA_1440_900, - VGA_1600_1200, - }; - -static struct linux_vesafb_res linux_vesafb_res[] = - { - { 320, 200 }, - { 640, 400 }, - { 640, 480 }, - { 800, 500 }, - { 800, 600 }, - { 896, 672 }, - { 1024, 640 }, - { 1024, 768 }, - { 1152, 720 }, - { 1280, 1024 }, - { 1440, 900 }, - { 1600, 1200 }, - }; - -/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt - plus a few more modes based on the table in - http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ -struct linux_vesafb_mode linux_vesafb_modes[] = - { - { VGA_640_400, 8 }, /* 0x300 */ - { VGA_640_480, 8 }, /* 0x301 */ - { VGA_800_600, 4 }, /* 0x302 */ - { VGA_800_600, 8 }, /* 0x303 */ - { VGA_1024_768, 4 }, /* 0x304 */ - { VGA_1024_768, 8 }, /* 0x305 */ - { VGA_1280_1024, 4 }, /* 0x306 */ - { VGA_1280_1024, 8 }, /* 0x307 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_320_200, 15 }, /* 0x30d */ - { VGA_320_200, 16 }, /* 0x30e */ - { VGA_320_200, 24 }, /* 0x30f */ - { VGA_640_480, 15 }, /* 0x310 */ - { VGA_640_480, 16 }, /* 0x311 */ - { VGA_640_480, 24 }, /* 0x312 */ - { VGA_800_600, 15 }, /* 0x313 */ - { VGA_800_600, 16 }, /* 0x314 */ - { VGA_800_600, 24 }, /* 0x315 */ - { VGA_1024_768, 15 }, /* 0x316 */ - { VGA_1024_768, 16 }, /* 0x317 */ - { VGA_1024_768, 24 }, /* 0x318 */ - { VGA_1280_1024, 15 }, /* 0x319 */ - { VGA_1280_1024, 16 }, /* 0x31a */ - { VGA_1280_1024, 24 }, /* 0x31b */ - { VGA_1600_1200, 8 }, /* 0x31c */ - { VGA_1600_1200, 15 }, /* 0x31d */ - { VGA_1600_1200, 16 }, /* 0x31e */ - { VGA_1600_1200, 24 }, /* 0x31f */ - { 0, 0 }, - { VGA_640_400, 15 }, /* 0x321 */ - { VGA_640_400, 16 }, /* 0x322 */ - { VGA_640_400, 24 }, /* 0x323 */ - { VGA_640_400, 32 }, /* 0x324 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_640_480, 32 }, /* 0x329 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_896_672, 8 }, /* 0x32f */ - { VGA_896_672, 15 }, /* 0x330 */ - { VGA_896_672, 16 }, /* 0x331 */ - { VGA_896_672, 24 }, /* 0x332 */ - { VGA_896_672, 32 }, /* 0x333 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_1600_1200, 32 }, /* 0x342 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_1440_900, 8 }, /* 0x360 */ - { VGA_1440_900, 15 }, /* 0x361 */ - { VGA_1440_900, 16 }, /* 0x362 */ - { VGA_1440_900, 24 }, /* 0x363 */ - { VGA_1440_900, 32 }, /* 0x364 */ - { VGA_1152_720, 8 }, /* 0x365 */ - { VGA_1152_720, 15 }, /* 0x366 */ - { VGA_1152_720, 16 }, /* 0x367 */ - { VGA_1152_720, 24 }, /* 0x368 */ - { VGA_1152_720, 32 }, /* 0x369 */ - { VGA_1024_640, 8 }, /* 0x36a */ - { VGA_1024_640, 15 }, /* 0x36b */ - { VGA_1024_640, 16 }, /* 0x36c */ - { VGA_1024_640, 24 }, /* 0x36d */ - { VGA_1024_640, 32 }, /* 0x36e */ - { VGA_800_500, 8 }, /* 0x36f */ - { VGA_800_500, 15 }, /* 0x370 */ - { VGA_800_500, 16 }, /* 0x371 */ - { VGA_800_500, 24 }, /* 0x372 */ - { VGA_800_500, 32 }, /* 0x373 */ - }; #endif static inline grub_size_t @@ -261,16 +98,59 @@ page_align (grub_size_t size) return (size + (1 << 12) - 1) & (~((1 << 12) - 1)); } +#ifdef GRUB_MACHINE_EFI +/* Find the optimal number of pages for the memory map. Is it better to + move this code to efi/mm.c? */ +static grub_efi_uintn_t +find_efi_mmap_size (void) +{ + static grub_efi_uintn_t mmap_size = 0; + + if (mmap_size != 0) + return mmap_size; + + mmap_size = (1 << 12); + while (1) + { + int ret; + grub_efi_memory_descriptor_t *mmap; + grub_efi_uintn_t desc_size; + + mmap = grub_malloc (mmap_size); + if (! mmap) + return 0; + + ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); + grub_free (mmap); + + if (ret < 0) + grub_fatal ("cannot get memory map"); + else if (ret > 0) + break; + + mmap_size += (1 << 12); + } + + /* Increase the size a bit for safety, because GRUB allocates more on + later, and EFI itself may allocate more. */ + mmap_size += (1 << 12); + + return page_align (mmap_size); +} + +#endif + /* Find the optimal number of pages for the memory map. */ static grub_size_t find_mmap_size (void) { grub_size_t count = 0, mmap_size; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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 __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { count++; return 0; @@ -290,41 +170,58 @@ find_mmap_size (void) static void free_pages (void) { + grub_relocator_unload (relocator); + relocator = NULL; real_mode_mem = prot_mode_mem = initrd_mem = 0; + real_mode_target = prot_mode_target = initrd_mem_target = 0; } /* Allocate pages for the real mode code and the protected mode code for linux as well as a memory map buffer. */ -static int +static grub_err_t allocate_pages (grub_size_t prot_size) { grub_size_t real_size, mmap_size; + grub_err_t err; /* Make sure that each size is aligned to a page boundary. */ real_size = GRUB_LINUX_CL_END_OFFSET; prot_size = page_align (prot_size); mmap_size = find_mmap_size (); +#ifdef GRUB_MACHINE_EFI + efi_mmap_size = find_efi_mmap_size (); +#endif + grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n", (unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size); /* Calculate the number of pages; Combine the real mode code with the memory map buffer for simplicity. */ - real_mode_pages = ((real_size + mmap_size) >> 12); + real_mode_pages = ((real_size + mmap_size + efi_mmap_size) >> 12); prot_mode_pages = (prot_size >> 12); /* Initialize the memory pointers with NULL for convenience. */ free_pages (); + relocator = grub_relocator_new (); + if (!relocator) + { + err = grub_errno; + goto fail; + } + /* FIXME: Should request low memory from the heap when this feature is implemented. */ - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + 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) { /* We must put real mode code in the traditional space. */ - if (type == GRUB_MACHINE_MEMORY_AVAILABLE + if (type == GRUB_MEMORY_AVAILABLE && addr <= 0x90000) { if (addr < 0x10000) @@ -336,35 +233,55 @@ allocate_pages (grub_size_t prot_size) if (addr + size > 0x90000) size = 0x90000 - addr; - if (real_size + mmap_size > size) + if (real_size + mmap_size + efi_mmap_size > size) return 0; - real_mode_mem = - (void *) (grub_size_t) ((addr + size) - (real_size + mmap_size)); + real_mode_target = ((addr + size) - (real_size + mmap_size + efi_mmap_size)); return 1; } return 0; } grub_mmap_iterate (hook); - if (! real_mode_mem) + if (! real_mode_target) { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); goto fail; } - prot_mode_mem = (void *) 0x100000; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + real_mode_target, + (real_size + mmap_size + + efi_mmap_size)); + if (err) + goto fail; + real_mode_mem = get_virtual_current_address (ch); + } + efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size + mmap_size; + + prot_mode_target = GRUB_LINUX_BZIMAGE_ADDR; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + prot_mode_target, prot_size); + if (err) + goto fail; + prot_mode_mem = get_virtual_current_address (ch); + } grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, " "prot_mode_mem = %lx, prot_mode_pages = %x\n", (unsigned long) real_mode_mem, (unsigned) real_mode_pages, (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages); - return 1; + return GRUB_ERR_NONE; fail: free_pages (); - return 0; + return err; } static void @@ -389,7 +306,7 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num, } } -static int +static grub_err_t grub_linux_setup_video (struct linux_kernel_params *params) { struct grub_video_mode_info mode_info; @@ -448,14 +365,9 @@ grub_linux_setup_video (struct linux_kernel_params *params) } #endif - return 0; + return GRUB_ERR_NONE; } -#ifdef __x86_64__ -extern grub_uint8_t grub_linux_trampoline_start[]; -extern grub_uint8_t grub_linux_trampoline_end[]; -#endif - static grub_err_t grub_linux_boot (void) { @@ -463,47 +375,53 @@ grub_linux_boot (void) int e820_num; grub_err_t err = 0; char *modevar, *tmp; + struct grub_relocator32_state state; params = real_mode_mem; - grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n", - (unsigned) params->code32_start, - (unsigned long) &(idt_desc.limit), - (unsigned long) &(gdt_desc.limit)); - grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n", - (unsigned) idt_desc.limit, (unsigned long) idt_desc.base, - (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base); +#ifdef GRUB_MACHINE_IEEE1275 + { + char *bootpath; + grub_ssize_t len; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + bootpath = grub_env_get ("root"); + if (bootpath) + grub_ieee1275_set_property (grub_ieee1275_chosen, + "bootpath", bootpath, + grub_strlen (bootpath) + 1, + &len); + } +#endif + + grub_dprintf ("linux", "code32_start = %x\n", + (unsigned) params->code32_start); + + 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) { switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_RAM); break; -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_ACPI); break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_NVS); break; -#endif -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: + case GRUB_MEMORY_CODE: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_EXEC_CODE); break; -#endif default: grub_e820_add_region (params->e820_map, &e820_num, @@ -522,14 +440,14 @@ grub_linux_boot (void) May change in future if we have modes without framebuffer. */ if (modevar && *modevar != 0) { - tmp = grub_xasprintf ("%s;text", modevar); + tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); if (! tmp) return grub_errno; err = grub_video_set_mode (tmp, 0, 0); grub_free (tmp); } else - err = grub_video_set_mode ("text", 0, 0); + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0); if (err) { @@ -548,23 +466,34 @@ grub_linux_boot (void) } else { +#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) params->have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT; - params->video_width = 80; - params->video_height = 25; + params->video_mode = 0x3; +#else + params->have_vga = 0; + params->video_mode = 0; + params->video_width = 0; + params->video_height = 0; +#endif } /* Initialize these last, because terminal position could be affected by printfs above. */ +#ifndef GRUB_MACHINE_IEEE1275 if (params->have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT) +#endif { grub_term_output_t term; int found = 0; FOR_ACTIVE_TERM_OUTPUTS(term) if (grub_strcmp (term->name, "vga_text") == 0 - || grub_strcmp (term->name, "console") == 0) + || grub_strcmp (term->name, "console") == 0 + || grub_strcmp (term->name, "ofconsole") == 0) { grub_uint16_t pos = grub_term_getxy (term); params->video_cursor_x = pos >> 8; params->video_cursor_y = pos & 0xff; + params->video_width = grub_term_width (term); + params->video_height = grub_term_height (term); found = 1; break; } @@ -572,34 +501,59 @@ grub_linux_boot (void) { params->video_cursor_x = 0; params->video_cursor_y = 0; + params->video_width = 80; + params->video_height = 25; } } -#ifdef __x86_64__ - - grub_memcpy ((char *) prot_mode_mem + (prot_mode_pages << 12), - grub_linux_trampoline_start, - grub_linux_trampoline_end - grub_linux_trampoline_start); - - ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem - + (prot_mode_pages << 12))) - (params->code32_start, real_mode_mem); -#else - - /* Hardware interrupts are not safe any longer. */ - asm volatile ("cli" : : ); - - /* Load the IDT and the GDT for the bootstrap. */ - asm volatile ("lidt %0" : : "m" (idt_desc)); - asm volatile ("lgdt %0" : : "m" (gdt_desc)); - - /* Enter Linux. */ - asm volatile ("jmp *%2" : : "b" (0), "S" (real_mode_mem), "g" (params->code32_start)); - +#ifdef GRUB_MACHINE_IEEE1275 + { + params->ofw_signature = GRUB_LINUX_OFW_SIGNATURE; + params->ofw_num_items = 1; + params->ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn; + params->ofw_idt = 0; + } #endif - /* Never reach here. */ - return GRUB_ERR_NONE; +#ifdef GRUB_MACHINE_EFI + { + grub_efi_uintn_t efi_desc_size; + grub_efi_uint32_t efi_desc_version; + err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL, + &efi_desc_size, &efi_desc_version); + if (err) + return err; + + /* Note that no boot services are available from here. */ + + /* Pass EFI parameters. */ + if (grub_le_to_cpu16 (params->version) >= 0x0206) + { + params->v0206.efi_mem_desc_size = efi_desc_size; + params->v0206.efi_mem_desc_version = efi_desc_version; + params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf; + params->v0206.efi_mmap_size = efi_mmap_size; +#ifdef __x86_64__ + params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) efi_mmap_buf >> 32); +#endif + } + else if (grub_le_to_cpu16 (params->version) >= 0x0204) + { + params->v0204.efi_mem_desc_size = efi_desc_size; + params->v0204.efi_mem_desc_version = efi_desc_version; + params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf; + params->v0204.efi_mmap_size = efi_mmap_size; + } + } +#endif + + /* FIXME. */ + /* asm volatile ("lidt %0" : : "m" (idt_desc)); */ + state.ebp = state.edi = state.ebx = 0; + state.esi = real_mode_target; + state.esp = real_mode_target; + state.eip = params->code32_start; + return grub_relocator32_boot (relocator, state); } static grub_err_t @@ -685,7 +639,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), real_size = setup_sects << GRUB_DISK_SECTOR_BITS; prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; - if (! allocate_pages (prot_size)) + if (allocate_pages (prot_size)) goto fail; params = (struct linux_kernel_params *) real_mode_mem; @@ -708,7 +662,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), params->cl_magic = GRUB_LINUX_CL_MAGIC; params->cl_offset = 0x1000; - params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000; + params->cmd_line_ptr = real_mode_target + 0x1000; params->ramdisk_image = 0; params->ramdisk_size = 0; @@ -724,14 +678,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Ignored by Linux. */ params->video_page = 0; - /* Must be non-zero even in text mode, or Linux will think there's no VGA. */ - params->video_mode = 0x3; - /* Only used when `video_mode == 0x7', otherwise ignored. */ params->video_ega_bx = 0; params->font_size = 16; /* XXX */ +#ifdef GRUB_MACHINE_EFI + if (grub_le_to_cpu16 (params->version) >= 0x0206) + { + params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE; + params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table; +#ifdef __x86_64__ + params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32); +#endif + } + else if (grub_le_to_cpu16 (params->version) >= 0x0204) + { + params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204; + params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table; + } +#endif + /* The other parameters are filled when booting. */ grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); @@ -748,10 +715,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Video mode selection support. */ char *val = argv[i] + 4; unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL; - struct linux_vesafb_mode *linux_mode; + struct grub_vesa_mode_table_entry *linux_mode; grub_err_t err; char *buf; + grub_dl_load ("vbe"); + if (grub_strcmp (val, "normal") == 0) vid_mode = GRUB_LINUX_VID_MODE_NORMAL; else if (grub_strcmp (val, "ext") == 0) @@ -791,9 +760,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), break; default: /* Ignore invalid values. */ - if (vid_mode < GRUB_LINUX_VID_MODE_VESA_START || - vid_mode >= GRUB_LINUX_VID_MODE_VESA_START + - ARRAY_SIZE (linux_vesafb_modes)) + if (vid_mode < GRUB_VESA_MODE_TABLE_START || + vid_mode > GRUB_VESA_MODE_TABLE_END) { grub_env_set ("gfxpayload", "text"); grub_printf ("%s is deprecated. Mode %d isn't recognized. " @@ -807,15 +775,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), is built-in because `vga=' parameter was used. */ params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; - linux_mode - = &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START]; + linux_mode = &grub_vesa_mode_table[vid_mode + - GRUB_VESA_MODE_TABLE_START]; buf = grub_xasprintf ("%ux%ux%u,%ux%u", - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height, + linux_mode->width, linux_mode->height, linux_mode->depth, - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height); + linux_mode->width, linux_mode->height); if (! buf) goto fail; @@ -888,7 +854,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), } len = prot_size; - if (grub_file_read (file, (void *) GRUB_LINUX_BZIMAGE_ADDR, len) != len) + if (grub_file_read (file, prot_mode_mem, len) != len) grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); if (grub_errno == GRUB_ERR_NONE) @@ -920,6 +886,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_ssize_t size; grub_addr_t addr_min, addr_max; grub_addr_t addr; + grub_err_t err; struct linux_kernel_header *lh; if (argc == 0) @@ -934,6 +901,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } + grub_file_filter_disable_compression (); file = grub_file_open (argv[0]); if (! file) goto fail; @@ -967,12 +935,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_max -= 0x10000; /* Usually, the compression ratio is about 50%. */ - addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12) + addr_min = (grub_addr_t) prot_mode_target + ((prot_mode_pages * 3) << 12) + page_align (size); - if (addr_max > grub_os_area_addr + grub_os_area_size) - addr_max = grub_os_area_addr + grub_os_area_size; - /* Put the initrd as high as possible, 4KiB aligned. */ addr = (addr_max - size) & ~0xFFF; @@ -982,7 +947,16 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - initrd_mem = (void *) addr; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + addr_min, addr, size, 0x1000, + GRUB_RELOCATOR_PREFERENCE_HIGH); + if (err) + return err; + initrd_mem = get_virtual_current_address (ch); + initrd_mem_target = get_physical_target_address (ch); + } if (grub_file_read (file, initrd_mem, size) != size) { @@ -993,7 +967,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n", (unsigned) addr, (unsigned) size); - lh->ramdisk_image = addr; + lh->ramdisk_image = initrd_mem_target; lh->ramdisk_size = size; lh->root_dev = 0x0100; /* XXX */ diff --git a/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c similarity index 67% rename from loader/i386/multiboot_mbi.c rename to grub-core/loader/i386/multiboot_mbi.c index d984e4e4e..79f72ee0f 100644 --- a/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -16,13 +16,13 @@ * along with GRUB. If not, see . */ -#include #include #ifdef GRUB_MACHINE_PCBIOS #include +#include +#include #endif #include -#include #include #include #include @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,10 @@ static unsigned modcnt; static char *cmdline = NULL; static grub_uint32_t bootdev; static int bootdev_set; +static grub_size_t elf_sec_num, elf_sec_entsize; +static unsigned elf_sec_shstrndx; +static void *elf_sections; + grub_err_t grub_multiboot_load (grub_file_t file) @@ -103,25 +108,24 @@ grub_multiboot_load (grub_file_t file) int load_size = ((header->load_end_addr == 0) ? file->size - offset : header->load_end_addr - header->load_addr); grub_size_t code_size; + void *source; + grub_relocator_chunk_t ch; if (header->bss_end_addr) code_size = (header->bss_end_addr - header->load_addr); else code_size = load_size; - grub_multiboot_payload_dest = header->load_addr; - grub_multiboot_pure_size += code_size; - - /* Allocate a bit more to avoid relocations in most cases. */ - grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536; - grub_multiboot_payload_orig - = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi); - - if (! grub_multiboot_payload_orig) + err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, + &ch, header->load_addr, + code_size); + if (err) { + grub_dprintf ("multiboot_loader", "Error loading aout kludge\n"); grub_free (buffer); - return grub_errno; + return err; } + source = get_virtual_current_address (ch); if ((grub_file_seek (file, offset)) == (grub_off_t) -1) { @@ -129,7 +133,7 @@ grub_multiboot_load (grub_file_t file) return grub_errno; } - grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size); + grub_file_read (file, source, load_size); if (grub_errno) { grub_free (buffer); @@ -137,11 +141,10 @@ grub_multiboot_load (grub_file_t file) } if (header->bss_end_addr) - grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0, + grub_memset ((grub_uint32_t *) source + load_size, 0, header->bss_end_addr - header->load_addr - load_size); grub_multiboot_payload_eip = header->entry_addr; - } else { @@ -184,14 +187,24 @@ grub_multiboot_load (grub_file_t file) return err; } -grub_size_t +#if GRUB_MACHINE_HAS_VBE || GRUB_MACHINE_HAS_VGA_TEXT +#include +#endif + +static grub_size_t grub_multiboot_get_mbi_size (void) { return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) - + 256 * sizeof (struct multiboot_color); + + elf_sec_entsize * elf_sec_num + + 256 * sizeof (struct multiboot_color) +#if GRUB_MACHINE_HAS_VBE || GRUB_MACHINE_HAS_VGA_TEXT + + sizeof (struct grub_vbe_info_block) + + sizeof (struct grub_vbe_mode_info_block) +#endif + + ALIGN_UP (sizeof (struct multiboot_apm_info), 4); } /* Fill previously allocated Multiboot mmap. */ @@ -200,28 +213,30 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) { struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + 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) { mmap_entry->addr = addr; mmap_entry->len = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE - case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + case GRUB_MEMORY_ACPI: mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: mmap_entry->type = MULTIBOOT_MEMORY_NVS; break; -#endif + + case GRUB_MEMORY_BADRAM: + mmap_entry->type = MULTIBOOT_MEMORY_BADRAM; + break; default: mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; @@ -236,6 +251,90 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) grub_mmap_iterate (hook); } +#if GRUB_MACHINE_HAS_VBE || GRUB_MACHINE_HAS_VGA_TEXT + +static grub_err_t +fill_vbe_info (struct multiboot_info *mbi, grub_uint8_t *ptrorig, + grub_uint32_t ptrdest, int fill_generic) +{ + grub_uint32_t vbe_mode; + struct grub_vbe_mode_info_block *mode_info; +#if GRUB_MACHINE_HAS_VBE + grub_vbe_status_t status; + void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + + status = grub_vbe_bios_get_controller_info (scratch); + if (status != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_IO, "Can't get controller info."); + + mbi->vbe_control_info = ptrdest; + grub_memcpy (ptrorig, scratch, sizeof (struct grub_vbe_info_block)); + ptrorig += sizeof (struct grub_vbe_info_block); + ptrdest += sizeof (struct grub_vbe_info_block); +#else + mbi->vbe_control_info = 0; +#endif + +#if GRUB_MACHINE_HAS_VBE + status = grub_vbe_bios_get_mode (scratch); + vbe_mode = *(grub_uint32_t *) scratch; + if (status != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_IO, "can't get VBE mode"); +#else + vbe_mode = 3; +#endif + mbi->vbe_mode = vbe_mode; + + mode_info = (struct grub_vbe_mode_info_block *) ptrorig; + mbi->vbe_mode_info = ptrdest; + /* get_mode_info isn't available for mode 3. */ + if (vbe_mode == 3) + { + grub_memset (mode_info, 0, sizeof (struct grub_vbe_mode_info_block)); + mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT; + mode_info->x_resolution = 80; + mode_info->y_resolution = 25; + } + else + { +#if GRUB_MACHINE_HAS_VBE + status = grub_vbe_bios_get_mode_info (vbe_mode, scratch); + if (status != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_IO, "can't get mode info"); + grub_memcpy (mode_info, scratch, + sizeof (struct grub_vbe_mode_info_block)); +#endif + } + ptrorig += sizeof (struct grub_vbe_mode_info_block); + ptrdest += sizeof (struct grub_vbe_mode_info_block); + +#if GRUB_MACHINE_HAS_VBE + grub_vbe_bios_get_pm_interface (&mbi->vbe_interface_seg, + &mbi->vbe_interface_off, + &mbi->vbe_interface_len); +#endif + + mbi->flags |= MULTIBOOT_INFO_VBE_INFO; + + if (fill_generic && mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT) + { + mbi->framebuffer_addr = 0xb8000; + + mbi->framebuffer_pitch = 2 * mode_info->x_resolution; + mbi->framebuffer_width = mode_info->x_resolution; + mbi->framebuffer_height = mode_info->y_resolution; + + mbi->framebuffer_bpp = 16; + + mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; + + mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; + } + + return GRUB_ERR_NONE; +} +#endif + static grub_err_t retrieve_video_parameters (struct multiboot_info *mbi, grub_uint8_t *ptrorig, grub_uint32_t ptrdest) @@ -256,8 +355,13 @@ retrieve_video_parameters (struct multiboot_info *mbi, grub_video_get_palette (0, ARRAY_SIZE (palette), palette); driv_id = grub_video_get_driver_id (); +#if GRUB_MACHINE_HAS_VGA_TEXT + if (driv_id == GRUB_VIDEO_DRIVER_NONE) + return fill_vbe_info (mbi, ptrorig, ptrdest, 1); +#else if (driv_id == GRUB_VIDEO_DRIVER_NONE) return GRUB_ERR_NONE; +#endif err = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (err) @@ -305,24 +409,41 @@ retrieve_video_parameters (struct multiboot_info *mbi, mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; +#if GRUB_MACHINE_HAS_VBE + if (driv_id == GRUB_VIDEO_DRIVER_VBE) + return fill_vbe_info (mbi, ptrorig, ptrdest, 0); +#endif + return GRUB_ERR_NONE; } grub_err_t -grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, - grub_size_t bufsize) +grub_multiboot_make_mbi (grub_uint32_t *target) { - grub_uint8_t *ptrorig = (grub_uint8_t *) orig + buf_off; - grub_uint32_t ptrdest = dest + buf_off; struct multiboot_info *mbi; struct multiboot_mod_list *modlist; unsigned i; struct module *cur; grub_size_t mmap_size; - grub_err_t err; + grub_uint8_t *ptrorig; + grub_addr_t ptrdest; - if (bufsize < grub_multiboot_get_mbi_size ()) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small"); + grub_err_t err; + grub_size_t bufsize; + grub_relocator_chunk_t ch; + + bufsize = grub_multiboot_get_mbi_size (); + + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, + 0, 0xffffffff - bufsize, + bufsize, 4, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + ptrorig = get_virtual_current_address (ch); + ptrdest = (grub_addr_t) get_virtual_current_address (ch); + + *target = ptrdest; mbi = (struct multiboot_info *) ptrorig; ptrorig += sizeof (*mbi); @@ -341,6 +462,29 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4); ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4); +#ifdef GRUB_MACHINE_PCBIOS + { + struct grub_apm_info info; + if (grub_apm_get_info (&info)) + { + struct multiboot_apm_info *mbinfo = (void *) ptrorig; + + mbinfo->cseg = info.cseg; + mbinfo->offset = info.offset; + mbinfo->cseg_16 = info.cseg_16; + mbinfo->dseg = info.dseg; + mbinfo->flags = info.flags; + mbinfo->cseg_len = info.cseg_len; + mbinfo->dseg_len = info.dseg_len; + mbinfo->cseg_16_len = info.cseg_16_len; + mbinfo->version = info.version; + + ptrorig += ALIGN_UP (sizeof (struct multiboot_apm_info), 4); + ptrdest += ALIGN_UP (sizeof (struct multiboot_apm_info), 4); + } + } +#endif + if (modcnt) { mbi->flags |= MULTIBOOT_INFO_MODS; @@ -386,16 +530,43 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, mbi->flags |= MULTIBOOT_INFO_BOOTDEV; } + if (elf_sec_num) + { + mbi->u.elf_sec.addr = ptrdest; + grub_memcpy (ptrorig, elf_sections, elf_sec_entsize * elf_sec_num); + mbi->u.elf_sec.num = elf_sec_num; + mbi->u.elf_sec.size = elf_sec_entsize; + mbi->u.elf_sec.shndx = elf_sec_shstrndx; + + mbi->flags |= MULTIBOOT_INFO_ELF_SHDR; + } + err = retrieve_video_parameters (mbi, ptrorig, ptrdest); if (err) { grub_print_error (); grub_errno = GRUB_ERR_NONE; } +#if GRUB_MACHINE_HAS_VBE + ptrorig += sizeof (struct grub_vbe_info_block); + ptrdest += sizeof (struct grub_vbe_info_block); + ptrorig += sizeof (struct grub_vbe_mode_info_block); + ptrdest += sizeof (struct grub_vbe_mode_info_block); +#endif return GRUB_ERR_NONE; } +void +grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, + unsigned shndx, void *data) +{ + elf_sec_num = num; + elf_sec_shstrndx = shndx; + elf_sec_entsize = entsize; + elf_sections = data; +} + void grub_multiboot_free_mbi (void) { @@ -416,6 +587,11 @@ grub_multiboot_free_mbi (void) } modules = NULL; modules_last = NULL; + + grub_free (elf_sections); + elf_sections = NULL; + elf_sec_entsize = 0; + elf_sec_num = 0; } grub_err_t diff --git a/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c similarity index 97% rename from loader/i386/pc/chainloader.c rename to grub-core/loader/i386/pc/chainloader.c index 502031d0e..fd99c81d5 100644 --- a/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -20,19 +20,20 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -69,6 +70,7 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) grub_dl_ref (my_mod); + grub_file_filter_disable_compression (); file = grub_file_open (filename); if (! file) goto fail; diff --git a/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c similarity index 69% rename from loader/i386/pc/linux.c rename to grub-core/loader/i386/pc/linux.c index 04bc66661..90de70f66 100644 --- a/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -25,14 +25,15 @@ #include #include #include -#include -#include +#include #include #include #include #include #include +#include #include +#include #define GRUB_LINUX_CL_OFFSET 0x9000 #define GRUB_LINUX_CL_END_OFFSET 0x90FF @@ -41,22 +42,37 @@ static grub_dl_t my_mod; static grub_size_t linux_mem_size; static int loaded; +static struct grub_relocator *relocator = NULL; +static grub_addr_t grub_linux_real_target; +static char *grub_linux_real_chunk; +static grub_size_t grub_linux16_prot_size; + +static grub_err_t +grub_linux16_boot (void) +{ + grub_uint16_t segment; + struct grub_relocator16_state state; + + segment = grub_linux_real_target >> 4; + state.gs = state.fs = state.es = state.ds = state.ss = segment; + state.sp = GRUB_LINUX_SETUP_STACK; + state.cs = segment + 0x20; + state.ip = 0; + + grub_video_set_mode ("text", 0, 0); + + grub_stop_floppy (); + + return grub_relocator16_boot (relocator, state); +} static grub_err_t grub_linux_unload (void) { grub_dl_unref (my_mod); loaded = 0; - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_linux16_boot (void) -{ - grub_video_set_mode ("text", 0, 0); - grub_linux16_real_boot (); - - /* Not reached. */ + grub_relocator_unload (relocator); + relocator = NULL; return GRUB_ERR_NONE; } @@ -67,10 +83,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_file_t file = 0; struct linux_kernel_header lh; grub_uint8_t setup_sects; - grub_size_t real_size, prot_size; + grub_size_t real_size; grub_ssize_t len; int i; char *dest; + char *grub_linux_prot_chunk; + int grub_linux_is_bzimage; + grub_addr_t grub_linux_prot_target; + grub_err_t err; grub_dl_ref (my_mod); @@ -84,14 +104,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (! file) goto fail; - if ((grub_size_t) grub_file_size (file) > grub_os_area_size) - { - grub_error (GRUB_ERR_OUT_OF_RANGE, "too big kernel (0x%x > 0x%x)", - (grub_size_t) grub_file_size (file), - grub_os_area_size); - goto fail; - } - if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); @@ -121,12 +133,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), lh.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE; /* Put the real mode part at as a high location as possible. */ - grub_linux_real_addr - = (char *) UINT_TO_PTR (grub_mmap_get_lower () - - GRUB_LINUX_SETUP_MOVE_SIZE); + grub_linux_real_target = grub_mmap_get_lower () + - GRUB_LINUX_SETUP_MOVE_SIZE; /* But it must not exceed the traditional area. */ - if (grub_linux_real_addr > (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR) - grub_linux_real_addr = (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR; + if (grub_linux_real_target > GRUB_LINUX_OLD_REAL_MODE_ADDR) + grub_linux_real_target = GRUB_LINUX_OLD_REAL_MODE_ADDR; if (grub_le_to_cpu16 (lh.version) >= 0x0201) { @@ -135,7 +146,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), } if (grub_le_to_cpu16 (lh.version) >= 0x0202) - lh.cmd_line_ptr = grub_linux_real_addr + GRUB_LINUX_CL_OFFSET; + lh.cmd_line_ptr = grub_linux_real_target + GRUB_LINUX_CL_OFFSET; else { lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC); @@ -151,7 +162,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS; - grub_linux_real_addr = (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR; + grub_linux_real_target = GRUB_LINUX_OLD_REAL_MODE_ADDR; } /* If SETUP_SECTS is not set, set it to the default (4). */ @@ -159,32 +170,36 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS; real_size = setup_sects << GRUB_DISK_SECTOR_BITS; - prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; - - grub_linux_tmp_addr = (char *) GRUB_LINUX_BZIMAGE_ADDR + prot_size; + grub_linux16_prot_size = grub_file_size (file) + - real_size - GRUB_DISK_SECTOR_SIZE; if (! grub_linux_is_bzimage - && ((char *) GRUB_LINUX_ZIMAGE_ADDR + prot_size > grub_linux_real_addr)) + && GRUB_LINUX_ZIMAGE_ADDR + grub_linux16_prot_size + > grub_linux_real_target) { grub_error (GRUB_ERR_BAD_OS, "too big zImage (0x%x > 0x%x), use bzImage instead", - (char *) GRUB_LINUX_ZIMAGE_ADDR + prot_size, - (grub_size_t) grub_linux_real_addr); + (char *) GRUB_LINUX_ZIMAGE_ADDR + grub_linux16_prot_size, + (grub_size_t) grub_linux_real_target); goto fail; } - if (grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE - > (char *) UINT_TO_PTR (grub_mmap_get_lower ())) + if (grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE + > grub_mmap_get_lower ()) { grub_error (GRUB_ERR_OUT_OF_RANGE, "too small lower memory (0x%x > 0x%x)", - grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE, + grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE, (int) grub_mmap_get_lower ()); goto fail; } - grub_dprintf ("linux", "Linux-%s, setup=0x%x, size=0x%x\n", - grub_linux_is_bzimage ? "bzImage" : "zImage", - real_size, prot_size); + grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", + grub_linux_is_bzimage ? "bzImage" : "zImage", real_size, + grub_linux16_prot_size); + + relocator = grub_relocator_new (); + if (!relocator) + goto fail; for (i = 1; i < argc; i++) if (grub_memcmp (argv[i], "vga=", 4) == 0) @@ -242,11 +257,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), } } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + grub_linux_real_target, + GRUB_LINUX_SETUP_MOVE_SIZE); + if (err) + return err; + grub_linux_real_chunk = get_virtual_current_address (ch); + } + /* Put the real mode code at the temporary address. */ - grub_memmove (grub_linux_tmp_addr, &lh, sizeof (lh)); + grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh)); len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh); - if (grub_file_read (file, grub_linux_tmp_addr + sizeof (lh), len) != len) + if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len) { grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); goto fail; @@ -255,21 +280,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) || grub_le_to_cpu16 (lh.version) < 0x0200) /* Clear the heap space. */ - grub_memset (grub_linux_tmp_addr + grub_memset (grub_linux_real_chunk + ((setup_sects + 1) << GRUB_DISK_SECTOR_BITS), 0, ((GRUB_LINUX_MAX_SETUP_SECTS - setup_sects - 1) << GRUB_DISK_SECTOR_BITS)); /* Specify the boot file. */ - dest = grub_stpcpy (grub_linux_tmp_addr + GRUB_LINUX_CL_OFFSET, + dest = grub_stpcpy (grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET, "BOOT_IMAGE="); dest = grub_stpcpy (dest, argv[0]); /* Copy kernel parameters. */ for (i = 1; i < argc - && dest + grub_strlen (argv[i]) + 1 < (grub_linux_tmp_addr + && dest + grub_strlen (argv[i]) + 1 < (grub_linux_real_chunk + GRUB_LINUX_CL_END_OFFSET); i++) { @@ -277,14 +302,28 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), dest = grub_stpcpy (dest, argv[i]); } - len = prot_size; - if (grub_file_read (file, (void *) GRUB_LINUX_BZIMAGE_ADDR, len) != len) + if (grub_linux_is_bzimage) + grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR; + else + grub_linux_prot_target = GRUB_LINUX_ZIMAGE_ADDR; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + grub_linux_prot_target, + grub_linux16_prot_size); + if (err) + return err; + grub_linux_prot_chunk = get_virtual_current_address (ch); + } + + len = grub_linux16_prot_size; + if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size) + != (grub_ssize_t) grub_linux16_prot_size) grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); if (grub_errno == GRUB_ERR_NONE) { - grub_linux_prot_size = prot_size; - grub_loader_set (grub_linux16_boot, grub_linux_unload, 1); + grub_loader_set (grub_linux16_boot, grub_linux_unload, 0); loaded = 1; } @@ -297,6 +336,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), { grub_dl_unref (my_mod); loaded = 0; + grub_relocator_unload (relocator); } return grub_errno; @@ -308,8 +348,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file = 0; grub_ssize_t size; - grub_addr_t addr_max, addr_min, addr; + grub_addr_t addr_max, addr_min; struct linux_kernel_header *lh; + grub_uint8_t *initrd_chunk; + grub_addr_t initrd_addr; + grub_err_t err; if (argc == 0) { @@ -323,7 +366,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - lh = (struct linux_kernel_header *) grub_linux_tmp_addr; + lh = (struct linux_kernel_header *) grub_linux_real_chunk; if (!(lh->header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) && grub_le_to_cpu16 (lh->version) >= 0x0200)) @@ -355,33 +398,34 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), worse than that of Linux 2.3.xx, so avoid the last 64kb. */ addr_max -= 0x10000; - if (addr_max > grub_os_area_addr + grub_os_area_size) - addr_max = grub_os_area_addr + grub_os_area_size; - - addr_min = (grub_addr_t) grub_linux_tmp_addr + GRUB_LINUX_CL_END_OFFSET; + addr_min = GRUB_LINUX_BZIMAGE_ADDR + grub_linux16_prot_size; + grub_file_filter_disable_compression (); file = grub_file_open (argv[0]); if (!file) goto fail; size = grub_file_size (file); - /* Put the initrd as high as possible, 4KiB aligned. */ - addr = (addr_max - size) & ~0xFFF; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, + addr_min, addr_max - size, + size, 0x1000, + GRUB_RELOCATOR_PREFERENCE_HIGH); + if (err) + return err; + initrd_chunk = get_virtual_current_address (ch); + initrd_addr = get_physical_target_address (ch); + } - if (addr < addr_min) - { - grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big"); - goto fail; - } - - if (grub_file_read (file, (void *) addr, size) != size) + if (grub_file_read (file, initrd_chunk, size) != size) { grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); goto fail; } - lh->ramdisk_image = addr; + lh->ramdisk_image = initrd_addr; lh->ramdisk_size = size; fail: diff --git a/grub-core/loader/i386/pc/ntldr.c b/grub-core/loader/i386/pc/ntldr.c new file mode 100644 index 000000000..0c33a0680 --- /dev/null +++ b/grub-core/loader/i386/pc/ntldr.c @@ -0,0 +1,157 @@ +/* chainloader.c - boot another boot loader */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2007,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 +#include +#include +#include +#include +#include +#include + +static grub_dl_t my_mod; +static struct grub_relocator *rel; +static grub_uint32_t edx = 0xffffffff; + +#define GRUB_NTLDR_SEGMENT 0x2000 + +static grub_err_t +grub_ntldr_boot (void) +{ + struct grub_relocator16_state state = { + .cs = GRUB_NTLDR_SEGMENT, + .ip = 0, + .ds = 0, + .es = 0, + .fs = 0, + .gs = 0, + .ss = 0, + .sp = 0x7c00, + .edx = edx + }; + grub_video_set_mode ("text", 0, 0); + + return grub_relocator16_boot (rel, state); +} + +static grub_err_t +grub_ntldr_unload (void) +{ + grub_relocator_unload (rel); + rel = NULL; + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_err_t err; + void *bs, *ntldr; + grub_size_t ntldrsize; + grub_device_t dev; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + + grub_dl_ref (my_mod); + + rel = grub_relocator_new (); + if (!rel) + goto fail; + + file = grub_file_open (argv[0]); + if (! file) + goto fail; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00, + GRUB_DISK_SECTOR_SIZE); + if (err) + goto fail; + bs = get_virtual_current_address (ch); + } + + edx = grub_get_root_biosnumber (); + dev = grub_device_open (0); + + if (dev && dev->disk) + { + err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs); + if (err) + { + grub_device_close (dev); + goto fail; + } + } + + if (dev) + grub_device_close (dev); + + ntldrsize = grub_file_size (file); + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, + ntldrsize); + if (err) + goto fail; + ntldr = get_virtual_current_address (ch); + } + + if (grub_file_read (file, ntldr, ntldrsize) + != (grub_ssize_t) ntldrsize) + goto fail; + + grub_loader_set (grub_ntldr_boot, grub_ntldr_unload, 1); + return GRUB_ERR_NONE; + + fail: + + if (file) + grub_file_close (file); + + grub_ntldr_unload (); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(ntldr) +{ + cmd = grub_register_command ("ntldr", grub_cmd_ntldr, + 0, N_("Load NTLDR or BootMGR.")); + my_mod = mod; +} + +GRUB_MOD_FINI(ntldr) +{ + grub_unregister_command (cmd); +} diff --git a/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c similarity index 89% rename from loader/i386/xnu.c rename to grub-core/loader/i386/xnu.c index 5f18d744b..a9435eff3 100644 --- a/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -41,7 +40,6 @@ #define DEFAULT_VIDEO_MODE "auto" char grub_xnu_cmdline[1024]; -grub_uint32_t grub_xnu_heap_will_be_at; grub_uint32_t grub_xnu_entry_point, grub_xnu_arg1, grub_xnu_stack; /* Aliases set for some tables. */ @@ -536,7 +534,7 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)), if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - file = grub_gzfile_open (args[0], 1); + file = grub_file_open (args[0]); if (! file) return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't load device-propertie dump"); @@ -837,11 +835,11 @@ grub_xnu_boot_resume (void) struct grub_relocator32_state state; state.esp = grub_xnu_stack; + state.ebp = grub_xnu_stack; state.eip = grub_xnu_entry_point; state.eax = grub_xnu_arg1; - return grub_relocator32_boot (grub_xnu_heap_start, grub_xnu_heap_will_be_at, - state); + return grub_relocator32_boot (grub_xnu_relocator, state); } /* Setup video for xnu. */ @@ -883,6 +881,18 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); if (grub_xnu_bitmap) + { + if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH) + err = grub_video_bitmap_create_scaled (&bitmap, + mode_info.width, + mode_info.height, + grub_xnu_bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + else + bitmap = grub_xnu_bitmap; + } + + if (bitmap) { if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH) err = grub_video_bitmap_create_scaled (&bitmap, @@ -940,18 +950,18 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) grub_err_t grub_xnu_boot (void) { - struct grub_xnu_boot_params *bootparams_relloc; - grub_off_t bootparams_relloc_off; - grub_off_t mmap_relloc_off; + struct grub_xnu_boot_params *bootparams; + grub_addr_t bootparams_target; grub_err_t err; grub_efi_uintn_t memory_map_size = 0; grub_efi_memory_descriptor_t *memory_map; + grub_addr_t memory_map_target; grub_efi_uintn_t map_key = 0; grub_efi_uintn_t descriptor_size = 0; grub_efi_uint32_t descriptor_version = 0; grub_uint64_t firstruntimepage, lastruntimepage; grub_uint64_t curruntimepage; - void *devtree; + grub_addr_t devtree_target; grub_size_t devtreelen; int i; struct grub_relocator32_state state; @@ -995,26 +1005,25 @@ grub_xnu_boot (void) } /* Relocate the boot parameters to heap. */ - bootparams_relloc = grub_xnu_heap_malloc (sizeof (*bootparams_relloc)); - if (! bootparams_relloc) - return grub_errno; - bootparams_relloc_off = (grub_uint8_t *) bootparams_relloc - - (grub_uint8_t *) grub_xnu_heap_start; + err = grub_xnu_heap_malloc (sizeof (*bootparams), + (void **) &bootparams, &bootparams_target); + if (err) + return err; /* Set video. */ - err = grub_xnu_set_video (bootparams_relloc); + err = grub_xnu_set_video (bootparams); if (err != GRUB_ERR_NONE) { grub_print_error (); grub_errno = GRUB_ERR_NONE; grub_printf ("Booting in blind mode\n"); - bootparams_relloc->lfb_mode = 0; - bootparams_relloc->lfb_width = 0; - bootparams_relloc->lfb_height = 0; - bootparams_relloc->lfb_depth = 0; - bootparams_relloc->lfb_line_len = 0; - bootparams_relloc->lfb_base = 0; + bootparams->lfb_mode = 0; + bootparams->lfb_width = 0; + bootparams->lfb_height = 0; + bootparams->lfb_depth = 0; + bootparams->lfb_line_len = 0; + bootparams->lfb_base = 0; } if (grub_autoefi_get_memory_map (&memory_map_size, memory_map, @@ -1025,38 +1034,30 @@ grub_xnu_boot (void) /* We will do few allocations later. Reserve some space for possible memory map growth. */ memory_map_size += 20 * descriptor_size; - memory_map = grub_xnu_heap_malloc (memory_map_size); - if (! memory_map) - return grub_errno; - mmap_relloc_off = (grub_uint8_t *) memory_map - - (grub_uint8_t *) grub_xnu_heap_start; - - err = grub_xnu_writetree_toheap (&devtree, &devtreelen); + err = grub_xnu_heap_malloc (memory_map_size, + (void **) &memory_map, &memory_map_target); if (err) return err; - bootparams_relloc = (struct grub_xnu_boot_params *) - (bootparams_relloc_off + (grub_uint8_t *) grub_xnu_heap_start); - grub_memcpy (bootparams_relloc->cmdline, grub_xnu_cmdline, - sizeof (bootparams_relloc->cmdline)); + err = grub_xnu_writetree_toheap (&devtree_target, &devtreelen); + if (err) + return err; - bootparams_relloc->devtree - = ((grub_uint8_t *) devtree - (grub_uint8_t *) grub_xnu_heap_start) - + grub_xnu_heap_will_be_at; - bootparams_relloc->devtreelen = devtreelen; + grub_memcpy (bootparams->cmdline, grub_xnu_cmdline, + sizeof (bootparams->cmdline)); - memory_map = (grub_efi_memory_descriptor_t *) - ((grub_uint8_t *) grub_xnu_heap_start + mmap_relloc_off); + bootparams->devtree = devtree_target; + bootparams->devtreelen = devtreelen; - if (grub_autoefi_get_memory_map (&memory_map_size, memory_map, - &map_key, &descriptor_size, - &descriptor_version) <= 0) - return grub_errno; + err = grub_autoefi_finish_boot_services (&memory_map_size, memory_map, + &map_key, &descriptor_size, + &descriptor_version); + if (err) + return err; - bootparams_relloc->efi_system_table - = PTR_TO_UINT32 (grub_autoefi_system_table); + bootparams->efi_system_table = PTR_TO_UINT32 (grub_autoefi_system_table); - firstruntimepage = (((grub_addr_t) grub_xnu_heap_will_be_at + firstruntimepage = (((grub_addr_t) grub_xnu_heap_target_start + grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1) / GRUB_XNU_PAGESIZE) + 20; curruntimepage = firstruntimepage; @@ -1077,7 +1078,7 @@ grub_xnu_boot (void) <= PTR_TO_UINT64 (grub_autoefi_system_table) && curdesc->physical_start + (curdesc->num_pages << 12) > PTR_TO_UINT64 (grub_autoefi_system_table)) - bootparams_relloc->efi_system_table + bootparams->efi_system_table = PTR_TO_UINT64 (grub_autoefi_system_table) - curdesc->physical_start + curdesc->virtual_start; if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit) @@ -1087,28 +1088,25 @@ grub_xnu_boot (void) lastruntimepage = curruntimepage; - bootparams_relloc->efi_mmap = grub_xnu_heap_will_be_at + mmap_relloc_off; - bootparams_relloc->efi_mmap_size = memory_map_size; - bootparams_relloc->efi_mem_desc_size = descriptor_size; - bootparams_relloc->efi_mem_desc_version = descriptor_version; + bootparams->efi_mmap = memory_map_target; + bootparams->efi_mmap_size = memory_map_size; + bootparams->efi_mem_desc_size = descriptor_size; + bootparams->efi_mem_desc_version = descriptor_version; - bootparams_relloc->heap_start = grub_xnu_heap_will_be_at; - bootparams_relloc->heap_size = grub_xnu_heap_size; - bootparams_relloc->efi_runtime_first_page = firstruntimepage; + bootparams->heap_start = grub_xnu_heap_target_start; + bootparams->heap_size = grub_xnu_heap_size; + bootparams->efi_runtime_first_page = firstruntimepage; - bootparams_relloc->efi_runtime_npages = lastruntimepage - firstruntimepage; - bootparams_relloc->efi_uintnbits = SIZEOF_OF_UINTN * 8; + bootparams->efi_runtime_npages = lastruntimepage - firstruntimepage; + bootparams->efi_uintnbits = SIZEOF_OF_UINTN * 8; - bootparams_relloc->verminor = GRUB_XNU_BOOTARGS_VERMINOR; - bootparams_relloc->vermajor = GRUB_XNU_BOOTARGS_VERMAJOR; + bootparams->verminor = GRUB_XNU_BOOTARGS_VERMINOR; + bootparams->vermajor = GRUB_XNU_BOOTARGS_VERMAJOR; /* Parameters for asm helper. */ - grub_xnu_stack = bootparams_relloc->heap_start - + bootparams_relloc->heap_size + GRUB_XNU_PAGESIZE; - grub_xnu_arg1 = bootparams_relloc_off + grub_xnu_heap_will_be_at; - - if (! grub_autoefi_exit_boot_services (map_key)) - return grub_error (GRUB_ERR_IO, "can't exit boot services"); + grub_xnu_stack = bootparams->heap_start + + bootparams->heap_size + GRUB_XNU_PAGESIZE; + grub_xnu_arg1 = bootparams_target; grub_autoefi_set_virtual_address_map (memory_map_size, descriptor_size, descriptor_version,memory_map); @@ -1116,8 +1114,8 @@ grub_xnu_boot (void) state.eip = grub_xnu_entry_point; state.eax = grub_xnu_arg1; state.esp = grub_xnu_stack; - return grub_relocator32_boot (grub_xnu_heap_start, grub_xnu_heap_will_be_at, - state); + state.ebp = grub_xnu_stack; + return grub_relocator32_boot (grub_xnu_relocator, state); } static grub_command_t cmd_devprop_load; diff --git a/loader/macho.c b/grub-core/loader/macho.c similarity index 98% rename from loader/macho.c rename to grub-core/loader/macho.c index 199d6f111..ecf0d8c53 100644 --- a/loader/macho.c +++ b/grub-core/loader/macho.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -149,7 +148,7 @@ grub_macho_open (const char *name) grub_file_t file; grub_macho_t macho; - file = grub_gzfile_open (name, 1); + file = grub_file_open (name); if (! file) return 0; diff --git a/loader/macho32.c b/grub-core/loader/macho32.c similarity index 100% rename from loader/macho32.c rename to grub-core/loader/macho32.c diff --git a/loader/macho64.c b/grub-core/loader/macho64.c similarity index 100% rename from loader/macho64.c rename to grub-core/loader/macho64.c diff --git a/loader/machoXX.c b/grub-core/loader/machoXX.c similarity index 100% rename from loader/machoXX.c rename to grub-core/loader/machoXX.c diff --git a/loader/mips/linux.c b/grub-core/loader/mips/linux.c similarity index 81% rename from loader/mips/linux.c rename to grub-core/loader/mips/linux.c index 64497f466..6ae2a9321 100644 --- a/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -23,18 +23,22 @@ #include #include #include -#include #include #include -#include +#include #include /* For frequencies. */ #include #include -#define ELF32_LOADMASK (0x00000000UL) -#define ELF64_LOADMASK (0x0000000000000000ULL) +#ifdef GRUB_MACHINE_MIPS_YEELOONG +/* This can be detected on runtime from PMON, but: + a) it wouldn't work when GRUB is the firmware + and + b) for now we only support Yeeloong anyway. */ +#define LOONGSON_MACHTYPE "machtype=lemote-yeeloong-2f-8.9inches" +#endif static grub_dl_t my_mod; @@ -42,6 +46,7 @@ static int loaded; static grub_size_t linux_size; +static struct grub_relocator *relocator; static grub_uint8_t *playground; static grub_addr_t target_addr, entry_addr; static int linux_argc; @@ -60,15 +65,7 @@ grub_linux_boot (void) state.gpr[5] = target_addr + argv_off; state.gpr[6] = target_addr + envp_off; state.jumpreg = 1; - grub_relocator32_boot (playground, target_addr, state); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_linux_release_mem (void) -{ - grub_relocator32_free (playground); + grub_relocator32_boot (relocator, state); return GRUB_ERR_NONE; } @@ -76,14 +73,12 @@ grub_linux_release_mem (void) static grub_err_t grub_linux_unload (void) { - grub_err_t err; - - err = grub_linux_release_mem (); + grub_relocator_unload (relocator); grub_dl_unref (my_mod); loaded = 0; - return err; + return GRUB_ERR_NONE; } static grub_err_t @@ -91,11 +86,12 @@ grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) { Elf32_Addr base; int extraoff; + grub_err_t err; /* Linux's entry point incorrectly contains a virtual address. */ - entry_addr = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK; + entry_addr = elf->ehdr.ehdr32.e_entry; - linux_size = grub_elf32_size (elf, &base); + linux_size = grub_elf32_size (elf, &base, 0); if (linux_size == 0) return grub_errno; target_addr = base; @@ -105,10 +101,20 @@ grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) extraoff = linux_size; linux_size += extra_size; - playground = grub_relocator32_alloc (linux_size); - if (!playground) + relocator = grub_relocator_new (); + if (!relocator) return grub_errno; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + target_addr & 0x1fffffff, + linux_size); + if (err) + return err; + playground = get_virtual_current_address (ch); + } + *extra_mem = playground + extraoff; /* Now load the segments into the area we claimed. */ @@ -135,11 +141,12 @@ grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) { Elf64_Addr base; int extraoff; + grub_err_t err; /* Linux's entry point incorrectly contains a virtual address. */ - entry_addr = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK; + entry_addr = elf->ehdr.ehdr64.e_entry; - linux_size = grub_elf64_size (elf, &base); + linux_size = grub_elf64_size (elf, &base, 0); if (linux_size == 0) return grub_errno; target_addr = base; @@ -149,10 +156,20 @@ grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) extraoff = linux_size; linux_size += extra_size; - playground = grub_relocator32_alloc (linux_size); - if (!playground) + relocator = grub_relocator_new (); + if (!relocator) return grub_errno; + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + target_addr & 0x1fffffff, + linux_size); + if (err) + return err; + playground = get_virtual_current_address (ch); + } + *extra_mem = playground + extraoff; /* Now load the segments into the area we claimed. */ @@ -205,6 +222,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* For arguments. */ linux_argc = argc; +#ifdef LOONGSON_MACHTYPE + linux_argc++; +#endif /* Main arguments. */ size = (linux_argc) * sizeof (grub_uint32_t); /* Initrd address and size. */ @@ -217,7 +237,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Normal arguments. */ for (i = 1; i < argc; i++) size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); - +#ifdef LOONGSON_MACHTYPE + size += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4); +#endif + /* rd arguments. */ size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); @@ -254,6 +277,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_argv++; linux_args += ALIGN_UP (sizeof ("a0"), 4); +#ifdef LOONGSON_MACHTYPE + /* In Loongson platform, it is the responsibility of the bootloader/firmware + to supply the OS kernel with machine type information. */ + grub_memcpy (linux_args, LOONGSON_MACHTYPE, sizeof (LOONGSON_MACHTYPE)); + *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground + + target_addr; + linux_argv++; + linux_args += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4); +#endif + for (i = 1; i < argc; i++) { grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); @@ -322,7 +355,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file = 0; grub_ssize_t size; - grub_size_t overhead; + void *initrd_src; + grub_addr_t initrd_dest; + grub_err_t err; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified"); @@ -333,25 +368,32 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), if (initrd_loaded) return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd can be loaded."); + grub_file_filter_disable_compression (); file = grub_file_open (argv[0]); if (! file) return grub_errno; size = grub_file_size (file); - overhead = ALIGN_UP (target_addr + linux_size + 0x10000, 0x10000) - - (target_addr + linux_size); + { + grub_relocator_chunk_t ch; - playground = grub_relocator32_realloc (playground, - linux_size + overhead + size); + err = grub_relocator_alloc_chunk_align (relocator, &ch, + target_addr + linux_size + 0x10000, + (0xffffffff - size) + 1, + size, 0x10000, + GRUB_RELOCATOR_PREFERENCE_NONE); - if (!playground) - { - grub_file_close (file); - return grub_errno; - } + if (err) + { + grub_file_close (file); + return err; + } + initrd_src = get_virtual_current_address (ch); + initrd_dest = get_physical_target_address (ch) | 0x80000000; + } - if (grub_file_read (file, playground + linux_size + overhead, size) != size) + if (grub_file_read (file, initrd_src, size) != size) { grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); grub_file_close (file); @@ -361,7 +403,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_snprintf ((char *) playground + rd_addr_arg_off, sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx", - (unsigned long long) target_addr + linux_size + overhead); + (unsigned long long) initrd_dest); ((grub_uint32_t *) (playground + argv_off))[linux_argc] = target_addr + rd_addr_arg_off; linux_argc++; diff --git a/loader/multiboot.c b/grub-core/loader/multiboot.c similarity index 79% rename from loader/multiboot.c rename to grub-core/loader/multiboot.c index 77a732838..4bfc2c191 100644 --- a/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -20,16 +20,14 @@ /* * FIXME: The following features from the Multiboot specification still * need to be implemented: - * - VBE support - * - symbol table * - drives table * - ROM configuration table - * - APM table + * - SMBIOS tables + * - Networking information */ #include #include -#include #include #include #include @@ -39,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -50,18 +47,14 @@ #include #endif +struct grub_relocator *grub_multiboot_relocator = NULL; +grub_uint32_t grub_multiboot_payload_eip; #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) #define DEFAULT_VIDEO_MODE "text" #else #define DEFAULT_VIDEO_MODE "auto" #endif -grub_size_t grub_multiboot_alloc_mbi; - -char *grub_multiboot_payload_orig; -grub_addr_t grub_multiboot_payload_dest; -grub_size_t grub_multiboot_pure_size; -grub_uint32_t grub_multiboot_payload_eip; static int accepts_video; static int accepts_ega_text; static int console_required; @@ -78,7 +71,7 @@ grub_get_multiboot_mmap_count (void) auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { count++; return 0; @@ -119,45 +112,23 @@ grub_multiboot_set_video_mode (void) static grub_err_t grub_multiboot_boot (void) { - grub_size_t mbi_size; grub_err_t err; struct grub_relocator32_state state = MULTIBOOT_INITIAL_STATE; state.MULTIBOOT_ENTRY_REGISTER = grub_multiboot_payload_eip; - mbi_size = grub_multiboot_get_mbi_size (); - if (grub_multiboot_alloc_mbi < mbi_size) - { - grub_multiboot_payload_orig - = grub_relocator32_realloc (grub_multiboot_payload_orig, - grub_multiboot_pure_size + mbi_size); - if (!grub_multiboot_payload_orig) - return grub_errno; - grub_multiboot_alloc_mbi = mbi_size; - } + err = grub_multiboot_make_mbi (&state.MULTIBOOT_MBI_REGISTER); -#ifdef GRUB_USE_MULTIBOOT2 - state.MULTIBOOT_MBI_REGISTER = ALIGN_UP (grub_multiboot_payload_dest - + grub_multiboot_pure_size, - MULTIBOOT_TAG_ALIGN); -#else - state.MULTIBOOT_MBI_REGISTER = grub_multiboot_payload_dest - + grub_multiboot_pure_size; -#endif - err = grub_multiboot_make_mbi (grub_multiboot_payload_orig, - grub_multiboot_payload_dest, - grub_multiboot_pure_size, mbi_size); if (err) return err; #ifdef GRUB_MACHINE_EFI - if (! grub_efi_finish_boot_services ()) - grub_fatal ("cannot exit boot services"); + err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL); + if (err) + return err; #endif - grub_relocator32_boot (grub_multiboot_payload_orig, - grub_multiboot_payload_dest, - state); + grub_relocator32_boot (grub_multiboot_relocator, state); /* Not reached. */ return GRUB_ERR_NONE; @@ -168,11 +139,9 @@ grub_multiboot_unload (void) { grub_multiboot_free_mbi (); - grub_relocator32_free (grub_multiboot_payload_orig); + grub_relocator_unload (grub_multiboot_relocator); + grub_multiboot_relocator = NULL; - grub_multiboot_alloc_mbi = 0; - - grub_multiboot_payload_orig = NULL; grub_dl_unref (my_mod); return GRUB_ERR_NONE; @@ -253,7 +222,7 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); - file = grub_gzfile_open (argv[0], 1); + file = grub_file_open (argv[0]); if (! file) return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file"); @@ -262,8 +231,11 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)), /* Skip filename. */ grub_multiboot_init_mbi (argc - 1, argv + 1); - grub_relocator32_free (grub_multiboot_payload_orig); - grub_multiboot_payload_orig = NULL; + grub_relocator_unload (grub_multiboot_relocator); + grub_multiboot_relocator = grub_relocator_new (); + + if (!grub_multiboot_relocator) + goto fail; err = grub_multiboot_load (file); if (err) @@ -279,8 +251,8 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)), if (grub_errno != GRUB_ERR_NONE) { - grub_relocator32_free (grub_multiboot_payload_orig); - grub_multiboot_free_mbi (); + grub_relocator_unload (grub_multiboot_relocator); + grub_multiboot_relocator = NULL; grub_dl_unref (my_mod); } @@ -293,30 +265,52 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file = 0; grub_ssize_t size; - char *module = 0; + void *module = NULL; + grub_addr_t target; grub_err_t err; + int nounzip = 0; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); - if (!grub_multiboot_payload_orig) + if (grub_strcmp (argv[0], "--nounzip") == 0) + { + argv++; + argc--; + nounzip = 1; + } + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); + + if (!grub_multiboot_relocator) return grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the multiboot kernel first"); - file = grub_gzfile_open (argv[0], 1); + if (nounzip) + grub_file_filter_disable_compression (); + + file = grub_file_open (argv[0]); if (! file) return grub_errno; size = grub_file_size (file); - module = grub_memalign (MULTIBOOT_MOD_ALIGN, size); - if (! module) - { - grub_file_close (file); - return grub_errno; - } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, + 0, (0xffffffff - size) + 1, + size, MULTIBOOT_MOD_ALIGN, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + { + grub_file_close (file); + return err; + } + module = get_virtual_current_address (ch); + target = (grub_addr_t) get_virtual_current_address (ch); + } - err = grub_multiboot_add_module ((grub_addr_t) module, size, - argc - 1, argv + 1); + err = grub_multiboot_add_module (target, size, argc - 1, argv + 1); if (err) { grub_file_close (file); diff --git a/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c similarity index 57% rename from loader/multiboot_elfxx.c rename to grub-core/loader/multiboot_elfxx.c index 78b7c542c..0c29fe9c2 100644 --- a/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -51,9 +51,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) { Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer; char *phdr_base; - int lowest_segment = -1, highest_segment = -1; int i; - grub_size_t code_size; if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX) return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); @@ -87,55 +85,45 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) phdr_base = (char *) buffer + ehdr->e_phoff; #define phdr(i) ((Elf_Phdr *) (phdr_base + (i) * ehdr->e_phentsize)) - for (i = 0; i < ehdr->e_phnum; i++) - if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0) - { - /* Beware that segment 0 isn't necessarily loadable */ - if (lowest_segment == -1 - || phdr(i)->p_paddr < phdr(lowest_segment)->p_paddr) - lowest_segment = i; - if (highest_segment == -1 - || phdr(i)->p_paddr > phdr(highest_segment)->p_paddr) - highest_segment = i; - } - - if (lowest_segment == -1) - return grub_error (GRUB_ERR_BAD_OS, "ELF contains no loadable segments"); - - code_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr; - grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr; - - grub_multiboot_pure_size += code_size; - - grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536; - grub_multiboot_payload_orig - = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi); - - if (!grub_multiboot_payload_orig) - return grub_errno; - /* Load every loadable segment in memory. */ for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0) + if (phdr(i)->p_type == PT_LOAD) { - char *load_this_module_at = (char *) (grub_multiboot_payload_orig + (long) (phdr(i)->p_paddr - phdr(lowest_segment)->p_paddr)); + grub_err_t err; + void *source; grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n", i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr); - if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset) - == (grub_off_t) -1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, + &ch, phdr(i)->p_paddr, + phdr(i)->p_memsz); + if (err) + { + grub_dprintf ("multiboot_loader", "Error loading phdr %d\n", i); + return err; + } + source = get_virtual_current_address (ch); + } - if (grub_file_read (file, load_this_module_at, phdr(i)->p_filesz) - != (grub_ssize_t) phdr(i)->p_filesz) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file"); + if (phdr(i)->p_filesz != 0) + { + if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset) + == (grub_off_t) -1) + return grub_error (GRUB_ERR_BAD_OS, + "invalid offset in program header"); + + if (grub_file_read (file, source, phdr(i)->p_filesz) + != (grub_ssize_t) phdr(i)->p_filesz) + return grub_error (GRUB_ERR_BAD_OS, + "couldn't read segment from file"); + } if (phdr(i)->p_filesz < phdr(i)->p_memsz) - grub_memset (load_this_module_at + phdr(i)->p_filesz, 0, + grub_memset ((grub_uint8_t *) source + phdr(i)->p_filesz, 0, phdr(i)->p_memsz - phdr(i)->p_filesz); } } @@ -144,14 +132,87 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) if (phdr(i)->p_vaddr <= ehdr->e_entry && phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry) { - grub_multiboot_payload_eip = grub_multiboot_payload_dest - + (ehdr->e_entry - phdr(i)->p_vaddr) + (phdr(i)->p_paddr - phdr(lowest_segment)->p_paddr); + grub_multiboot_payload_eip = (ehdr->e_entry - phdr(i)->p_vaddr) + + phdr(i)->p_paddr; break; } if (i == ehdr->e_phnum) return grub_error (GRUB_ERR_BAD_OS, "entry point isn't in a segment"); +#if defined (__i386__) || defined (__x86_64__) + +#elif defined (__mips) + grub_multiboot_payload_eip |= 0x80000000; +#else +#error Please complete this +#endif + + if (ehdr->e_shnum) + { + grub_uint8_t *shdr, *shdrptr; + + shdr = grub_malloc (ehdr->e_shnum * ehdr->e_shentsize); + if (!shdr) + return grub_errno; + + if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1) + return grub_error (GRUB_ERR_BAD_OS, + "invalid offset to section headers"); + + if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize) + != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize) + return grub_error (GRUB_ERR_BAD_OS, + "couldn't read sections headers from file"); + + for (shdrptr = shdr, i = 0; i < ehdr->e_shnum; + shdrptr += ehdr->e_shentsize, i++) + { + Elf_Shdr *sh = (Elf_Shdr *) shdrptr; + void *src; + grub_addr_t target; + grub_err_t err; + + /* This section is a loaded section, + so we don't care. */ + if (sh->sh_addr != 0) + continue; + + /* This section is empty, so we don't care. */ + if (sh->sh_size == 0) + continue; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, + &ch, 0, + (0xffffffff - sh->sh_size) + + 1, sh->sh_size, + sh->sh_addralign, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + { + grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i); + return err; + } + src = get_virtual_current_address (ch); + target = get_physical_target_address (ch); + } + + if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1) + return grub_error (GRUB_ERR_BAD_OS, + "invalid offset in section header"); + + if (grub_file_read (file, src, sh->sh_size) + != (grub_ssize_t) sh->sh_size) + return grub_error (GRUB_ERR_BAD_OS, + "couldn't read segment from file"); + sh->sh_addr = target; + } + grub_multiboot_add_elfsyms (ehdr->e_shnum, ehdr->e_shentsize, + ehdr->e_shstrndx, shdr); + } + #undef phdr return grub_errno; diff --git a/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c similarity index 71% rename from loader/multiboot_mbi2.c rename to grub-core/loader/multiboot_mbi2.c index 3ad6a6c4a..3141f0028 100644 --- a/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -16,10 +16,11 @@ * along with GRUB. If not, see . */ -#include #include #ifdef GRUB_MACHINE_PCBIOS #include +#include +#include #endif #include #include @@ -31,6 +32,11 @@ #include #include #include +#include + +#if defined (GRUB_MACHINE_EFI) +#include +#endif #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU) #include @@ -55,6 +61,19 @@ static unsigned modcnt; static char *cmdline = NULL; static int bootdev_set; static grub_uint32_t biosdev, slice, part; +static grub_size_t elf_sec_num, elf_sec_entsize; +static unsigned elf_sec_shstrndx; +static void *elf_sections; + +void +grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, + unsigned shndx, void *data) +{ + elf_sec_num = num; + elf_sec_shstrndx = shndx; + elf_sec_entsize = entsize; + elf_sections = data; +} grub_err_t grub_multiboot_load (grub_file_t file) @@ -125,11 +144,15 @@ grub_multiboot_load (grub_file_t file) case MULTIBOOT_TAG_TYPE_BOOTDEV: case MULTIBOOT_TAG_TYPE_MMAP: case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: - break; - case MULTIBOOT_TAG_TYPE_VBE: case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: case MULTIBOOT_TAG_TYPE_APM: + case MULTIBOOT_TAG_TYPE_EFI32: + case MULTIBOOT_TAG_TYPE_EFI64: + case MULTIBOOT_TAG_TYPE_ACPI_OLD: + case MULTIBOOT_TAG_TYPE_ACPI_NEW: + break; + default: grub_free (buffer); return grub_error (GRUB_ERR_UNKNOWN_OS, @@ -190,25 +213,24 @@ grub_multiboot_load (grub_file_t file) int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset : addr_tag->load_end_addr - addr_tag->load_addr); grub_size_t code_size; + void *source; + grub_relocator_chunk_t ch; if (addr_tag->bss_end_addr) code_size = (addr_tag->bss_end_addr - addr_tag->load_addr); else code_size = load_size; - grub_multiboot_payload_dest = addr_tag->load_addr; - grub_multiboot_pure_size += code_size; - - /* Allocate a bit more to avoid relocations in most cases. */ - grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536; - grub_multiboot_payload_orig - = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi); - - if (! grub_multiboot_payload_orig) + err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, + &ch, addr_tag->load_addr, + code_size); + if (err) { + grub_dprintf ("multiboot_loader", "Error loading aout kludge\n"); grub_free (buffer); - return grub_errno; + return err; } + source = get_virtual_current_address (ch); if ((grub_file_seek (file, offset)) == (grub_off_t) -1) { @@ -216,7 +238,7 @@ grub_multiboot_load (grub_file_t file) return grub_errno; } - grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size); + grub_file_read (file, source, load_size); if (grub_errno) { grub_free (buffer); @@ -224,7 +246,7 @@ grub_multiboot_load (grub_file_t file) } if (addr_tag->bss_end_addr) - grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0, + grub_memset ((grub_uint32_t *) source + load_size, 0, addr_tag->bss_end_addr - addr_tag->load_addr - load_size); } else @@ -252,7 +274,23 @@ grub_multiboot_load (grub_file_t file) return err; } -grub_size_t +static grub_size_t +acpiv2_size (void) +{ +#if GRUB_MACHINE_HAS_ACPI + struct grub_acpi_rsdp_v20 *p = grub_acpi_get_rsdpv2 (); + + if (!p) + return 0; + + return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi) + + p->length, MULTIBOOT_TAG_ALIGN); +#else + return 0; +#endif +} + +static grub_size_t grub_multiboot_get_mbi_size (void) { return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag) @@ -261,11 +299,22 @@ grub_multiboot_get_mbi_size (void) + (sizeof (struct multiboot_tag_string) + ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN)) + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd) - + sizeof (struct multiboot_tag_basic_meminfo) + + ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo), + MULTIBOOT_TAG_ALIGN) + ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN) - + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count () - * sizeof (struct multiboot_mmap_entry)) - + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1; + + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (elf_sec_entsize * elf_sec_num, MULTIBOOT_TAG_ALIGN) + + ALIGN_UP ((sizeof (struct multiboot_tag_mmap) + + grub_get_multiboot_mmap_count () + * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN) + + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi) + + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN) + + acpiv2_size () + + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1 + + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1; } /* Fill previously allocated Multiboot mmap. */ @@ -274,29 +323,31 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag) { struct multiboot_mmap_entry *mmap_entry = tag->entries; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + 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) { mmap_entry->addr = addr; mmap_entry->len = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE - case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + case GRUB_MEMORY_ACPI: mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: mmap_entry->type = MULTIBOOT_MEMORY_NVS; break; -#endif - + + case GRUB_MEMORY_BADRAM: + mmap_entry->type = MULTIBOOT_MEMORY_BADRAM; + break; + default: mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; break; @@ -315,6 +366,54 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag) grub_mmap_iterate (hook); } +#if defined (GRUB_MACHINE_PCBIOS) +static void +fill_vbe_tag (struct multiboot_tag_vbe *tag) +{ + grub_vbe_status_t status; + void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + + tag->type = MULTIBOOT_TAG_TYPE_VBE; + tag->size = 0; + + status = grub_vbe_bios_get_controller_info (scratch); + if (status != GRUB_VBE_STATUS_OK) + return; + + grub_memcpy (&tag->vbe_control_info, scratch, + sizeof (struct grub_vbe_info_block)); + + status = grub_vbe_bios_get_mode (scratch); + tag->vbe_mode = *(grub_uint32_t *) scratch; + if (status != GRUB_VBE_STATUS_OK) + return; + + /* get_mode_info isn't available for mode 3. */ + if (tag->vbe_mode == 3) + { + struct grub_vbe_mode_info_block *mode_info = (void *) &tag->vbe_mode_info; + grub_memset (mode_info, 0, + sizeof (struct grub_vbe_mode_info_block)); + mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT; + mode_info->x_resolution = 80; + mode_info->y_resolution = 25; + } + else + { + status = grub_vbe_bios_get_mode_info (tag->vbe_mode, scratch); + if (status != GRUB_VBE_STATUS_OK) + return; + grub_memcpy (&tag->vbe_mode_info, scratch, + sizeof (struct grub_vbe_mode_info_block)); + } + grub_vbe_bios_get_pm_interface (&tag->vbe_interface_seg, + &tag->vbe_interface_off, + &tag->vbe_interface_len); + + tag->size = sizeof (*tag); +} +#endif + static grub_err_t retrieve_video_parameters (grub_uint8_t **ptrorig) { @@ -403,6 +502,16 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) return GRUB_ERR_NONE; #endif +#if GRUB_MACHINE_HAS_VBE + { + struct multiboot_tag_vbe *tag_vbe = (struct multiboot_tag_vbe *) *ptrorig; + + fill_vbe_tag (tag_vbe); + + *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN); + } +#endif + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (err) return err; @@ -456,18 +565,34 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) } grub_err_t -grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, - grub_size_t bufsize) +grub_multiboot_make_mbi (grub_uint32_t *target) { grub_uint8_t *ptrorig; - grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off - + (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off)); + grub_uint8_t *mbistart; grub_err_t err; + grub_size_t bufsize; + grub_relocator_chunk_t ch; - if (bufsize < grub_multiboot_get_mbi_size ()) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small"); + bufsize = grub_multiboot_get_mbi_size (); - ptrorig = mbistart + 2 * sizeof (grub_uint32_t); + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, + 0, 0xffffffff - bufsize, + bufsize, MULTIBOOT_TAG_ALIGN, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + return err; + + ptrorig = get_virtual_current_address (ch); +#if defined (__i386__) || defined (__x86_64__) + *target = get_physical_target_address (ch); +#elif defined (__mips) + *target = get_physical_target_address (ch) | 0x80000000; +#else +#error Please complete this +#endif + + mbistart = ptrorig; + ptrorig += 2 * sizeof (grub_uint32_t); { struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig; @@ -485,6 +610,31 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } +#ifdef GRUB_MACHINE_PCBIOS + { + struct grub_apm_info info; + if (grub_apm_get_info (&info)) + { + struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig; + + tag->type = MULTIBOOT_TAG_TYPE_APM; + tag->size = sizeof (struct multiboot_tag_apm); + + tag->cseg = info.cseg; + tag->offset = info.offset; + tag->cseg_16 = info.cseg_16; + tag->dseg = info.dseg; + tag->flags = info.flags; + tag->cseg_len = info.cseg_len; + tag->dseg_len = info.dseg_len; + tag->cseg_16_len = info.cseg_16_len; + tag->version = info.version; + + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } +#endif + { unsigned i; struct module *cur; @@ -508,6 +658,19 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } + { + struct multiboot_tag_elf_sections *tag + = (struct multiboot_tag_elf_sections *) ptrorig; + tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS; + tag->size = sizeof (struct multiboot_tag_elf_sections) + + elf_sec_entsize * elf_sec_num; + grub_memcpy (tag->sections, elf_sections, elf_sec_entsize * elf_sec_num); + tag->num = elf_sec_num; + tag->entsize = elf_sec_entsize; + tag->shndx = elf_sec_shstrndx; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + { struct multiboot_tag_basic_meminfo *tag = (struct multiboot_tag_basic_meminfo *) ptrorig; @@ -541,7 +704,55 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, grub_errno = GRUB_ERR_NONE; } } - + +#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__) + { + struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi64 *) ptrorig; + tag->type = MULTIBOOT_TAG_TYPE_EFI64; + tag->size = sizeof (*tag); + tag->pointer = (grub_addr_t) grub_efi_system_table; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } +#endif + +#if defined (GRUB_MACHINE_EFI) && defined (__i386__) + { + struct multiboot_tag_efi32 *tag = (struct multiboot_tag_efi32 *) ptrorig; + tag->type = MULTIBOOT_TAG_TYPE_EFI32; + tag->size = sizeof (*tag); + tag->pointer = (grub_addr_t) grub_efi_system_table; + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } +#endif + +#if GRUB_MACHINE_HAS_ACPI + { + struct multiboot_tag_old_acpi *tag = (struct multiboot_tag_old_acpi *) + ptrorig; + struct grub_acpi_rsdp_v10 *a = grub_acpi_get_rsdpv1 (); + if (a) + { + tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD; + tag->size = sizeof (*tag) + sizeof (*a); + grub_memcpy (tag->rsdp, a, sizeof (*a)); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } + + { + struct multiboot_tag_new_acpi *tag = (struct multiboot_tag_new_acpi *) + ptrorig; + struct grub_acpi_rsdp_v20 *a = grub_acpi_get_rsdpv2 (); + if (a) + { + tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW; + tag->size = sizeof (*tag) + a->length; + grub_memcpy (tag->rsdp, a, a->length); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } +#endif + { struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_END; diff --git a/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c similarity index 76% rename from loader/powerpc/ieee1275/linux.c rename to grub-core/loader/powerpc/ieee1275/linux.c index 6b17a47ad..231aec1d3 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/grub-core/loader/powerpc/ieee1275/linux.c @@ -24,9 +24,9 @@ #include #include #include -#include #include #include +#include #define ELF32_LOADMASK (0xc0000000UL) #define ELF64_LOADMASK (0xc000000000000000ULL) @@ -46,6 +46,51 @@ static char *linux_args; typedef void (*kernel_entry_t) (void *, unsigned long, int (void *), unsigned long, unsigned long); +static grub_addr_t +grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size, + grub_size_t align) +{ + grub_addr_t found_addr = (grub_addr_t) -1; + + auto int NESTED_FUNC_ATTR alloc_mem (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR alloc_mem (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) + { + grub_uint64_t end = addr + len; + addr = ALIGN_UP (addr, align); + target = ALIGN_UP (target, align); + + /* Target above the memory chunk. */ + if (type != GRUB_MEMORY_AVAILABLE || target > end) + return 0; + + /* Target inside the memory chunk. */ + if (target >= addr && target < end && size <= end - target) + { + if (grub_claimmap (target, size) == GRUB_ERR_NONE) + { + found_addr = target; + return 1; + } + } + /* Target below the memory chunk. */ + if (target < addr && addr + size <= end) + { + if (grub_claimmap (addr, size) == GRUB_ERR_NONE) + { + found_addr = addr; + return 1; + } + } + return 0; + } + + grub_machine_mmap_iterate (alloc_mem); + + return found_addr; +} + static grub_err_t grub_linux_boot (void) { @@ -103,34 +148,30 @@ grub_linux_unload (void) static grub_err_t grub_linux_load32 (grub_elf_t elf) { - Elf32_Addr entry; - int found_addr = 0; + Elf32_Addr base_addr; + grub_addr_t seg_addr; + grub_uint32_t align; + int offset; - /* Linux's entry point incorrectly contains a virtual address. */ - entry = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK; - if (entry == 0) - entry = 0x01400000; - - linux_size = grub_elf32_size (elf, 0); + linux_size = grub_elf32_size (elf, &base_addr, &align); if (linux_size == 0) return grub_errno; /* Pad it; the kernel scribbles over memory beyond its load address. */ linux_size += 0x100000; + offset = elf->ehdr.ehdr32.e_entry - base_addr; + /* Linux's incorrectly contains a virtual address. */ + base_addr &= ~ELF32_LOADMASK; + /* On some systems, firmware occupies the memory we're trying to use. * Happily, Linux can be loaded anywhere (it relocates itself). Iterate * until we find an open area. */ - for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000) - { - grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", - linux_addr, linux_size); - found_addr = grub_claimmap (linux_addr, linux_size); - if (found_addr != -1) - break; - } - if (found_addr == -1) + seg_addr = grub_linux_claimmap_iterate (base_addr & ~ELF32_LOADMASK, linux_size, align); + if (seg_addr == (grub_addr_t) -1) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory"); + linux_addr = seg_addr + offset; + /* Now load the segments into the area we claimed. */ auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load); grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load) @@ -142,9 +183,7 @@ grub_linux_load32 (grub_elf_t elf) } *do_load = 1; - /* Linux's program headers incorrectly contain virtual addresses. - * Translate those to physical, and offset to the area we claimed. */ - *addr = (phdr->p_paddr & ~ELF32_LOADMASK) + linux_addr; + *addr = (phdr->p_paddr - base_addr) + seg_addr; return 0; } return grub_elf32_load (elf, offset_phdr, 0, 0); @@ -153,34 +192,30 @@ grub_linux_load32 (grub_elf_t elf) static grub_err_t grub_linux_load64 (grub_elf_t elf) { - Elf64_Addr entry; - int found_addr = 0; + Elf64_Addr base_addr; + grub_addr_t seg_addr; + grub_uint64_t align; + int offset; - /* Linux's entry point incorrectly contains a virtual address. */ - entry = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK; - if (entry == 0) - entry = 0x01400000; - - linux_size = grub_elf64_size (elf, 0); + linux_size = grub_elf64_size (elf, &base_addr, &align); if (linux_size == 0) return grub_errno; /* Pad it; the kernel scribbles over memory beyond its load address. */ linux_size += 0x100000; + offset = elf->ehdr.ehdr64.e_entry - base_addr; + /* Linux's incorrectly contains a virtual address. */ + base_addr &= ~ELF64_LOADMASK; + /* On some systems, firmware occupies the memory we're trying to use. * Happily, Linux can be loaded anywhere (it relocates itself). Iterate * until we find an open area. */ - for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000) - { - grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", - linux_addr, linux_size); - found_addr = grub_claimmap (linux_addr, linux_size); - if (found_addr != -1) - break; - } - if (found_addr == -1) + seg_addr = grub_linux_claimmap_iterate (base_addr & ~ELF64_LOADMASK, linux_size, align); + if (seg_addr == (grub_addr_t) -1) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't claim memory"); + linux_addr = seg_addr + offset; + /* Now load the segments into the area we claimed. */ auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load); grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load) @@ -191,9 +226,8 @@ grub_linux_load64 (grub_elf_t elf) return 0; } *do_load = 1; - /* Linux's program headers incorrectly contain virtual addresses. - * Translate those to physical, and offset to the area we claimed. */ - *addr = (phdr->p_paddr & ~ELF64_LOADMASK) + linux_addr; + + *addr = (phdr->p_paddr - base_addr) + seg_addr; return 0; } return grub_elf64_load (elf, offset_phdr, 0, 0); @@ -288,7 +322,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_ssize_t size; grub_addr_t first_addr; grub_addr_t addr; - int found_addr = 0; if (argc == 0) { @@ -302,6 +335,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } + grub_file_filter_disable_compression (); file = grub_file_open (argv[0]); if (! file) goto fail; @@ -311,20 +345,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), /* Attempt to claim at a series of addresses until successful in the same way that grub_rescue_cmd_linux does. */ - for (addr = first_addr; addr < first_addr + 200 * 0x100000; addr += 0x100000) - { - grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", - addr, size); - found_addr = grub_claimmap (addr, size); - if (found_addr != -1) - break; - } - - if (found_addr == -1) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot claim memory"); - goto fail; - } + addr = grub_linux_claimmap_iterate (first_addr, size, 0x100000); + if (addr == (grub_addr_t) -1) + goto fail; grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size); diff --git a/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c similarity index 98% rename from loader/sparc64/ieee1275/linux.c rename to grub-core/loader/sparc64/ieee1275/linux.c index f55b4fa2a..8ea96f1c9 100644 --- a/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -24,10 +24,9 @@ #include #include #include -#include -#include #include #include +#include static grub_dl_t my_mod; @@ -183,8 +182,10 @@ alloc_phys (grub_addr_t size) { grub_addr_t ret = (grub_addr_t) -1; - auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type); - int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type) + auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) { grub_addr_t end = addr + len; @@ -246,7 +247,7 @@ grub_linux_load64 (grub_elf_t elf) linux_entry = elf->ehdr.ehdr64.e_entry; linux_addr = 0x40004000; off = 0x4000; - linux_size = grub_elf64_size (elf, 0); + linux_size = grub_elf64_size (elf, 0, 0); if (linux_size == 0) return grub_errno; @@ -306,7 +307,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto out; } - file = grub_gzfile_open (argv[0], 1); + file = grub_file_open (argv[0]); if (!file) goto out; @@ -394,6 +395,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } + grub_file_filter_disable_compression (); file = grub_file_open (argv[0]); if (! file) goto fail; diff --git a/loader/xnu.c b/grub-core/loader/xnu.c similarity index 91% rename from loader/xnu.c rename to grub-core/loader/xnu.c index 8f1d0c641..d0b32dc6f 100644 --- a/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -40,45 +39,30 @@ static int driverspackagenum = 0; static int driversnum = 0; int grub_xnu_is_64bit = 0; -void *grub_xnu_heap_start = 0; +grub_addr_t grub_xnu_heap_target_start = 0; grub_size_t grub_xnu_heap_size = 0; - -/* Allocate heap by 32MB-blocks. */ -#define GRUB_XNU_HEAP_ALLOC_BLOCK 0x2000000 +struct grub_relocator *grub_xnu_relocator; static grub_err_t grub_xnu_register_memory (char *prefix, int *suffix, - void *addr, grub_size_t size); -void * -grub_xnu_heap_malloc (int size) + grub_addr_t addr, grub_size_t size); +grub_err_t +grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target) { - void *val; - int oldblknum, newblknum; + grub_err_t err; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, + grub_xnu_heap_target_start + + grub_xnu_heap_size, size); + if (err) + return err; - /* The page after the heap is used for stack. Ensure it's usable. */ - if (grub_xnu_heap_size) - oldblknum = (grub_xnu_heap_size + GRUB_XNU_PAGESIZE - + GRUB_XNU_HEAP_ALLOC_BLOCK - 1) / GRUB_XNU_HEAP_ALLOC_BLOCK; - else - oldblknum = 0; - newblknum = (grub_xnu_heap_size + size + GRUB_XNU_PAGESIZE - + GRUB_XNU_HEAP_ALLOC_BLOCK - 1) / GRUB_XNU_HEAP_ALLOC_BLOCK; - if (oldblknum != newblknum) - { - /* FIXME: instruct realloc to allocate at 1MB if possible once - advanced mm is ready. */ - grub_xnu_heap_start - = XNU_RELOCATOR (realloc) (grub_xnu_heap_start, - newblknum - * GRUB_XNU_HEAP_ALLOC_BLOCK); - if (!grub_xnu_heap_start) - return NULL; - } - - val = (grub_uint8_t *) grub_xnu_heap_start + grub_xnu_heap_size; + *src = get_virtual_current_address (ch); + *target = grub_xnu_heap_target_start + grub_xnu_heap_size; grub_xnu_heap_size += size; - grub_dprintf ("xnu", "val=%p\n", val); - return val; + grub_dprintf ("xnu", "val=%p\n", *src); + return GRUB_ERR_NONE; } /* Make sure next block of the heap will be aligned. @@ -87,11 +71,9 @@ grub_xnu_heap_malloc (int size) grub_err_t grub_xnu_align_heap (int align) { - int align_overhead = align - grub_xnu_heap_size % align; - if (align_overhead == align) - return GRUB_ERR_NONE; - if (! grub_xnu_heap_malloc (align_overhead)) - return grub_errno; + grub_xnu_heap_size + = ALIGN_UP (grub_xnu_heap_target_start+ grub_xnu_heap_size, align) + - grub_xnu_heap_target_start; return GRUB_ERR_NONE; } @@ -207,13 +189,14 @@ grub_xnu_writetree_toheap_real (void *curptr, } grub_err_t -grub_xnu_writetree_toheap (void **start, grub_size_t *size) +grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size) { struct grub_xnu_devtree_key *chosen; struct grub_xnu_devtree_key *memorymap; struct grub_xnu_devtree_key *driverkey; struct grub_xnu_extdesc *extdesc; grub_err_t err; + void *src; err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); if (err) @@ -244,16 +227,17 @@ grub_xnu_writetree_toheap (void **start, grub_size_t *size) /* Allocate the space based on the size with dummy value. */ *size = grub_xnu_writetree_get_size (grub_xnu_devtree_root, "/"); - *start = grub_xnu_heap_malloc (*size + GRUB_XNU_PAGESIZE - - *size % GRUB_XNU_PAGESIZE); + err = grub_xnu_heap_malloc (ALIGN_UP (*size + 1, GRUB_XNU_PAGESIZE), + &src, target); + if (err) + return err; /* Put real data in the dummy. */ - extdesc->addr = (grub_uint8_t *) *start - (grub_uint8_t *) grub_xnu_heap_start - + grub_xnu_heap_will_be_at; + extdesc->addr = *target; extdesc->size = (grub_uint32_t) *size; /* Write the tree to heap. */ - grub_xnu_writetree_toheap_real (*start, grub_xnu_devtree_root, "/"); + grub_xnu_writetree_toheap_real (src, grub_xnu_devtree_root, "/"); return GRUB_ERR_NONE; } @@ -338,8 +322,9 @@ grub_xnu_unload (void) /* Free loaded image. */ driversnum = 0; driverspackagenum = 0; - grub_free (grub_xnu_heap_start); - grub_xnu_heap_start = 0; + grub_relocator_unload (grub_xnu_relocator); + grub_xnu_relocator = NULL; + grub_xnu_heap_target_start = 0; grub_xnu_heap_size = 0; grub_xnu_unlock (); return GRUB_ERR_NONE; @@ -354,6 +339,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), grub_uint32_t startcode, endcode; int i; char *ptr, *loadaddr; + grub_addr_t loadaddr_target; if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); @@ -381,15 +367,18 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("xnu", "endcode = %lx, startcode = %lx\n", (unsigned long) endcode, (unsigned long) startcode); - loadaddr = grub_xnu_heap_malloc (endcode - startcode); - grub_xnu_heap_will_be_at = startcode; + grub_xnu_relocator = grub_relocator_new (); + if (!grub_xnu_relocator) + return grub_errno; + grub_xnu_heap_target_start = startcode; + err = grub_xnu_heap_malloc (endcode - startcode, (void **) &loadaddr, + &loadaddr_target); - if (! loadaddr) + if (err) { grub_macho_close (macho); grub_xnu_unload (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "not enough memory to load kernel"); + return err; } /* Load kernel. */ @@ -452,6 +441,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), grub_uint64_t startcode, endcode; int i; char *ptr, *loadaddr; + grub_addr_t loadaddr_target; if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); @@ -482,15 +472,18 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("xnu", "endcode = %lx, startcode = %lx\n", (unsigned long) endcode, (unsigned long) startcode); - loadaddr = grub_xnu_heap_malloc (endcode - startcode); - grub_xnu_heap_will_be_at = startcode; + grub_xnu_relocator = grub_relocator_new (); + if (!grub_xnu_relocator) + return grub_errno; + grub_xnu_heap_target_start = startcode; + err = grub_xnu_heap_malloc (endcode - startcode, (void **) &loadaddr, + &loadaddr_target); - if (! loadaddr) + if (err) { grub_macho_close (macho); grub_xnu_unload (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "not enough memory to load kernel"); + return err; } /* Load kernel. */ @@ -548,7 +541,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), and increment SUFFIX. */ static grub_err_t grub_xnu_register_memory (char *prefix, int *suffix, - void *addr, grub_size_t size) + grub_addr_t addr, grub_size_t size) { struct grub_xnu_devtree_key *chosen; struct grub_xnu_devtree_key *memorymap; @@ -585,8 +578,7 @@ grub_xnu_register_memory (char *prefix, int *suffix, = (struct grub_xnu_extdesc *) grub_malloc (sizeof (*extdesc)); if (! driverkey->data) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register extension"); - extdesc->addr = grub_xnu_heap_will_be_at + - ((grub_uint8_t *) addr - (grub_uint8_t *) grub_xnu_heap_start); + extdesc->addr = addr; extdesc->size = (grub_uint32_t) size; return GRUB_ERR_NONE; } @@ -628,7 +620,8 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) grub_file_t infoplist; struct grub_xnu_extheader *exthead; int neededspace = sizeof (*exthead); - grub_uint8_t *buf; + grub_uint8_t *buf, *buf0; + grub_addr_t buf_target; grub_size_t infoplistsize = 0, machosize = 0; char *name, *nameend; int namelen; @@ -667,7 +660,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) macho = 0; if (infoplistname) - infoplist = grub_gzfile_open (infoplistname, 1); + infoplist = grub_file_open (infoplistname); else infoplist = 0; grub_errno = GRUB_ERR_NONE; @@ -683,7 +676,10 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); if (err) return err; - buf = grub_xnu_heap_malloc (neededspace); + err = grub_xnu_heap_malloc (neededspace, (void **) &buf0, &buf_target); + if (err) + return err; + buf = buf0; exthead = (struct grub_xnu_extheader *) buf; grub_memset (exthead, 0, sizeof (*exthead)); @@ -692,8 +688,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) /* Load the binary. */ if (macho) { - exthead->binaryaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) - + grub_xnu_heap_will_be_at; + exthead->binaryaddr = buf_target + (buf - buf0); exthead->binarysize = machosize; if (grub_xnu_is_64bit) err = grub_macho_readfile64 (macho, buf); @@ -712,8 +707,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) /* Load the plist. */ if (infoplist) { - exthead->infoplistaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) - + grub_xnu_heap_will_be_at; + exthead->infoplistaddr = buf_target + (buf - buf0); exthead->infoplistsize = infoplistsize + 1; if (grub_file_read (infoplist, buf, infoplistsize) != (grub_ssize_t) (infoplistsize)) @@ -729,15 +723,14 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) } grub_errno = GRUB_ERR_NONE; - exthead->nameaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) - + grub_xnu_heap_will_be_at; + exthead->nameaddr = (buf - buf0) + buf_target; exthead->namesize = namelen + 1; grub_memcpy (buf, name, namelen); buf[namelen] = 0; buf += namelen + 1; /* Announce to kernel */ - return grub_xnu_register_memory ("Driver-", &driversnum, exthead, + return grub_xnu_register_memory ("Driver-", &driversnum, buf_target, neededspace); } @@ -748,6 +741,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file; void *loadto; + grub_addr_t loadto_target; grub_err_t err; grub_off_t readoff = 0; grub_ssize_t readlen = -1; @@ -761,7 +755,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), if (! grub_xnu_heap_size) return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); - file = grub_gzfile_open (args[0], 1); + file = grub_file_open (args[0]); if (! file) return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't load driver package"); @@ -836,11 +830,11 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), return err; } - loadto = grub_xnu_heap_malloc (readlen); - if (! loadto) + err = grub_xnu_heap_malloc (readlen, &loadto, &loadto_target); + if (err) { grub_file_close (file); - return grub_errno; + return err; } /* Read the file. */ @@ -855,7 +849,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), /* Pass it to kernel. */ return grub_xnu_register_memory ("DriversPackage-", &driverspackagenum, - loadto, readlen); + loadto_target, readlen); } static grub_err_t @@ -864,6 +858,7 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file; void *loadto; + grub_addr_t loadto_target; grub_err_t err; grub_size_t size; @@ -873,7 +868,7 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), if (! grub_xnu_heap_size) return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); - file = grub_gzfile_open (args[0], 1); + file = grub_file_open (args[0]); if (! file) return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't load ramdisk"); @@ -884,9 +879,9 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), size = grub_file_size (file); - loadto = grub_xnu_heap_malloc (size); - if (! loadto) - return grub_errno; + err = grub_xnu_heap_malloc (size, &loadto, &loadto_target); + if (err) + return err; if (grub_file_read (file, loadto, size) != (grub_ssize_t) (size)) { @@ -894,7 +889,7 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), grub_error_push (); return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); } - return grub_xnu_register_memory ("RAMDisk", 0, loadto, size); + return grub_xnu_register_memory ("RAMDisk", 0, loadto_target, size); } /* Returns true if the kext should be loaded according to plist @@ -913,7 +908,7 @@ grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq, if (binname) *binname = 0; - file = grub_gzfile_open (plistname, 1); + file = grub_file_open (plistname); if (! file) { grub_file_close (file); @@ -1170,7 +1165,7 @@ grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, grub_strcpy (binname + grub_strlen (binname), "/"); grub_strcpy (binname + grub_strlen (binname), binsuffix); grub_dprintf ("xnu", "%s:%s\n", plistname, binname); - binfile = grub_gzfile_open (binname, 1); + binfile = grub_file_open (binname); if (! binfile) grub_errno = GRUB_ERR_NONE; @@ -1208,7 +1203,7 @@ grub_cmd_xnu_kext (grub_command_t cmd __attribute__ ((unused)), /* User explicitly specified plist and binary. */ if (grub_strcmp (args[1], "-") != 0) { - binfile = grub_gzfile_open (args[1], 1); + binfile = grub_file_open (args[1]); if (! binfile) { grub_error (GRUB_ERR_BAD_OS, "can't open file"); @@ -1368,15 +1363,15 @@ static const struct grub_arg_option xnu_splash_cmd_options[] = }; static grub_err_t -grub_cmd_xnu_splash (grub_extcmd_t cmd, +grub_cmd_xnu_splash (grub_extcmd_context_t ctxt, int argc, char *args[]) { grub_err_t err; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - if (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && - grub_strcmp (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, + if (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && + grub_strcmp (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, "stretch") == 0) grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_STRETCH; else @@ -1439,8 +1434,7 @@ GRUB_MOD_INIT(xnu) "Load XNU ramdisk. " "It will be seen as md0."); cmd_splash = grub_register_extcmd ("xnu_splash", - grub_cmd_xnu_splash, - GRUB_COMMAND_FLAG_BOTH, 0, + grub_cmd_xnu_splash, 0, 0, N_("Load a splash image for XNU."), xnu_splash_cmd_options); diff --git a/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c similarity index 76% rename from loader/xnu_resume.c rename to grub-core/loader/xnu_resume.c index e6620e7b7..8f0e24483 100644 --- a/loader/xnu_resume.c +++ b/grub-core/loader/xnu_resume.c @@ -45,11 +45,14 @@ grub_xnu_resume (char *imagename) grub_file_t file; grub_size_t total_header_size; struct grub_xnu_hibernate_header hibhead; - grub_uint8_t *buf; - + void *code; + void *image; grub_uint32_t codedest; grub_uint32_t codesize; + grub_addr_t target_image; + grub_err_t err; + grub_file_filter_disable_compression (); file = grub_file_open (imagename); if (! file) return 0; @@ -94,18 +97,44 @@ grub_xnu_resume (char *imagename) /* Try to allocate necessary space. FIXME: mm isn't good enough yet to handle huge allocations. */ - grub_xnu_hibernate_image = buf = XNU_RELOCATOR (alloc) (hibhead.image_size - + codesize - + GRUB_XNU_PAGESIZE); - if (! buf) + grub_xnu_relocator = grub_relocator_new (); + if (!grub_xnu_relocator) { grub_file_close (file); return grub_errno; } + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, codedest, + codesize + GRUB_XNU_PAGESIZE); + if (err) + { + grub_file_close (file); + return err; + } + code = get_virtual_current_address (ch); + } + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &ch, 0, + (0xffffffff - hibhead.image_size) + 1, + hibhead.image_size, + GRUB_XNU_PAGESIZE, + GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + { + grub_file_close (file); + return err; + } + image = get_virtual_current_address (ch); + target_image = get_physical_target_address (ch); + } + /* Read code part. */ if (grub_file_seek (file, total_header_size) == (grub_off_t) -1 - || grub_file_read (file, buf, codesize) + || grub_file_read (file, code, codesize) != (grub_ssize_t) codesize) { grub_file_close (file); @@ -114,8 +143,7 @@ grub_xnu_resume (char *imagename) /* Read image. */ if (grub_file_seek (file, 0) == (grub_off_t) -1 - || grub_file_read (file, buf + codesize + GRUB_XNU_PAGESIZE, - hibhead.image_size) + || grub_file_read (file, image, hibhead.image_size) != (grub_ssize_t) hibhead.image_size) { grub_file_close (file); @@ -124,12 +152,11 @@ grub_xnu_resume (char *imagename) grub_file_close (file); /* Setup variables needed by asm helper. */ - grub_xnu_heap_will_be_at = codedest; - grub_xnu_heap_start = buf; - grub_xnu_heap_size = codesize + GRUB_XNU_PAGESIZE + hibhead.image_size; + grub_xnu_heap_target_start = codedest; + grub_xnu_heap_size = target_image + hibhead.image_size - codedest; grub_xnu_stack = (codedest + hibhead.stack); grub_xnu_entry_point = (codedest + hibhead.entry_point); - grub_xnu_arg1 = codedest + codesize + GRUB_XNU_PAGESIZE; + grub_xnu_arg1 = target_image; grub_dprintf ("xnu", "entry point 0x%x\n", codedest + hibhead.entry_point); grub_dprintf ("xnu", "image at 0x%x\n", diff --git a/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c similarity index 92% rename from mmap/efi/mmap.c rename to grub-core/mmap/efi/mmap.c index 316c997c7..5b82a8717 100644 --- a/mmap/efi/mmap.c +++ b/grub-core/mmap/efi/mmap.c @@ -29,9 +29,7 @@ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_efi_uintn_t mmap_size = 0; grub_efi_memory_descriptor_t *map_buf = 0; @@ -69,7 +67,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_CODE); + GRUB_MEMORY_CODE); + break; + + case GRUB_EFI_UNUSABLE_MEMORY: + hook (desc->physical_start, desc->num_pages * 4096, + GRUB_MEMORY_BADRAM); break; default: @@ -78,12 +81,11 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RUNTIME_SERVICES_DATA: - case GRUB_EFI_UNUSABLE_MEMORY: case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -92,17 +94,17 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_ACPI); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_NVS); + GRUB_MEMORY_NVS); break; } } @@ -115,29 +117,26 @@ make_efi_memtype (int type) { switch (type) { - case GRUB_MACHINE_MEMORY_CODE: + case GRUB_MEMORY_CODE: return GRUB_EFI_RUNTIME_SERVICES_CODE; /* No way to remove a chunk of memory from EFI mmap. So mark it as unusable. */ - case GRUB_MACHINE_MEMORY_HOLE: - - default: - - case GRUB_MACHINE_MEMORY_RESERVED: + case GRUB_MEMORY_HOLE: + case GRUB_MEMORY_RESERVED: return GRUB_EFI_UNUSABLE_MEMORY; - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: return GRUB_EFI_CONVENTIONAL_MEMORY; - case GRUB_MACHINE_MEMORY_ACPI: - return GRUB_EFI_ACPI_RECLAIM_MEMORY; - - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_ACPI: return GRUB_EFI_ACPI_RECLAIM_MEMORY; + case GRUB_MEMORY_NVS: + return GRUB_EFI_ACPI_MEMORY_NVS; } + return GRUB_EFI_UNUSABLE_MEMORY; } struct overlay diff --git a/mmap/i386/mmap.c b/grub-core/mmap/i386/mmap.c similarity index 94% rename from mmap/i386/mmap.c rename to grub-core/mmap/i386/mmap.c index f6e16129e..e9c030b7b 100644 --- a/mmap/i386/mmap.c +++ b/grub-core/mmap/i386/mmap.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -33,12 +34,12 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, grub_uint64_t highestlow = 0; auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); + grub_memory_type_t); int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t rangesize, - grub_uint32_t memtype) + grub_memory_type_t memtype) { grub_uint64_t end = start + rangesize; - if (memtype != GRUB_MACHINE_MEMORY_AVAILABLE) + if (memtype != GRUB_MEMORY_AVAILABLE) return 0; if (end > 0x100000) end = 0x100000; diff --git a/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c similarity index 98% rename from mmap/i386/pc/mmap.c rename to grub-core/mmap/i386/pc/mmap.c index 7d5a43fec..8dec083f8 100644 --- a/mmap/i386/pc/mmap.c +++ b/grub-core/mmap/i386/pc/mmap.c @@ -57,7 +57,7 @@ preboot (int noreturn __attribute__ ((unused))) auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { grub_dprintf ("mmap", "mmap chunk %llx-%llx:%x\n", addr, addr + size, type); hookmmapcur->addr = addr; @@ -135,7 +135,7 @@ malloc_hook (void) grub_uint32_t); int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { regcount++; return 0; @@ -172,7 +172,7 @@ malloc_hook (void) reentry = 1; hooktarget = grub_mmap_malign_and_register (16, hooksize, &mmapregion, - GRUB_MACHINE_MEMORY_RESERVED, + GRUB_MEMORY_RESERVED, GRUB_MMAP_MALLOC_LOW); reentry = 0; diff --git a/mmap/i386/pc/mmap_helper.S b/grub-core/mmap/i386/pc/mmap_helper.S similarity index 100% rename from mmap/i386/pc/mmap_helper.S rename to grub-core/mmap/i386/pc/mmap_helper.S diff --git a/mmap/i386/uppermem.c b/grub-core/mmap/i386/uppermem.c similarity index 78% rename from mmap/i386/uppermem.c rename to grub-core/mmap/i386/uppermem.c index cd1a45239..2aa430155 100644 --- a/mmap/i386/uppermem.c +++ b/grub-core/mmap/i386/uppermem.c @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -26,11 +27,12 @@ grub_mmap_get_lower (void) { grub_uint64_t lower = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr == 0) lower = size; @@ -48,11 +50,12 @@ grub_mmap_get_upper (void) { grub_uint64_t upper = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= 0x100000 && addr + size > 0x100000) upper = addr + size - 0x100000; @@ -69,11 +72,12 @@ grub_mmap_get_post64 (void) { grub_uint64_t post64 = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= 0x4000000 && addr + size > 0x4000000) post64 = addr + size - 0x4000000; diff --git a/mmap/mips/yeeloong/uppermem.c b/grub-core/mmap/mips/yeeloong/uppermem.c similarity index 82% rename from mmap/mips/yeeloong/uppermem.c rename to grub-core/mmap/mips/yeeloong/uppermem.c index 3c5f814de..723b6a888 100644 --- a/mmap/mips/yeeloong/uppermem.c +++ b/grub-core/mmap/mips/yeeloong/uppermem.c @@ -27,11 +27,12 @@ grub_mmap_get_lower (void) { grub_uint64_t lower = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr == 0) lower = size; @@ -49,11 +50,12 @@ grub_mmap_get_upper (void) { grub_uint64_t upper = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size > GRUB_ARCH_HIGHMEMPSTART) diff --git a/mmap/mmap.c b/grub-core/mmap/mmap.c similarity index 80% rename from mmap/mmap.c rename to grub-core/mmap/mmap.c index a1afc8b06..1c1825490 100644 --- a/mmap/mmap.c +++ b/grub-core/mmap/mmap.c @@ -17,8 +17,8 @@ * along with GRUB. If not, see . */ -#include #include +#include #include #include #include @@ -34,8 +34,7 @@ static int curhandle = 1; #endif grub_err_t -grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, grub_uint32_t)) +grub_mmap_iterate (grub_memory_hook_t hook) { /* This function resolves overlapping regions and sorts the memory map. @@ -48,27 +47,17 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 3 - unusable memory 4 - a range deliberately empty */ - int priority[GRUB_MACHINE_MEMORY_MAX_TYPE + 2] = + int priority[] = { -#ifdef GRUB_MACHINE_MEMORY_AVAILABLE - [GRUB_MACHINE_MEMORY_AVAILABLE] = 1, -#endif -#if defined (GRUB_MACHINE_MEMORY_RESERVED) && GRUB_MACHINE_MEMORY_RESERVED != GRUB_MACHINE_MEMORY_HOLE - [GRUB_MACHINE_MEMORY_RESERVED] = 3, -#endif -#ifdef GRUB_MACHINE_MEMORY_ACPI - [GRUB_MACHINE_MEMORY_ACPI] = 2, -#endif -#ifdef GRUB_MACHINE_MEMORY_CODE - [GRUB_MACHINE_MEMORY_CODE] = 3, -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - [GRUB_MACHINE_MEMORY_NVS] = 3, -#endif - [GRUB_MACHINE_MEMORY_HOLE] = 4, + [GRUB_MEMORY_AVAILABLE] = 1, + [GRUB_MEMORY_RESERVED] = 3, + [GRUB_MEMORY_ACPI] = 2, + [GRUB_MEMORY_CODE] = 3, + [GRUB_MEMORY_NVS] = 3, + [GRUB_MEMORY_HOLE] = 4, }; - int i, k, done; + int i, done; /* Scanline events. */ struct grub_mmap_scan @@ -89,7 +78,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, /* Current scanline event. */ int curtype; /* How many regions of given type overlap at current location? */ - int present[GRUB_MACHINE_MEMORY_MAX_TYPE + 2]; + int present[ARRAY_SIZE (priority)]; /* Number of mmap chunks. */ int mmap_num; @@ -101,7 +90,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { mmap_num++; return 0; @@ -111,17 +100,17 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { scanline_events[i].pos = addr; scanline_events[i].type = 0; - if (type <= GRUB_MACHINE_MEMORY_MAX_TYPE && priority[type]) + if (type < ARRAY_SIZE (priority) && priority[type]) scanline_events[i].memtype = type; else { grub_dprintf ("mmap", "Unknown memory type %d. Assuming unusable\n", type); - scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED; + scanline_events[i].memtype = GRUB_MEMORY_RESERVED; } i++; @@ -160,12 +149,10 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { scanline_events[i].pos = cur->start; scanline_events[i].type = 0; - if (cur->type == GRUB_MACHINE_MEMORY_HOLE - || (cur->type >= 0 && cur->type <= GRUB_MACHINE_MEMORY_MAX_TYPE - && priority[cur->type])) + if (cur->type < ARRAY_SIZE (priority) && priority[cur->type]) scanline_events[i].memtype = cur->type; else - scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED; + scanline_events[i].memtype = GRUB_MEMORY_RESERVED; i++; scanline_events[i].pos = cur->end; @@ -201,6 +188,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, lasttype = scanline_events[0].memtype; for (i = 0; i < 2 * mmap_num; i++) { + unsigned k; /* Process event. */ if (scanline_events[i].type) present[scanline_events[i].memtype]--; @@ -209,7 +197,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, /* Determine current region type. */ curtype = -1; - for (k = 0; k <= GRUB_MACHINE_MEMORY_MAX_TYPE + 1; k++) + for (k = 0; k < ARRAY_SIZE (priority); k++) if (present[k] && (curtype == -1 || priority[k] > priority[curtype])) curtype = k; @@ -217,7 +205,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, if ((curtype == -1 || curtype != lasttype) && lastaddr != scanline_events[i].pos && lasttype != -1 - && lasttype != GRUB_MACHINE_MEMORY_HOLE + && lasttype != GRUB_MEMORY_HOLE && hook (lastaddr, scanline_events[i].pos - lastaddr, lasttype)) { grub_free (scanline_events); @@ -324,10 +312,11 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), char * str; grub_uint64_t badaddr, badmask; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + 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_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { grub_uint64_t iterator, low, high, cur; int tail, var; @@ -370,7 +359,7 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), { grub_dprintf ("badram", "%llx (size %llx) is a badram range\n", (unsigned long long) cur, (1ULL << tail)); - grub_mmap_register (cur, (1ULL << tail), GRUB_MACHINE_MEMORY_HOLE); + grub_mmap_register (cur, (1ULL << tail), GRUB_MEMORY_HOLE); } return 0; } @@ -409,7 +398,71 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), } } -static grub_command_t cmd; +static grub_uint64_t +parsemem (const char *str) +{ + grub_uint64_t ret; + char *ptr; + + ret = grub_strtoul (str, &ptr, 0); + + switch (*ptr) + { + case 'K': + return ret << 10; + case 'M': + return ret << 20; + case 'G': + return ret << 30; + case 'T': + return ret << 40; + } + return ret; +} + +static grub_err_t +grub_cmd_cutmem (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_uint64_t from, to; + + 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 __attribute__ ((unused))) + { + grub_uint64_t end = addr + size; + + if (addr <= from) + addr = from; + if (end >= to) + end = to; + + if (end <= addr) + return 0; + + grub_mmap_register (addr, end - addr, GRUB_MEMORY_HOLE); + return 0; + } + + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "argements required"); + + from = parsemem (args[0]); + if (grub_errno) + return grub_errno; + + to = parsemem (args[1]); + if (grub_errno) + return grub_errno; + + grub_mmap_iterate (hook); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd, cmd_cut; GRUB_MOD_INIT(mmap) @@ -417,10 +470,15 @@ GRUB_MOD_INIT(mmap) cmd = grub_register_command ("badram", grub_cmd_badram, N_("ADDR1,MASK1[,ADDR2,MASK2[,...]]"), N_("Declare memory regions as badram.")); + cmd_cut = grub_register_command ("cutmem", grub_cmd_cutmem, + N_("FROM[K|M|G] TO[K|M|G]"), + N_("Remove any memory regions in specified range.")); + } GRUB_MOD_FINI(mmap) { grub_unregister_command (cmd); + grub_unregister_command (cmd_cut); } diff --git a/normal/auth.c b/grub-core/normal/auth.c similarity index 90% rename from normal/auth.c rename to grub-core/normal/auth.c index bf1efbfdd..e5d187f0e 100644 --- a/normal/auth.c +++ b/grub-core/normal/auth.c @@ -161,7 +161,7 @@ grub_username_get (char buf[], unsigned buf_size) while (1) { - key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + key = grub_getkey (); if (key == '\n' || key == '\r') break; @@ -201,7 +201,6 @@ grub_auth_check_authentication (const char *userlist) { char login[1024]; struct grub_auth_user *cur = NULL; - grub_err_t err; static unsigned long punishment_delay = 1; char entered[GRUB_AUTH_MAX_PASSLEN]; struct grub_auth_user *user; @@ -233,7 +232,7 @@ grub_auth_check_authentication (const char *userlist) if (!cur || ! cur->callback) goto access_denied; - err = cur->callback (login, entered, cur->arg); + cur->callback (login, entered, cur->arg); if (is_authenticated (userlist)) { punishment_delay = 1; @@ -248,3 +247,27 @@ grub_auth_check_authentication (const char *userlist) return GRUB_ACCESS_DENIED; } + +static grub_err_t +grub_cmd_authenticate (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + return grub_auth_check_authentication ((argc >= 1) ? args[0] : ""); +} + +static grub_command_t cmd; + +void +grub_normal_auth_init (void) +{ + cmd = grub_register_command ("authenticate", + grub_cmd_authenticate, + N_("[USERLIST]"), N_("Authenticate users")); + +} + +void +grub_normal_auth_fini (void) +{ + grub_unregister_command (cmd); +} diff --git a/normal/autofs.c b/grub-core/normal/autofs.c similarity index 100% rename from normal/autofs.c rename to grub-core/normal/autofs.c diff --git a/normal/charset.c b/grub-core/normal/charset.c similarity index 99% rename from normal/charset.c rename to grub-core/normal/charset.c index fd377e1c6..b7f775c4f 100644 --- a/normal/charset.c +++ b/grub-core/normal/charset.c @@ -297,13 +297,10 @@ grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, { grub_size_t msg_len = grub_strlen (msg); - *unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t)); + *unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t)); if (!*unicode_msg) - { - grub_printf ("utf8_to_ucs4 ERROR1: %s", msg); - return -1; - } + return -1; msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len, (grub_uint8_t *) msg, -1, 0); @@ -1215,6 +1212,8 @@ grub_bidi_logical_to_visual (const grub_uint32_t *logical, struct grub_unicode_glyph *visual_ptr; *visual_out = visual_ptr = grub_malloc (2 * sizeof (visual_ptr[0]) * logical_len); + if (!visual_ptr) + return -1; for (ptr = logical; ptr <= logical + logical_len; ptr++) { if (ptr == logical + logical_len || *ptr == '\n') diff --git a/normal/cmdline.c b/grub-core/normal/cmdline.c similarity index 95% rename from normal/cmdline.c rename to grub-core/normal/cmdline.c index daa0a1adb..b8c20d91c 100644 --- a/normal/cmdline.c +++ b/grub-core/normal/cmdline.c @@ -388,16 +388,18 @@ grub_cmdline_get (const char *prompt) grub_refresh (); - while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') + while ((key = grub_getkey ()) != '\n' && key != '\r') { switch (key) { - case 1: /* Ctrl-a */ + case GRUB_TERM_CTRL | 'a': + case GRUB_TERM_KEY_HOME: lpos = 0; cl_set_pos_all (); break; - case 2: /* Ctrl-b */ + case GRUB_TERM_CTRL | 'b': + case GRUB_TERM_KEY_LEFT: if (lpos > 0) { lpos--; @@ -405,12 +407,14 @@ grub_cmdline_get (const char *prompt) } break; - case 5: /* Ctrl-e */ + case GRUB_TERM_CTRL | 'e': + case GRUB_TERM_KEY_END: lpos = llen; cl_set_pos_all (); break; - case 6: /* Ctrl-f */ + case GRUB_TERM_CTRL | 'f': + case GRUB_TERM_KEY_RIGHT: if (lpos < llen) { lpos++; @@ -418,7 +422,8 @@ grub_cmdline_get (const char *prompt) } break; - case 9: /* Ctrl-i or TAB */ + case GRUB_TERM_CTRL | 'i': + case '\t': { int restore; char *insertu8; @@ -492,7 +497,7 @@ grub_cmdline_get (const char *prompt) } break; - case 11: /* Ctrl-k */ + case GRUB_TERM_CTRL | 'k': if (lpos < llen) { if (kill_buf) @@ -516,7 +521,8 @@ grub_cmdline_get (const char *prompt) } break; - case 14: /* Ctrl-n */ + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: { grub_uint32_t *hist; @@ -534,7 +540,9 @@ grub_cmdline_get (const char *prompt) break; } - case 16: /* Ctrl-p */ + + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': { grub_uint32_t *hist; @@ -553,7 +561,7 @@ grub_cmdline_get (const char *prompt) } break; - case 21: /* Ctrl-u */ + case GRUB_TERM_CTRL | 'u': if (lpos > 0) { grub_size_t n = lpos; @@ -579,12 +587,13 @@ grub_cmdline_get (const char *prompt) } break; - case 25: /* Ctrl-y */ + case GRUB_TERM_CTRL | 'y': if (kill_buf) cl_insert (kill_buf); break; case '\e': + grub_free (cl_terms); return 0; case '\b': @@ -597,7 +606,8 @@ grub_cmdline_get (const char *prompt) break; /* fall through */ - case 4: /* Ctrl-d */ + case GRUB_TERM_CTRL | 'd': + case GRUB_TERM_KEY_DC: if (lpos < llen) cl_delete (1); break; @@ -635,5 +645,6 @@ grub_cmdline_get (const char *prompt) ret = grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1); grub_free (buf); + grub_free (cl_terms); return ret; } diff --git a/normal/color.c b/grub-core/normal/color.c similarity index 90% rename from normal/color.c rename to grub-core/normal/color.c index bae082911..2e6c80b94 100644 --- a/normal/color.c +++ b/grub-core/normal/color.c @@ -56,22 +56,23 @@ parse_color_name (grub_uint8_t *ret, char *name) return -1; } -void -grub_parse_color_name_pair (grub_uint8_t *ret, const char *name) +int +grub_parse_color_name_pair (grub_uint8_t *color, const char *name) { + int result = 1; grub_uint8_t fg, bg; char *fg_name, *bg_name; /* nothing specified by user */ if (name == NULL) - return; + return result; fg_name = grub_strdup (name); if (fg_name == NULL) { /* "out of memory" message was printed by grub_strdup() */ grub_wait_after_message (); - return; + return result; } bg_name = grub_strchr (fg_name, '/'); @@ -97,10 +98,12 @@ grub_parse_color_name_pair (grub_uint8_t *ret, const char *name) goto free_and_return; } - *ret = (bg << 4) | fg; + *color = (bg << 4) | fg; + result = 0; free_and_return: grub_free (fg_name); + return result; } static grub_uint8_t color_normal, color_highlight; @@ -125,7 +128,8 @@ char * grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_parse_color_name_pair (&color_normal, val); + if (grub_parse_color_name_pair (&color_normal, val)) + return NULL; set_colors (); @@ -137,7 +141,8 @@ char * grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_parse_color_name_pair (&color_highlight, val); + if (grub_parse_color_name_pair (&color_highlight, val)) + return NULL; set_colors (); diff --git a/normal/completion.c b/grub-core/normal/completion.c similarity index 91% rename from normal/completion.c rename to grub-core/normal/completion.c index 40a645fb4..67676dfe4 100644 --- a/normal/completion.c +++ b/grub-core/normal/completion.c @@ -100,15 +100,16 @@ static int iterate_partition (grub_disk_t disk, const grub_partition_t p) { const char *disk_name = disk->name; - char *partition_name = grub_partition_get_name (p); char *name; int ret; + char *part_name; - if (! partition_name) + part_name = grub_partition_get_name (p); + if (! part_name) return 1; - name = grub_xasprintf ("%s,%s", disk_name, partition_name); - grub_free (partition_name); + name = grub_xasprintf ("%s,%s", disk_name, part_name); + grub_free (part_name); if (! name) return 1; @@ -160,14 +161,23 @@ iterate_dev (const char *devname) if (dev) { - if (dev->disk && dev->disk->has_partitions) + char tmp[grub_strlen (devname) + sizeof (",")]; + + grub_memcpy (tmp, devname, grub_strlen (devname)); + + if (grub_strcmp (devname, current_word) == 0) { - if (add_completion (devname, ",", GRUB_COMPLETION_TYPE_DEVICE)) + if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_PARTITION)) return 1; + + if (dev->disk) + if (grub_partition_iterate (dev->disk, iterate_partition)) + return 1; } else { - if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_DEVICE)) + grub_memcpy (tmp + grub_strlen (devname), "", sizeof ("")); + if (add_completion (tmp, "", GRUB_COMPLETION_TYPE_DEVICE)) return 1; } } @@ -200,7 +210,7 @@ complete_device (void) if (dev) { - if (dev->disk && dev->disk->has_partitions) + if (dev->disk) { if (grub_partition_iterate (dev->disk, iterate_partition)) { @@ -247,7 +257,8 @@ complete_file (void) goto fail; } - dir = grub_strchr (current_word, '/'); + dir = grub_strchr (current_word + (device ? 2 + grub_strlen (device) : 0), + '/'); last_dir = grub_strrchr (current_word, '/'); if (dir) { @@ -419,11 +430,8 @@ grub_normal_do_completion (char *buf, int *restore, { if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) { - if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) - { - if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) - goto fail; - } + if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) + goto fail; } } } @@ -499,7 +507,10 @@ grub_normal_do_completion (char *buf, int *restore, fail: if (argc != 0) - grub_free (argv[0]); + { + grub_free (argv[0]); + grub_free (argv); + } grub_free (match); grub_errno = GRUB_ERR_NONE; diff --git a/normal/context.c b/grub-core/normal/context.c similarity index 74% rename from normal/context.c rename to grub-core/normal/context.c index 27adf287a..75beeefda 100644 --- a/normal/context.c +++ b/grub-core/normal/context.c @@ -52,8 +52,8 @@ grub_env_set_menu (grub_menu_t nmenu) current_menu->menu = nmenu; } -grub_err_t -grub_env_context_open (int export) +static grub_err_t +grub_env_new_context (int export_all) { struct grub_env_context *context; int i; @@ -78,23 +78,36 @@ grub_env_context_open (int export) struct grub_env_var *var; for (var = context->prev->vars[i]; var; var = var->next) - { - if (export && var->global) - { - if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE) - { - grub_env_context_close (); - return grub_errno; - } - grub_env_export (var->name); - grub_register_variable_hook (var->name, var->read_hook, var->write_hook); - } - } + if (var->global || export_all) + { + if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE) + { + grub_env_context_close (); + return grub_errno; + } + grub_env_export (var->name); + grub_register_variable_hook (var->name, var->read_hook, var->write_hook); + } } return GRUB_ERR_NONE; } +grub_err_t +grub_env_context_open (void) +{ + return grub_env_new_context (0); +} + +int grub_extractor_level = 0; + +grub_err_t +grub_env_extractor_open (int source) +{ + grub_extractor_level++; + return grub_env_new_context (source); +} + grub_err_t grub_env_context_close (void) { @@ -132,6 +145,36 @@ grub_env_context_close (void) return GRUB_ERR_NONE; } +grub_err_t +grub_env_extractor_close (int source) +{ + grub_menu_t menu, menu2; + grub_menu_entry_t *last; + grub_err_t err; + + if (source) + { + menu = grub_env_get_menu (); + grub_env_unset_menu (); + } + err = grub_env_context_close (); + + if (source) + { + menu2 = grub_env_get_menu (); + + last = &menu2->entry_list; + while (*last) + last = &(*last)->next; + + *last = menu->entry_list; + menu2->size += menu->size; + } + + grub_extractor_level--; + return err; +} + grub_err_t grub_env_export (const char *name) { @@ -158,11 +201,15 @@ static grub_err_t grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { + int i; + if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no environment variable specified"); - grub_env_export (args[0]); + for (i = 0; i < argc; i++) + grub_env_export (args[i]); + return 0; } @@ -173,7 +220,8 @@ grub_context_init (void) grub_env_export ("prefix"); export_cmd = grub_register_command ("export", grub_cmd_export, - N_("ENVVAR"), N_("Export a variable.")); + N_("ENVVAR [ENVVAR] ..."), + N_("Export variables.")); } void diff --git a/normal/crypto.c b/grub-core/normal/crypto.c similarity index 100% rename from normal/crypto.c rename to grub-core/normal/crypto.c diff --git a/normal/datetime.c b/grub-core/normal/datetime.c similarity index 100% rename from normal/datetime.c rename to grub-core/normal/datetime.c diff --git a/normal/dyncmd.c b/grub-core/normal/dyncmd.c similarity index 78% rename from normal/dyncmd.c rename to grub-core/normal/dyncmd.c index a3cafa514..ed98855eb 100644 --- a/normal/dyncmd.c +++ b/grub-core/normal/dyncmd.c @@ -23,16 +23,21 @@ #include #include #include +#include +#include #include static grub_err_t -grub_dyncmd_dispatcher (struct grub_command *cmd, +grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, int argc, char **args) { - char *modname = cmd->data; + char *modname; grub_dl_t mod; grub_err_t ret; + grub_extcmd_t extcmd = ctxt->extcmd; + grub_command_t cmd = extcmd->cmd; + modname = extcmd->data; mod = grub_dl_load (modname); if (mod) { @@ -42,11 +47,17 @@ grub_dyncmd_dispatcher (struct grub_command *cmd, grub_dl_ref (mod); name = (char *) cmd->name; - grub_unregister_command (cmd); + grub_unregister_extcmd (extcmd); cmd = grub_command_find (name); if (cmd) - ret = (cmd->func) (cmd, argc, args); + { + if (cmd->flags & GRUB_COMMAND_FLAG_BLOCKS && + cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) + ret = grub_extcmd_dispatcher (cmd, argc, args, ctxt->script); + else + ret = (cmd->func) (cmd, argc, args); + } else ret = grub_errno; @@ -81,13 +92,14 @@ read_command_list (const char *prefix) for (ptr = grub_command_list; ptr; ptr = next) { next = ptr->next; - if (ptr->func == grub_dyncmd_dispatcher) + if (ptr->flags & GRUB_COMMAND_FLAG_DYNCMD) { if (last) last->next = ptr->next; else grub_command_list = ptr->next; grub_free (ptr); + grub_free (ptr->data); /* extcmd struct */ } else last = ptr; @@ -96,7 +108,7 @@ read_command_list (const char *prefix) for (;; grub_free (buf)) { char *p, *name, *modname; - grub_command_t cmd; + grub_extcmd_t cmd; int prio = 0; buf = grub_file_getline (file); @@ -139,16 +151,19 @@ read_command_list (const char *prefix) continue; } - cmd = grub_register_command_prio (name, - grub_dyncmd_dispatcher, - 0, N_("not loaded"), prio); + cmd = grub_register_extcmd_prio (name, + grub_dyncmd_dispatcher, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_FLAG_EXTCMD + | GRUB_COMMAND_FLAG_DYNCMD, + 0, N_("not loaded"), 0, + prio); if (! cmd) { grub_free (name); grub_free (modname); continue; } - cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD; cmd->data = modname; /* Update the active flag. */ diff --git a/normal/main.c b/grub-core/normal/main.c similarity index 69% rename from normal/main.c rename to grub-core/normal/main.c index 710b68d14..3bfbbeb72 100644 --- a/normal/main.c +++ b/grub-core/normal/main.c @@ -123,8 +123,8 @@ grub_file_getline (grub_file_t file) return cmdline; } -static void -free_menu (grub_menu_t menu) +void +grub_normal_free_menu (grub_menu_t menu) { grub_menu_entry_t entry = menu->entry_list; @@ -141,209 +141,6 @@ free_menu (grub_menu_t menu) grub_env_unset_menu (); } -static void -free_menu_entry_classes (struct grub_menu_entry_class *head) -{ - /* Free all the classes. */ - while (head) - { - struct grub_menu_entry_class *next; - - grub_free (head->name); - next = head->next; - grub_free (head); - head = next; - } -} - -static struct -{ - char *name; - int key; -} hotkey_aliases[] = - { - {"backspace", '\b'}, - {"tab", '\t'}, - {"delete", GRUB_TERM_DC} - }; - -/* Add a menu entry to the current menu context (as given by the environment - variable data slot `menu'). As the configuration file is read, the script - parser calls this when a menu entry is to be created. */ -grub_err_t -grub_normal_add_menu_entry (int argc, const char **args, - const char *sourcecode) -{ - const char *menutitle = 0; - const char *menusourcecode; - grub_menu_t menu; - grub_menu_entry_t *last; - int failed = 0; - int i; - struct grub_menu_entry_class *classes_head; /* Dummy head node for list. */ - struct grub_menu_entry_class *classes_tail; - char *users = NULL; - int hotkey = 0; - - /* Allocate dummy head node for class list. */ - classes_head = grub_zalloc (sizeof (struct grub_menu_entry_class)); - if (! classes_head) - return grub_errno; - classes_tail = classes_head; - - menu = grub_env_get_menu (); - if (! menu) - return grub_error (GRUB_ERR_MENU, "no menu context"); - - last = &menu->entry_list; - - menusourcecode = grub_strdup (sourcecode); - if (! menusourcecode) - return grub_errno; - - /* Parse menu arguments. */ - for (i = 0; i < argc; i++) - { - /* Capture arguments. */ - if (grub_strncmp ("--", args[i], 2) == 0 && i + 1 < argc) - { - const char *arg = &args[i][2]; - - /* Handle menu class. */ - if (grub_strcmp(arg, "class") == 0) - { - char *class_name; - struct grub_menu_entry_class *new_class; - - i++; - class_name = grub_strdup (args[i]); - if (! class_name) - { - failed = 1; - break; - } - - /* Create a new class and add it at the tail of the list. */ - new_class = grub_zalloc (sizeof (struct grub_menu_entry_class)); - if (! new_class) - { - grub_free (class_name); - failed = 1; - break; - } - /* Fill in the new class node. */ - new_class->name = class_name; - /* Link the tail to it, and make it the new tail. */ - classes_tail->next = new_class; - classes_tail = new_class; - continue; - } - else if (grub_strcmp(arg, "users") == 0) - { - i++; - users = grub_strdup (args[i]); - if (! users) - { - failed = 1; - break; - } - - continue; - } - else if (grub_strcmp(arg, "hotkey") == 0) - { - unsigned j; - - i++; - if (args[i][1] == 0) - { - hotkey = args[i][0]; - continue; - } - - for (j = 0; j < ARRAY_SIZE (hotkey_aliases); j++) - if (grub_strcmp (args[i], hotkey_aliases[j].name) == 0) - { - hotkey = hotkey_aliases[j].key; - break; - } - - if (j < ARRAY_SIZE (hotkey_aliases)) - continue; - - failed = 1; - grub_error (GRUB_ERR_MENU, - "Invalid hotkey: '%s'.", args[i]); - break; - } - else - { - /* Handle invalid argument. */ - failed = 1; - grub_error (GRUB_ERR_MENU, - "invalid argument for menuentry: %s", args[i]); - break; - } - } - - /* Capture title. */ - if (! menutitle) - { - menutitle = grub_strdup (args[i]); - } - else - { - failed = 1; - grub_error (GRUB_ERR_MENU, - "too many titles for menuentry: %s", args[i]); - break; - } - } - - /* Validate arguments. */ - if ((! failed) && (! menutitle)) - { - grub_error (GRUB_ERR_MENU, "menuentry is missing title"); - failed = 1; - } - - /* If argument parsing failed, free any allocated resources. */ - if (failed) - { - free_menu_entry_classes (classes_head); - grub_free ((void *) menutitle); - grub_free ((void *) menusourcecode); - - /* Here we assume that grub_error has been used to specify failure details. */ - return grub_errno; - } - - /* Add the menu entry at the end of the list. */ - while (*last) - last = &(*last)->next; - - *last = grub_zalloc (sizeof (**last)); - if (! *last) - { - free_menu_entry_classes (classes_head); - grub_free ((void *) menutitle); - grub_free ((void *) menusourcecode); - return grub_errno; - } - - (*last)->title = menutitle; - (*last)->hotkey = hotkey; - (*last)->classes = classes_head; - if (users) - (*last)->restricted = 1; - (*last)->users = users; - (*last)->sourcecode = menusourcecode; - - menu->size++; - - return GRUB_ERR_NONE; -} - static grub_menu_t read_config_file (const char *config) { @@ -445,10 +242,13 @@ grub_normal_init_page (struct grub_term_output *term) static void read_lists (const char *val) { - read_command_list (val); - read_fs_list (val); - read_crypto_list (val); - read_terminal_list (val); + if (! grub_no_autoload) + { + read_command_list (val); + read_fs_list (val); + read_crypto_list (val); + read_terminal_list (val); + } } static char * @@ -489,7 +289,7 @@ grub_normal_execute (const char *config, int nested, int batch) { grub_show_menu (menu, nested); if (nested) - free_menu (menu); + grub_normal_free_menu (menu); } } } @@ -674,7 +474,13 @@ static void (*grub_xputs_saved) (const char *str); GRUB_MOD_INIT(normal) { + /* Previously many modules depended on gzio. Be nice to user and load it. */ + grub_dl_load ("gzio"); + + grub_normal_auth_init (); grub_context_init (); + grub_script_init (); + grub_menu_init (); grub_xputs_saved = grub_xputs; grub_xputs = grub_xputs_normal; @@ -704,11 +510,18 @@ GRUB_MOD_INIT(normal) /* Preserve hooks after context changes. */ grub_env_export ("color_normal"); grub_env_export ("color_highlight"); + + /* Set default color names. */ + grub_env_set ("color_normal", "white/black"); + grub_env_set ("color_highlight", "black/white"); } GRUB_MOD_FINI(normal) { grub_context_fini (); + grub_script_fini (); + grub_menu_fini (); + grub_normal_auth_fini (); grub_xputs = grub_xputs_saved; diff --git a/normal/menu.c b/grub-core/normal/menu.c similarity index 91% rename from normal/menu.c rename to grub-core/normal/menu.c index b57990b0d..807ad51e0 100644 --- a/normal/menu.c +++ b/grub-core/normal/menu.c @@ -43,9 +43,20 @@ grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu, void grub_wait_after_message (void) { + grub_uint64_t endtime; grub_xputs ("\n"); grub_printf_ (N_("Press any key to continue...")); - (void) grub_getkey (); + grub_refresh (); + + endtime = grub_get_time_ms () + 10000; + + while (grub_get_time_ms () < endtime) + if (grub_checkkey () >= 0) + { + grub_getkey (); + break; + } + grub_xputs ("\n"); } @@ -142,49 +153,13 @@ get_and_remove_first_entry_number (const char *name) return entry; } -static void -grub_menu_execute_entry_real (grub_menu_entry_t entry) -{ - const char *source; - - auto grub_err_t getline (char **line, int cont); - grub_err_t getline (char **line, int cont __attribute__ ((unused))) - { - const 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; - } - - source = entry->sourcecode; - - while (source) - { - char *line; - - getline (&line, 0); - grub_normal_parse_line (line, getline); - grub_free (line); - } -} - /* Run a menu entry. */ void grub_menu_execute_entry(grub_menu_entry_t entry) { grub_err_t err = GRUB_ERR_NONE; + int errs_before; + grub_menu_t menu; if (entry->restricted) err = grub_auth_check_authentication (entry->users); @@ -196,13 +171,36 @@ grub_menu_execute_entry(grub_menu_entry_t entry) return; } - grub_env_set ("chosen", entry->title); + errs_before = grub_err_printed_errors; - grub_menu_execute_entry_real (entry); + if (entry->submenu) + { + grub_env_context_open (); + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return; + grub_env_set_menu (menu); + } + + grub_env_set ("chosen", entry->title); + grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args); + + if (errs_before != grub_err_printed_errors) + grub_wait_after_message (); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ grub_command_execute ("boot", 0, 0); + + if (entry->submenu) + { + if (menu && menu->size) + { + grub_show_menu (menu, 1); + grub_normal_free_menu (menu); + } + grub_env_context_close (); + } } /* Execute ENTRY from the menu MENU, falling back to entries specified @@ -435,7 +433,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) if (grub_checkkey () >= 0 || timeout < 0) { - c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + c = grub_getkey (); if (timeout >= 0) { @@ -446,31 +444,36 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) switch (c) { - case GRUB_TERM_HOME: + case GRUB_TERM_KEY_HOME: + case GRUB_TERM_CTRL | 'a': current_entry = 0; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_END: + case GRUB_TERM_KEY_END: + case GRUB_TERM_CTRL | 'e': current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_UP: + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_DOWN: + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_PPAGE: + case GRUB_TERM_CTRL | 'g': + case GRUB_TERM_KEY_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else @@ -478,7 +481,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_NPAGE: + case GRUB_TERM_CTRL | 'c': + case GRUB_TERM_KEY_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else @@ -488,7 +492,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) case '\n': case '\r': - case 6: + case GRUB_TERM_KEY_RIGHT: + case GRUB_TERM_CTRL | 'f': menu_fini (); *auto_boot = 0; return current_entry; @@ -604,20 +609,9 @@ show_menu (grub_menu_t menu, int nested) grub_cls (); if (auto_boot) - { - grub_menu_execute_with_fallback (menu, e, &execution_callback, 0); - } + grub_menu_execute_with_fallback (menu, e, &execution_callback, 0); else - { - int chars_before = grub_normal_get_char_counter (); - grub_errno = GRUB_ERR_NONE; - grub_menu_execute_entry (e); - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - - if (chars_before != grub_normal_get_char_counter ()) - grub_wait_after_message (); - } + grub_menu_execute_entry (e); } return GRUB_ERR_NONE; diff --git a/normal/menu_entry.c b/grub-core/normal/menu_entry.c similarity index 95% rename from normal/menu_entry.c rename to grub-core/normal/menu_entry.c index 238c94ecd..6cadf81ba 100644 --- a/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -71,6 +71,8 @@ struct screen /* The flag of a completion window. */ int completion_shown; + int submenu; + struct per_term_screen *terms; unsigned nterms; }; @@ -496,6 +498,8 @@ make_screen (grub_menu_entry_t entry) if (! screen) return 0; + screen->submenu = entry->submenu; + screen->num_lines = 1; screen->lines = grub_malloc (sizeof (struct line)); if (! screen->lines) @@ -1161,6 +1165,8 @@ run (struct screen *screen) { int currline = 0; char *nextline; + int errs_before; + grub_menu_t menu; auto grub_err_t editor_getline (char **line, int cont); grub_err_t editor_getline (char **line, int cont __attribute__ ((unused))) @@ -1194,6 +1200,16 @@ run (struct screen *screen) grub_printf_ (N_("Booting a command list")); grub_printf ("\n\n"); + errs_before = grub_err_printed_errors; + + if (screen->submenu) + { + grub_env_context_open (); + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return 0; + grub_env_set_menu (menu); + } /* Execute the script, line for line. */ while (currline < screen->num_lines) @@ -1203,10 +1219,23 @@ run (struct screen *screen) break; } + if (errs_before != grub_err_printed_errors) + grub_wait_after_message (); + if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ grub_command_execute ("boot", 0, 0); + if (screen->submenu) + { + if (menu && menu->size) + { + grub_show_menu (menu, 1); + grub_normal_free_menu (menu); + } + grub_env_context_close (); + } + if (grub_errno != GRUB_ERR_NONE) { grub_print_error (); @@ -1272,7 +1301,7 @@ grub_menu_entry_run (grub_menu_entry_t entry) while (1) { - int c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + int c = grub_getkey (); if (screen->completion_shown) { @@ -1288,70 +1317,79 @@ grub_menu_entry_run (grub_menu_entry_t entry) switch (c) { - case 16: /* C-p */ + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': if (! previous_line (screen, 1)) goto fail; break; - case 14: /* C-n */ + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: if (! next_line (screen, 1)) goto fail; break; - case 6: /* C-f */ + case GRUB_TERM_CTRL | 'f': + case GRUB_TERM_KEY_RIGHT: if (! forward_char (screen, 1)) goto fail; break; - case 2: /* C-b */ + case GRUB_TERM_CTRL | 'b': + case GRUB_TERM_KEY_LEFT: if (! backward_char (screen, 1)) goto fail; break; - case 1: /* C-a */ + case GRUB_TERM_CTRL | 'a': + case GRUB_TERM_KEY_HOME: if (! beginning_of_line (screen, 1)) goto fail; break; - case 5: /* C-e */ + case GRUB_TERM_CTRL | 'e': + case GRUB_TERM_KEY_END: if (! end_of_line (screen, 1)) goto fail; break; - case '\t': /* C-i */ + case GRUB_TERM_CTRL | 'i': + case '\t': if (! complete (screen, prev_c == c, 1)) goto fail; break; - case 4: /* C-d */ + case GRUB_TERM_CTRL | 'd': + case GRUB_TERM_KEY_DC: if (! delete_char (screen, 1)) goto fail; break; - case 8: /* C-h */ + case GRUB_TERM_CTRL | 'h': + case '\b': if (! backward_delete_char (screen, 1)) goto fail; break; - case 11: /* C-k */ + case GRUB_TERM_CTRL | 'k': if (! kill_line (screen, prev_c == c, 1)) goto fail; break; - case 21: /* C-u */ + case GRUB_TERM_CTRL | 'u': /* FIXME: What behavior is good for this key? */ break; - case 25: /* C-y */ + case GRUB_TERM_CTRL | 'y': if (! yank (screen, 1)) goto fail; break; - case 12: /* C-l */ + case GRUB_TERM_CTRL | 'l': /* FIXME: centering. */ goto refresh; - case 15: /* C-o */ + case GRUB_TERM_CTRL | 'o': if (! open_line (screen, 1)) goto fail; break; @@ -1366,23 +1404,19 @@ grub_menu_entry_run (grub_menu_entry_t entry) destroy_screen (screen); return; - case 3: /* C-c */ + case GRUB_TERM_CTRL | 'c': + case GRUB_TERM_KEY_F2: grub_cmdline_run (1); goto refresh; - case 24: /* C-x */ - { - int chars_before = grub_normal_get_char_counter (); - run (screen); - - if (chars_before != grub_normal_get_char_counter ()) - grub_wait_after_message (); - } + case GRUB_TERM_CTRL | 'x': + case GRUB_TERM_KEY_F10: + run (screen); goto refresh; - case 18: /* C-r */ - case 19: /* C-s */ - case 20: /* C-t */ + case GRUB_TERM_CTRL | 'r': + case GRUB_TERM_CTRL | 's': + case GRUB_TERM_CTRL | 't': /* FIXME */ break; diff --git a/normal/menu_text.c b/grub-core/normal/menu_text.c similarity index 96% rename from normal/menu_text.c rename to grub-core/normal/menu_text.c index 3e3e7e2fa..fc4a89196 100644 --- a/normal/menu_text.c +++ b/grub-core/normal/menu_text.c @@ -120,17 +120,10 @@ print_message (int nested, int edit, struct grub_term_output *term) if (edit) { grub_putcode ('\n', term); -#ifdef GRUB_MACHINE_EFI grub_print_message_indented (_("Minimum Emacs-like screen editing is \ -supported. TAB lists completions. Press F1 to boot, F2=Ctrl-a, F3=Ctrl-e, \ -F4 for a command-line or ESC to discard edits and return to the GRUB menu."), - STANDARD_MARGIN, STANDARD_MARGIN, term); -#else - grub_print_message_indented (_("Minimum Emacs-like screen editing is \ -supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \ +supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \ command-line or ESC to discard edits and return to the GRUB menu."), STANDARD_MARGIN, STANDARD_MARGIN, term); -#endif } else { diff --git a/normal/misc.c b/grub-core/normal/misc.c similarity index 86% rename from normal/misc.c rename to grub-core/normal/misc.c index 2b84b1c82..d81b6d26f 100644 --- a/normal/misc.c +++ b/grub-core/normal/misc.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Print the information on the device NAME. */ grub_err_t @@ -107,10 +108,18 @@ grub_normal_print_device_info (const char *name) grub_errno = GRUB_ERR_NONE; } } - else if (! dev->disk->has_partitions || dev->disk->partition) - grub_printf ("%s", _("Unknown filesystem")); else - grub_printf ("%s", _("Partition table")); + grub_printf ("%s", _("Not a known filesystem")); + + if (dev->disk->partition) + grub_printf (_(" - Partition start at %u"), + grub_partition_get_start (dev->disk->partition)); + if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) + grub_printf (_(" - Total size unknown"), + grub_disk_get_size (dev->disk)); + else + grub_printf (_(" - Total size %u sectors"), + grub_disk_get_size (dev->disk)); grub_device_close (dev); } diff --git a/normal/term.c b/grub-core/normal/term.c similarity index 92% rename from normal/term.c rename to grub-core/normal/term.c index 4f5779abe..00721c447 100644 --- a/normal/term.c +++ b/grub-core/normal/term.c @@ -42,13 +42,8 @@ static struct term_state *term_states = NULL; /* If the more pager is active. */ static int grub_more; -static int grub_normal_char_counter = 0; - -int -grub_normal_get_char_counter (void) -{ - return grub_normal_char_counter; -} +static void +putcode_real (grub_uint32_t code, struct grub_term_output *term); void grub_normal_reset_more (void) @@ -83,7 +78,7 @@ print_more (void) { grub_print_ucs4 (unicode_str, unicode_last_position, 0, 0, term); } - grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_free (unicode_str); @@ -94,6 +89,7 @@ print_more (void) FOR_ACTIVE_TERM_OUTPUTS(term) grub_print_spaces (term, 8); grub_term_restore_pos (pos); + grub_free (pos); /* Scroll one lines or an entire page, depending on the key. */ @@ -202,8 +198,39 @@ void grub_puts_terminal (const char *str, struct grub_term_output *term) { grub_uint32_t *unicode_str, *unicode_last_position; + grub_error_push (); grub_utf8_to_ucs4_alloc (str, &unicode_str, &unicode_last_position); + grub_error_pop (); + if (!unicode_str) + { + for (; *str; str++) + { + struct grub_unicode_glyph c = + { + .variant = 0, + .attributes = 0, + .ncomb = 0, + .combining = 0, + .estimated_width = 1, + .base = *str + }; + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + (term->putchar) (term, &c); + } + if (*str == '\n') + { + c.base = '\r'; + FOR_ACTIVE_TERM_OUTPUTS(term) + { + (term->putchar) (term, &c); + } + } + } + return; + } grub_print_ucs4 (unicode_str, unicode_last_position, 0, 0, term); grub_free (unicode_str); @@ -349,8 +376,8 @@ read_terminal_list (const char *prefix) if (! cur->modname) { grub_errno = GRUB_ERR_NONE; - grub_free (cur); grub_free (cur->name); + grub_free (cur); continue; } cur->next = *target; @@ -374,8 +401,6 @@ putglyph (const struct grub_unicode_glyph *c, struct grub_term_output *term) .estimated_width = 1 }; - grub_normal_char_counter++; - if (c->base == '\t' && term->getxy) { int n; @@ -622,7 +647,7 @@ put_glyphs_terminal (const struct grub_unicode_glyph *visual, >= (grub_ssize_t) grub_term_height (term) - 2) { state->backlog_glyphs = visual_ptr + 1; - state->backlog_len = visual_len - (visual - visual_ptr) - 1; + state->backlog_len = visual_len - (visual_ptr - visual) - 1; return 1; } @@ -653,6 +678,7 @@ print_backlog (struct grub_term_output *term, grub_free (state->free); state->free = NULL; state->backlog_len = 0; + state->backlog_ucs4 = 0; } return ret; } @@ -668,6 +694,7 @@ print_backlog (struct grub_term_output *term, grub_free (state->free); state->free = NULL; state->backlog_len = 0; + state->backlog_glyphs = 0; } return ret; } @@ -742,15 +769,43 @@ grub_print_ucs4 (const grub_uint32_t * str, void grub_xputs_normal (const char *str) { - grub_term_output_t term; - grub_uint32_t *unicode_str, *unicode_last_position; + grub_uint32_t *unicode_str = NULL, *unicode_last_position; int backlog = 0; + grub_term_output_t term; + + grub_error_push (); grub_utf8_to_ucs4_alloc (str, &unicode_str, - &unicode_last_position); + &unicode_last_position); + grub_error_pop (); if (!unicode_str) { - grub_errno = GRUB_ERR_NONE; + for (; *str; str++) + { + struct grub_unicode_glyph c = + { + .variant = 0, + .attributes = 0, + .ncomb = 0, + .combining = 0, + .estimated_width = 1, + .base = *str + }; + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + (term->putchar) (term, &c); + } + if (*str == '\n') + { + c.base = '\r'; + FOR_ACTIVE_TERM_OUTPUTS(term) + { + (term->putchar) (term, &c); + } + } + } + return; } diff --git a/partmap/acorn.c b/grub-core/partmap/acorn.c similarity index 100% rename from partmap/acorn.c rename to grub-core/partmap/acorn.c diff --git a/partmap/amiga.c b/grub-core/partmap/amiga.c similarity index 100% rename from partmap/amiga.c rename to grub-core/partmap/amiga.c diff --git a/partmap/apple.c b/grub-core/partmap/apple.c similarity index 100% rename from partmap/apple.c rename to grub-core/partmap/apple.c diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c new file mode 100644 index 000000000..09ecd935a --- /dev/null +++ b/grub-core/partmap/bsdlabel.c @@ -0,0 +1,251 @@ +/* bsdlabel.c - Read BSD style partition tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,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 + * 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 + +#ifdef GRUB_UTIL +#include +#endif + +static struct grub_partition_map grub_bsdlabel_partition_map; +static struct grub_partition_map grub_netbsdlabel_partition_map; +static struct grub_partition_map grub_openbsdlabel_partition_map; + + + +static grub_err_t +iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd, + struct grub_partition_map *pmap, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition_bsd_disk_label label; + struct grub_partition p; + grub_disk_addr_t delta = 0; + grub_disk_addr_t pos; + + /* Read the BSD label. */ + if (grub_disk_read (disk, sector, 0, sizeof (label), &label)) + return grub_errno; + + /* Check if it is valid. */ + if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + /* A kludge to determine a base of be.offset. */ + if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION + < grub_cpu_to_le16 (label.num_partitions) && freebsd) + { + struct grub_partition_bsd_entry whole_disk_be; + + pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE + + sizeof (struct grub_partition_bsd_entry) + * GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION; + + if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE, + pos % GRUB_DISK_SECTOR_SIZE, sizeof (whole_disk_be), + &whole_disk_be)) + return grub_errno; + + delta = grub_le_to_cpu32 (whole_disk_be.offset); + } + + pos = sizeof (label) + sector * GRUB_DISK_SECTOR_SIZE; + + for (p.number = 0; + p.number < grub_cpu_to_le16 (label.num_partitions); + p.number++, pos += sizeof (struct grub_partition_bsd_entry)) + { + struct grub_partition_bsd_entry be; + + if (p.number == GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION) + continue; + + p.offset = pos / GRUB_DISK_SECTOR_SIZE; + p.index = pos % GRUB_DISK_SECTOR_SIZE; + + if (grub_disk_read (disk, p.offset, p.index, sizeof (be), &be)) + return grub_errno; + + p.start = grub_le_to_cpu32 (be.offset); + p.len = grub_le_to_cpu32 (be.size); + p.partmap = pmap; + + if (p.len == 0) + continue; + + if (p.start < delta) + { +#ifdef GRUB_UTIL + char *partname; + /* disk->partition != NULL as 0 < delta */ + partname = grub_partition_get_name (disk->partition); + grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)", + disk->name, partname, p.partmap->name, p.number + 1); + grub_free (partname); +#endif + continue; + } + + p.start -= delta; + + if (hook (disk, &p)) + return grub_errno; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +bsdlabel_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + + if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos") + == 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD) + return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1, + &grub_bsdlabel_partition_map, hook); + + if (disk->partition + && (grub_strcmp (disk->partition->partmap->name, "msdos") == 0 + || disk->partition->partmap == &grub_bsdlabel_partition_map + || disk->partition->partmap == &grub_netbsdlabel_partition_map + || disk->partition->partmap == &grub_openbsdlabel_partition_map)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); + + return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, + &grub_bsdlabel_partition_map, hook); +} + +/* This is a total breakage. Even when net-/openbsd label is inside partition + it actually describes the whole disk. + */ +static grub_err_t +netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type, + struct grub_partition_map *pmap, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + int count = 0; + + auto int check_msdos (grub_disk_t dsk, + const grub_partition_t partition); + + int check_msdos (grub_disk_t dsk, + const grub_partition_t partition) + { + grub_err_t err; + + if (partition->msdostype != type) + return 0; + + err = iterate_real (dsk, partition->start + + GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, pmap, hook); + if (err == GRUB_ERR_NONE) + { + count++; + return 1; + } + if (err == GRUB_ERR_BAD_PART_TABLE) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + grub_print_error (); + return 0; + } + + if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos") + == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); + + { + grub_err_t err; + err = grub_partition_msdos_iterate (disk, check_msdos); + + if (err) + return err; + if (!count) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no bsdlabel found"); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +netbsdlabel_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + return netopenbsdlabel_partition_map_iterate (disk, + GRUB_PC_PARTITION_TYPE_NETBSD, + &grub_netbsdlabel_partition_map, + hook); +} + +static grub_err_t +openbsdlabel_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + return netopenbsdlabel_partition_map_iterate (disk, + GRUB_PC_PARTITION_TYPE_OPENBSD, + &grub_openbsdlabel_partition_map, + hook); +} + + +static struct grub_partition_map grub_bsdlabel_partition_map = + { + .name = "bsd", + .iterate = bsdlabel_partition_map_iterate, + }; + +static struct grub_partition_map grub_openbsdlabel_partition_map = + { + .name = "openbsd", + .iterate = openbsdlabel_partition_map_iterate, + }; + +static struct grub_partition_map grub_netbsdlabel_partition_map = + { + .name = "netbsd", + .iterate = netbsdlabel_partition_map_iterate, + }; + + + +GRUB_MOD_INIT(part_bsd) +{ + grub_partition_map_register (&grub_bsdlabel_partition_map); + grub_partition_map_register (&grub_netbsdlabel_partition_map); + grub_partition_map_register (&grub_openbsdlabel_partition_map); +} + +GRUB_MOD_FINI(part_bsd) +{ + grub_partition_map_unregister (&grub_bsdlabel_partition_map); + grub_partition_map_unregister (&grub_netbsdlabel_partition_map); + grub_partition_map_unregister (&grub_openbsdlabel_partition_map); +} diff --git a/partmap/gpt.c b/grub-core/partmap/gpt.c similarity index 68% rename from partmap/gpt.c rename to grub-core/partmap/gpt.c index 0dd670cce..7f2c36143 100644 --- a/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -32,6 +32,10 @@ static grub_uint8_t grub_gpt_magic[8] = static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY; +#ifdef GRUB_UTIL +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#endif + /* 512 << 7 = 65536 byte sectors. */ #define MAX_SECTOR_LOG 7 @@ -97,6 +101,7 @@ gpt_partition_map_iterate (grub_disk_t disk, part.number = i; part.index = last_offset; part.partmap = &grub_gpt_partition_map; + part.parent = disk->partition; grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i, (unsigned long long) part.start, @@ -117,12 +122,77 @@ gpt_partition_map_iterate (grub_disk_t disk, return GRUB_ERR_NONE; } +#ifdef GRUB_UTIL +static grub_err_t +gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + grub_disk_addr_t start = 0, len = 0; + unsigned i; + grub_err_t err; + + auto int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) + { + struct grub_gpt_partentry gptdata; + + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + return 0; + + /* If there's an embed region, it is in a dedicated partition. */ + if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) + { + start = p->start; + len = p->len; + return 1; + } + + return 0; + } + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "GPT curently supports only PC-BIOS embedding"); + + err = gpt_partition_map_iterate (disk, find_usable_region); + if (err) + return err; + + if (len == 0) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This GPT partition label has no BIOS Boot Partition;" + " embedding won't be possible!"); + + if (len < *nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your BIOS Boot Partition is too small;" + " embedding won't be possible!"); + + *nsectors = len; + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = start + i; + + return GRUB_ERR_NONE; +} +#endif + /* Partition map type. */ static struct grub_partition_map grub_gpt_partition_map = { .name = "gpt", .iterate = gpt_partition_map_iterate, +#ifdef GRUB_UTIL + .embed = gpt_partition_map_embed +#endif }; GRUB_MOD_INIT(part_gpt) diff --git a/partmap/msdos.c b/grub-core/partmap/msdos.c similarity index 50% rename from partmap/msdos.c rename to grub-core/partmap/msdos.c index 3898d09fa..f99e27a6e 100644 --- a/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -27,16 +27,25 @@ static struct grub_partition_map grub_msdos_partition_map; -static grub_err_t -pc_partition_map_iterate (grub_disk_t disk, - int (*hook) (grub_disk_t disk, - const grub_partition_t partition)) +grub_err_t +grub_partition_msdos_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) { struct grub_partition p; struct grub_msdos_partition_mbr mbr; int labeln = 0; grub_disk_addr_t lastaddr; grub_disk_addr_t ext_offset; + grub_disk_addr_t delta = 0; + + if (disk->partition && disk->partition->partmap == &grub_msdos_partition_map) + { + if (disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_LINUX_MINIX) + delta = disk->partition->start; + else + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported"); + } p.offset = 0; ext_offset = 0; @@ -81,8 +90,9 @@ pc_partition_map_iterate (grub_disk_t disk, { e = mbr.entries + p.index; - p.start = p.offset + grub_le_to_cpu32 (e->start); + p.start = p.offset + grub_le_to_cpu32 (e->start) - delta; p.len = grub_le_to_cpu32 (e->length); + p.msdostype = e->type; grub_dprintf ("partition", "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n", @@ -133,12 +143,132 @@ pc_partition_map_iterate (grub_disk_t disk, return grub_errno; } +#ifdef GRUB_UTIL +static grub_err_t +pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + grub_disk_addr_t end = ~0ULL; + struct grub_msdos_partition_mbr mbr; + int labeln = 0; + /* Any value different than `p.offset' will satisfy the check during + first loop. */ + grub_disk_addr_t lastaddr = 1; + grub_disk_addr_t ext_offset = 0; + grub_disk_addr_t offset = 0; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "PC-style partitions curently support " + "only PC-BIOS embedding"); + + if (disk->partition) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Embedding on MSDOS subpartition isn't supported"); + + while (1) + { + int i; + struct grub_msdos_partition_entry *e; + grub_err_t err; + + /* Read the MBR. */ + err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr); + if (err) + return err; + + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = offset; + + /* Check if it is valid. */ + if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) + if (mbr.entries[i].flag & 0x7f) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag"); + + /* Analyze DOS partitions. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (!grub_msdos_partition_is_empty (e->type) + && end > offset + grub_le_to_cpu32 (e->start)) + end = offset + grub_le_to_cpu32 (e->start); + + /* If this is a GPT partition, this MBR is just a dummy. */ + if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr"); + } + + /* Find an extended partition. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (grub_msdos_partition_is_extended (e->type)) + { + offset = ext_offset + grub_le_to_cpu32 (e->start); + if (! ext_offset) + ext_offset = offset; + + break; + } + } + + /* If no extended partition, the end. */ + if (i == 4) + break; + } + + if (end >= *nsectors + 1) + { + int i; + *nsectors = end - 1; + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = 1 + i; + return GRUB_ERR_NONE; + } + + if (end <= 1) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This msdos-style partition label has no " + "post-MBR gap; embedding won't be possible!"); + + if (*nsectors > 62) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your core.img is unusually large. " + "It won't fit in the embedding area."); + + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your embedding area is unusually small. " + "core.img won't fit in it."); +} +#endif + /* Partition map type. */ static struct grub_partition_map grub_msdos_partition_map = { .name = "msdos", - .iterate = pc_partition_map_iterate, + .iterate = grub_partition_msdos_iterate, +#ifdef GRUB_UTIL + .embed = pc_partition_map_embed +#endif }; GRUB_MOD_INIT(part_msdos) diff --git a/partmap/sun.c b/grub-core/partmap/sun.c similarity index 87% rename from partmap/sun.c rename to grub-core/partmap/sun.c index 7a7eaef27..7af95c939 100644 --- a/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -87,36 +87,23 @@ sun_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { - grub_partition_t p; + struct grub_partition p; struct grub_sun_block block; int partnum; grub_err_t err; - p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); - if (! p) - return grub_errno; - - p->partmap = &grub_sun_partition_map; + p.partmap = &grub_sun_partition_map; err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block), &block); if (err) - { - grub_free (p); - return err; - } + return err; if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) - { - grub_free (p); - return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); - } + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); if (! grub_sun_is_valid (&block)) - { - grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); - } - + /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) @@ -128,20 +115,18 @@ sun_partition_map_iterate (grub_disk_t disk, continue; desc = &block.partitions[partnum]; - p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) + p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) * grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.nsect)); - p->len = grub_be_to_cpu32 (desc->num_sectors); - p->number = p->index = partnum; - if (p->len) + p.len = grub_be_to_cpu32 (desc->num_sectors); + p.number = p.index = partnum; + if (p.len) { - if (hook (disk, p)) + if (hook (disk, &p)) partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } - grub_free (p); - return grub_errno; } diff --git a/partmap/sunpc.c b/grub-core/partmap/sunpc.c similarity index 100% rename from partmap/sunpc.c rename to grub-core/partmap/sunpc.c diff --git a/parttool/msdospart.c b/grub-core/parttool/msdospart.c similarity index 100% rename from parttool/msdospart.c rename to grub-core/parttool/msdospart.c diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c new file mode 100644 index 000000000..50f810fcf --- /dev/null +++ b/grub-core/script/argv.c @@ -0,0 +1,154 @@ +/* argv.c - methods for constructing argument vector */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include +#include +#include + +/* Return nearest power of two that is >= v. */ +static unsigned +round_up_exp (unsigned v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + if (sizeof (v) > 4) + v |= v >> 32; + + v++; + v += (v == 0); + + return v; +} + +void +grub_script_argv_free (struct grub_script_argv *argv) +{ + unsigned i; + + if (argv->args) + { + for (i = 0; i < argv->argc; i++) + grub_free (argv->args[i]); + + grub_free (argv->args); + } + + argv->argc = 0; + argv->args = 0; + argv->script = 0; +} + +/* Make argv from argc, args pair. */ +int +grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args) +{ + int i; + struct grub_script_argv r = { 0, 0, 0 }; + + for (i = 0; i < argc; i++) + if (grub_script_argv_next (&r) || grub_script_argv_append (&r, args[i])) + { + grub_script_argv_free (&r); + return 1; + } + *argv = r; + return 0; +} + +/* Prepare for next argc. */ +int +grub_script_argv_next (struct grub_script_argv *argv) +{ + char **p = argv->args; + + if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0) + return 0; + + p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); + if (! p) + return 1; + + argv->argc++; + argv->args = p; + + if (argv->argc == 1) + argv->args[0] = 0; + argv->args[argv->argc] = 0; + return 0; +} + +/* Append `s' to the last argument. */ +int +grub_script_argv_append (struct grub_script_argv *argv, const char *s) +{ + int a; + int b; + char *p = argv->args[argv->argc - 1]; + + if (! s) + return 0; + + a = p ? grub_strlen (p) : 0; + b = grub_strlen (s); + + p = grub_realloc (p, round_up_exp ((a + b + 1) * sizeof (char))); + if (! p) + return 1; + + grub_strcpy (p + a, s); + argv->args[argv->argc - 1] = p; + + return 0; +} + +/* Split `s' and append words as multiple arguments. */ +int +grub_script_argv_split_append (struct grub_script_argv *argv, char *s) +{ + char ch; + char *p; + int errors = 0; + + if (! s) + return 0; + + while (! errors && *s) + { + p = s; + while (*s && ! grub_isspace (*s)) + s++; + + ch = *s; + *s = '\0'; + errors += grub_script_argv_append (argv, p); + *s = ch; + + while (*s && grub_isspace (*s)) + s++; + + if (*s) + errors += grub_script_argv_next (argv); + } + return errors; +} diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c new file mode 100644 index 000000000..72d199760 --- /dev/null +++ b/grub-core/script/execute.c @@ -0,0 +1,783 @@ +/* execute.c -- Execute a GRUB script. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,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 + +/* Max digits for a char is 3 (0xFF is 255), similarly for an int it + is sizeof (int) * 3, and one extra for a possible -ve sign. */ +#define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1) + +static unsigned long is_continue; +static unsigned long active_loops; +static unsigned long active_breaks; +static unsigned long function_return; + +#define GRUB_SCRIPT_SCOPE_MALLOCED 1 +#define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2 + +/* Scope for grub script functions. */ +struct grub_script_scope +{ + unsigned flags; + unsigned shifts; + struct grub_script_argv argv; +}; +static struct grub_script_scope *scope = 0; + +/* Wildcard translator for GRUB script. */ +struct grub_script_wildcard_translator *grub_wildcard_translator; + +static void +replace_scope (struct grub_script_scope *new_scope) +{ + if (scope) + { + scope->argv.argc += scope->shifts; + scope->argv.args -= scope->shifts; + + if (scope->flags & GRUB_SCRIPT_SCOPE_ARGS_MALLOCED) + grub_script_argv_free (&scope->argv); + + if (scope->flags & GRUB_SCRIPT_SCOPE_MALLOCED) + grub_free (scope); + } + scope = new_scope; +} + +grub_err_t +grub_script_break (grub_command_t cmd, int argc, char *argv[]) +{ + char *p = 0; + unsigned long count; + + if (argc == 0) + count = 1; + + else if ((argc > 1) || (count = grub_strtoul (argv[0], &p, 10)) == 0 || + (*p != '\0')) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad break"); + + is_continue = grub_strcmp (cmd->name, "break") ? 1 : 0; + active_breaks = grub_min (active_loops, count); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_script_shift (grub_command_t cmd __attribute__((unused)), + int argc, char *argv[]) +{ + char *p = 0; + unsigned long n = 0; + + if (! scope) + return GRUB_ERR_NONE; + + if (argc == 0) + n = 1; + + else if (argc > 1) + return GRUB_ERR_BAD_ARGUMENT; + + else + { + n = grub_strtoul (argv[0], &p, 10); + if (*p != '\0') + return GRUB_ERR_BAD_ARGUMENT; + } + + if (n > scope->argv.argc) + return GRUB_ERR_BAD_ARGUMENT; + + scope->shifts += n; + scope->argv.argc -= n; + scope->argv.args += n; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_script_setparams (grub_command_t cmd __attribute__((unused)), + int argc, char **args) +{ + struct grub_script_scope *new_scope; + struct grub_script_argv argv = { 0, 0, 0 }; + + if (! scope) + return GRUB_ERR_INVALID_COMMAND; + + new_scope = grub_malloc (sizeof (*new_scope)); + if (! new_scope) + return grub_errno; + + if (grub_script_argv_make (&argv, argc, args)) + { + grub_free (new_scope); + return grub_errno; + } + + new_scope->shifts = 0; + new_scope->argv = argv; + new_scope->flags = GRUB_SCRIPT_SCOPE_MALLOCED | + GRUB_SCRIPT_SCOPE_ARGS_MALLOCED; + + replace_scope (new_scope); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_script_return (grub_command_t cmd __attribute__((unused)), + int argc, char *argv[]) +{ + char *p; + unsigned long n; + + if (! scope || argc > 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in function scope"); + + if (argc == 0) + { + function_return = 1; + return grub_strtoul (grub_env_get ("?"), NULL, 10); + } + + n = grub_strtoul (argv[0], &p, 10); + if (*p != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad argument"); + + function_return = 1; + return n ? grub_error (GRUB_ERR_TEST_FAILURE, "false") : GRUB_ERR_NONE; +} + +static int +grub_env_special (const char *name) +{ + if (grub_isdigit (name[0]) || + grub_strcmp (name, "#") == 0 || + grub_strcmp (name, "*") == 0 || + grub_strcmp (name, "@") == 0) + return 1; + return 0; +} + +static char ** +grub_script_env_get (const char *name, grub_script_arg_type_t type) +{ + unsigned i; + struct grub_script_argv result = { 0, 0, 0 }; + + if (grub_script_argv_next (&result)) + goto fail; + + if (! grub_env_special (name)) + { + char *v = grub_env_get (name); + if (v && v[0]) + { + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_split_append (&result, v)) + goto fail; + } + else + if (grub_script_argv_append (&result, v)) + goto fail; + } + } + else if (! scope) + { + if (grub_script_argv_append (&result, 0)) + goto fail; + } + else if (grub_strcmp (name, "#") == 0) + { + char buffer[ERRNO_DIGITS_MAX + 1]; + grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc); + if (grub_script_argv_append (&result, buffer)) + goto fail; + } + else if (grub_strcmp (name, "*") == 0) + { + for (i = 0; i < scope->argv.argc; i++) + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (i != 0 && grub_script_argv_next (&result)) + goto fail; + + if (grub_script_argv_split_append (&result, scope->argv.args[i])) + goto fail; + } + else + { + if (i != 0 && grub_script_argv_append (&result, " ")) + goto fail; + + if (grub_script_argv_append (&result, scope->argv.args[i])) + goto fail; + } + } + else if (grub_strcmp (name, "@") == 0) + { + for (i = 0; i < scope->argv.argc; i++) + { + if (i != 0 && grub_script_argv_next (&result)) + goto fail; + + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_split_append (&result, scope->argv.args[i])) + goto fail; + } + else + if (grub_script_argv_append (&result, scope->argv.args[i])) + goto fail; + } + } + else + { + unsigned long num = grub_strtoul (name, 0, 10); + if (num == 0) + ; /* XXX no file name, for now. */ + + else if (num <= scope->argv.argc) + { + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_split_append (&result, + scope->argv.args[num - 1])) + goto fail; + } + else + if (grub_script_argv_append (&result, scope->argv.args[num - 1])) + goto fail; + } + } + + return result.args; + + fail: + + grub_script_argv_free (&result); + return 0; +} + +static grub_err_t +grub_script_env_set (const char *name, const char *val) +{ + if (grub_env_special (name)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variable name"); + + return grub_env_set (name, val); +} + +/* Convert arguments in ARGLIST into ARGV form. */ +static int +grub_script_arglist_to_argv (struct grub_script_arglist *arglist, + struct grub_script_argv *argv) +{ + int i; + char **values = 0; + struct grub_script_arg *arg = 0; + struct grub_script_argv result = { 0, 0, 0 }; + + auto int append (char *s, int escape_type); + int append (char *s, int escape_type) + { + int r; + char *p = 0; + + if (! grub_wildcard_translator || escape_type == 0) + return grub_script_argv_append (&result, s); + + if (escape_type > 0) + p = grub_wildcard_translator->escape (s); + else if (escape_type < 0) + p = grub_wildcard_translator->unescape (s); + + if (! p) + return 1; + + r = grub_script_argv_append (&result, p); + grub_free (p); + return r; + } + + for (; arglist && arglist->arg; arglist = arglist->next) + { + if (grub_script_argv_next (&result)) + goto fail; + + arg = arglist->arg; + while (arg) + { + switch (arg->type) + { + case GRUB_SCRIPT_ARG_TYPE_VAR: + case GRUB_SCRIPT_ARG_TYPE_DQVAR: + values = grub_script_env_get (arg->str, arg->type); + for (i = 0; values && values[i]; i++) + { + if (i != 0 && grub_script_argv_next (&result)) + goto fail; + + if (arg->type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_append (&result, values[i])) + goto fail; + } + else + { + if (append (values[i], 1)) + goto fail; + } + + grub_free (values[i]); + } + grub_free (values); + break; + + case GRUB_SCRIPT_ARG_TYPE_BLOCK: + if (grub_script_argv_append (&result, "{") || + grub_script_argv_append (&result, arg->str) || + grub_script_argv_append (&result, "}")) + goto fail; + result.script = arg->script; + break; + + case GRUB_SCRIPT_ARG_TYPE_TEXT: + if (grub_strlen (arg->str) && + grub_script_argv_append (&result, arg->str)) + goto fail; + break; + + case GRUB_SCRIPT_ARG_TYPE_DQSTR: + case GRUB_SCRIPT_ARG_TYPE_SQSTR: + if (append (arg->str, 1)) + goto fail; + break; + } + arg = arg->next; + } + } + + if (! result.args[result.argc - 1]) + result.argc--; + + /* Perform wildcard expansion. */ + + if (grub_wildcard_translator) + { + int j; + int failed = 0; + char **expansions = 0; + struct grub_script_argv unexpanded = result; + + result.argc = 0; + result.args = 0; + for (i = 0; unexpanded.args[i]; i++) + { + if (grub_wildcard_translator->expand (unexpanded.args[i], + &expansions)) + { + grub_script_argv_free (&unexpanded); + goto fail; + } + + if (! expansions) + { + grub_script_argv_next (&result); + append (unexpanded.args[i], -1); + } + else + { + for (j = 0; expansions[j]; j++) + { + failed = (failed || grub_script_argv_next (&result) || + append (expansions[j], -1)); + grub_free (expansions[j]); + } + grub_free (expansions); + + if (failed) + { + grub_script_argv_free (&unexpanded); + goto fail; + } + } + } + grub_script_argv_free (&unexpanded); + } + + *argv = result; + return 0; + + fail: + + grub_script_argv_free (&result); + return 1; +} + +static grub_err_t +grub_script_execute_cmd (struct grub_script_cmd *cmd) +{ + int ret; + char errnobuf[ERRNO_DIGITS_MAX + 1]; + + if (cmd == 0) + return 0; + + ret = cmd->exec (cmd); + + grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); + grub_env_set ("?", errnobuf); + return ret; +} + +/* Execute a function call. */ +grub_err_t +grub_script_function_call (grub_script_function_t func, int argc, char **args) +{ + grub_err_t ret = 0; + unsigned long loops = active_loops; + struct grub_script_scope *old_scope; + struct grub_script_scope new_scope; + + active_loops = 0; + new_scope.flags = 0; + new_scope.shifts = 0; + new_scope.argv.argc = argc; + new_scope.argv.args = args; + + old_scope = scope; + scope = &new_scope; + + ret = grub_script_execute (func->func); + + function_return = 0; + active_loops = loops; + replace_scope (old_scope); /* free any scopes by setparams */ + return ret; +} + +/* Execute a source script. */ +grub_err_t +grub_script_execute_sourcecode (const char *source, int argc, char **args) +{ + grub_err_t ret = 0; + struct grub_script *parsed_script; + struct grub_script_scope new_scope; + struct grub_script_scope *old_scope; + + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line, int cont __attribute__ ((unused))) + { + const 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; + } + + new_scope.argv.argc = argc; + new_scope.argv.args = args; + new_scope.flags = 0; + + old_scope = scope; + scope = &new_scope; + + while (source) + { + char *line; + + getline (&line, 0); + parsed_script = grub_script_parse (line, getline); + if (! parsed_script) + { + ret = grub_errno; + break; + } + + ret = grub_script_execute (parsed_script); + grub_free (line); + } + + scope = old_scope; + return ret; +} + +/* Execute a single command line. */ +grub_err_t +grub_script_execute_cmdline (struct grub_script_cmd *cmd) +{ + struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd; + grub_command_t grubcmd; + grub_err_t ret = 0; + grub_script_function_t func = 0; + char errnobuf[18]; + char *cmdname; + int argc; + char **args; + int invert; + struct grub_script_argv argv = { 0, 0, 0 }; + + /* Lookup the command. */ + if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0]) + return grub_errno; + + invert = 0; + argc = argv.argc - 1; + args = argv.args + 1; + cmdname = argv.args[0]; + if (grub_strcmp (cmdname, "!") == 0) + { + if (argv.argc < 2 || ! argv.args[1]) + { + grub_script_argv_free (&argv); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments"); + } + + invert = 1; + argc = argv.argc - 2; + args = argv.args + 2; + cmdname = argv.args[1]; + } + grubcmd = grub_command_find (cmdname); + if (! grubcmd) + { + grub_errno = GRUB_ERR_NONE; + + /* It's not a GRUB command, try all functions. */ + func = grub_script_function_find (cmdname); + if (! func) + { + /* As a last resort, try if it is an assignment. */ + char *assign = grub_strdup (cmdname); + char *eq = grub_strchr (assign, '='); + + if (eq) + { + /* This was set because the command was not found. */ + grub_errno = GRUB_ERR_NONE; + + /* Create two strings and set the variable. */ + *eq = '\0'; + eq++; + grub_script_env_set (assign, eq); + } + grub_free (assign); + + grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno); + grub_script_env_set ("?", errnobuf); + + grub_script_argv_free (&argv); + grub_print_error (); + + return 0; + } + } + + /* Execute the GRUB command or function. */ + if (grubcmd) + { + if (grub_extractor_level && !(grubcmd->flags + & GRUB_COMMAND_FLAG_EXTRACTOR)) + ret = grub_error (GRUB_ERR_EXTRACTOR, + "%s isn't allowed to execute in an extractor", + cmdname); + else if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) && + (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD)) + ret = grub_extcmd_dispatcher (grubcmd, argc, args, argv.script); + else + ret = (grubcmd->func) (grubcmd, argc, args); + } + else + ret = grub_script_function_call (func, argc, args); + + if (invert) + { + if (ret == GRUB_ERR_TEST_FAILURE) + grub_errno = ret = GRUB_ERR_NONE; + else if (ret == GRUB_ERR_NONE) + ret = grub_error (GRUB_ERR_TEST_FAILURE, "false"); + else + { + grub_print_error (); + ret = GRUB_ERR_NONE; + } + } + + /* Free arguments. */ + grub_script_argv_free (&argv); + + if (grub_errno == GRUB_ERR_TEST_FAILURE) + grub_errno = GRUB_ERR_NONE; + + grub_print_error (); + + grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); + grub_env_set ("?", errnobuf); + + return ret; +} + +/* Execute a block of one or more commands. */ +grub_err_t +grub_script_execute_cmdlist (struct grub_script_cmd *list) +{ + int ret = 0; + struct grub_script_cmd *cmd; + + /* Loop over every command and execute it. */ + for (cmd = list->next; cmd; cmd = cmd->next) + { + if (active_breaks) + break; + + ret = grub_script_execute_cmd (cmd); + + if (function_return) + break; + } + + return ret; +} + +/* Execute an if statement. */ +grub_err_t +grub_script_execute_cmdif (struct grub_script_cmd *cmd) +{ + int ret; + char *result; + struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd; + + /* Check if the commands results in a true or a false. The value is + read from the env variable `?'. */ + ret = grub_script_execute_cmd (cmdif->exec_to_evaluate); + if (function_return) + return ret; + + result = grub_env_get ("?"); + grub_errno = GRUB_ERR_NONE; + + /* Execute the `if' or the `else' part depending on the value of + `?'. */ + if (result && ! grub_strcmp (result, "0")) + return grub_script_execute_cmd (cmdif->exec_on_true); + else + return grub_script_execute_cmd (cmdif->exec_on_false); +} + +/* Execute a for statement. */ +grub_err_t +grub_script_execute_cmdfor (struct grub_script_cmd *cmd) +{ + unsigned i; + grub_err_t result; + struct grub_script_argv argv = { 0, 0, 0 }; + struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; + + if (grub_script_arglist_to_argv (cmdfor->words, &argv)) + return grub_errno; + + active_loops++; + result = 0; + for (i = 0; i < argv.argc; i++) + { + if (is_continue && active_breaks == 1) + active_breaks = 0; + + if (! active_breaks) + { + grub_script_env_set (cmdfor->name->str, argv.args[i]); + result = grub_script_execute_cmd (cmdfor->list); + if (function_return) + break; + } + } + + if (active_breaks) + active_breaks--; + + active_loops--; + grub_script_argv_free (&argv); + return result; +} + +/* Execute a "while" or "until" command. */ +grub_err_t +grub_script_execute_cmdwhile (struct grub_script_cmd *cmd) +{ + int result; + struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd; + + active_loops++; + do { + result = grub_script_execute_cmd (cmdwhile->cond); + if (function_return) + break; + + if (cmdwhile->until ? !result : result) + break; + + result = grub_script_execute_cmd (cmdwhile->list); + if (function_return) + break; + + if (active_breaks == 1 && is_continue) + active_breaks = 0; + + if (active_breaks) + break; + + } while (1); /* XXX Put a check for ^C here */ + + if (active_breaks) + active_breaks--; + + active_loops--; + return result; +} + +/* Execute any GRUB pre-parsed command or script. */ +grub_err_t +grub_script_execute (struct grub_script *script) +{ + if (script == 0) + return 0; + + return grub_script_execute_cmd (script->cmd); +} + diff --git a/script/function.c b/grub-core/script/function.c similarity index 91% rename from script/function.c rename to grub-core/script/function.c index 810c65233..47b236652 100644 --- a/script/function.c +++ b/grub-core/script/function.c @@ -103,12 +103,3 @@ grub_script_function_find (char *functionname) return func; } - -int -grub_script_function_call (grub_script_function_t func, - int argc __attribute__((unused)), - char **args __attribute__((unused))) -{ - /* XXX: Arguments are not supported yet. */ - return grub_script_execute (func->func); -} diff --git a/script/lexer.c b/grub-core/script/lexer.c similarity index 69% rename from script/lexer.c rename to grub-core/script/lexer.c index 42a570348..909b515fa 100644 --- a/script/lexer.c +++ b/grub-core/script/lexer.c @@ -17,6 +17,8 @@ * along with GRUB. If not, see . */ +#include + #include #include #include @@ -38,68 +40,57 @@ grub_script_lexer_deref (struct grub_lexer_param *state) } /* Start recording all characters passing through the lexer. */ -void +unsigned grub_script_lexer_record_start (struct grub_parser_param *parser) { struct grub_lexer_param *lexer = parser->lexerstate; - lexer->record = 1; - lexer->recordpos = 0; - if (lexer->recording) /* reuse last record */ - return; + lexer->record++; + if (lexer->recording) + return lexer->recordpos; + lexer->recordpos = 0; lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE; lexer->recording = grub_malloc (lexer->recordlen); if (!lexer->recording) { grub_script_yyerror (parser, 0); - lexer->record = 0; lexer->recordlen = 0; } + return lexer->recordpos; } char * -grub_script_lexer_record_stop (struct grub_parser_param *parser) +grub_script_lexer_record_stop (struct grub_parser_param *parser, unsigned offset) { - char *ptr; + int count; char *result; struct grub_lexer_param *lexer = parser->lexerstate; - auto char *compact (char *start, char *end); - char *compact (char *start, char *end) - { - /* Delete '{' and '}' characters and whitespaces. */ - while (*start && grub_isspace (*start)) start++; - if (*start == '{') start++; - while (*start && grub_isspace (*start)) start++; - - while (*end && grub_isspace (*end)) end--; - if (*end == '}') end--; - while (*end && grub_isspace (*end)) end--; - end[1] = '\0'; - - return start; - } - - if (!lexer->record || !lexer->recording) + if (!lexer->record) return 0; - /* XXX This is not necessary in BASH. */ + lexer->record--; + if (!lexer->recording) + return 0; - ptr = compact (lexer->recording, lexer->recording + lexer->recordpos - 1); - lexer->record = 0; - lexer->recordpos = 0; - - /* This memory would be freed by, grub_script_free. */ - result = grub_script_malloc (parser, grub_strlen (ptr) + 1); - if (result) - grub_strcpy (result, ptr); + count = lexer->recordpos - offset; + result = grub_script_malloc (parser, count + 1); + if (result) { + grub_strncpy (result, lexer->recording + offset, count); + result[count] = '\0'; + } + if (lexer->record == 0) + { + grub_free (lexer->recording); + lexer->recording = 0; + lexer->recordlen = 0; + lexer->recordpos = 0; + } return result; } -#define MAX(a,b) ((a) < (b) ? (b) : (a)) - /* Record STR if input recording is enabled. */ void grub_script_lexer_record (struct grub_parser_param *parser, char *str) @@ -108,21 +99,20 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) char *old; struct grub_lexer_param *lexer = parser->lexerstate; - if (!lexer->record) + if (!lexer->record || !lexer->recording) return; len = grub_strlen (str); if (lexer->recordpos + len + 1 > lexer->recordlen) { old = lexer->recording; - lexer->recordlen = MAX (len, lexer->recordlen) * 2; + lexer->recordlen = grub_max (len, lexer->recordlen) * 2; lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); if (!lexer->recording) { grub_free (old); - lexer->record = 0; lexer->recordpos = 0; - lexer->recordlen /= 2; + lexer->recordlen = 0; grub_script_yyerror (parser, 0); return; } @@ -131,85 +121,92 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) lexer->recordpos += len; } -/* Append '\n' to SRC, before '\0' */ -static char * -append_newline (const char *src) -{ - char *line; - grub_size_t len; - - len = grub_strlen (src); - line = grub_malloc (len + 2); - if (!line) - return 0; - - grub_strcpy (line, src); - - line[len] = '\n'; - line[len + 1] = '\0'; - return line; -} - /* Read next line of input if necessary, and set yyscanner buffers. */ int -grub_script_lexer_yywrap (struct grub_parser_param *parserstate) +grub_script_lexer_yywrap (struct grub_parser_param *parserstate, + const char *input) { int len; - char *line; - char *line2; + char *p = 0; + char *line = 0; YY_BUFFER_STATE buffer; struct grub_lexer_param *lexerstate = parserstate->lexerstate; - if (!lexerstate->refs) - return 0; + if (! lexerstate->refs && ! lexerstate->prefix && ! input) + return 1; - if (!lexerstate->getline) + if (! lexerstate->getline && ! input) { grub_script_yyerror (parserstate, "unexpected end of file"); - return 0; + return 1; } line = 0; - buffer = 0; - lexerstate->getline (&line, 1); - if (!line) - { - grub_script_yyerror (parserstate, 0); /* XXX this could be for ^C case? */ - return 0; - } - - len = grub_strlen (line); - if (line[len - 1] == '\n') - { - buffer = yy_scan_string (line, lexerstate->yyscanner); - } + if (! input) + lexerstate->getline (&line, 1); else + line = grub_strdup (input); + + /* Ensure '\n' at the end. */ + if (line && line[0] == '\0') { - line2 = append_newline (line); - if (line2) - { - buffer = yy_scan_string (line2, lexerstate->yyscanner); - grub_free (line2); - } + grub_free (line); + line = grub_strdup ("\n"); } + if (line && (len = grub_strlen(line)) && line[len - 1] != '\n') + { + p = grub_realloc (line, len + 2); + if (p) + { + p[len++] = '\n'; + p[len] = '\0'; + } + line = p; + } + + if (! line) + { + grub_script_yyerror (parserstate, "out of memory"); + return 1; + } + + /* Prepend any left over unput-text. */ + if (lexerstate->prefix) + { + int plen = grub_strlen (lexerstate->prefix); + + p = grub_malloc (len + plen + 1); + if (! p) + { + grub_free (line); + return 1; + } + grub_strcpy (p, lexerstate->prefix); + lexerstate->prefix = 0; + + grub_strcpy (p + plen, line); + grub_free (line); + + line = p; + len = len + plen; + } + + buffer = yy_scan_string (line, lexerstate->yyscanner); grub_free (line); - if (!buffer) + + if (! buffer) { grub_script_yyerror (parserstate, 0); - return 0; + return 1; } - - return 1; + return 0; } struct grub_lexer_param * grub_script_lexer_init (struct grub_parser_param *parser, char *script, grub_reader_getline_t getline) { - int len; - char *script2; - YY_BUFFER_STATE buffer; struct grub_lexer_param *lexerstate; lexerstate = grub_zalloc (sizeof (*lexerstate)); @@ -232,34 +229,18 @@ grub_script_lexer_init (struct grub_parser_param *parser, char *script, return 0; } - buffer = 0; - script = script ? : "\n"; - len = grub_strlen (script); + yyset_extra (parser, lexerstate->yyscanner); + parser->lexerstate = lexerstate; - if (script[len - 1] == '\n') - { - buffer = yy_scan_string (script, lexerstate->yyscanner); - } - else - { - script2 = append_newline (script); - if (script2) - { - buffer = yy_scan_string (script2, lexerstate->yyscanner); - grub_free (script2); - } - } - - if (!buffer) + if (grub_script_lexer_yywrap (parser, script ?: "\n")) { + parser->lexerstate = 0; yylex_destroy (lexerstate->yyscanner); grub_free (lexerstate->yyscanner); - grub_free (lexerstate->text); grub_free (lexerstate); return 0; } - yyset_extra (parser, lexerstate->yyscanner); return lexerstate; } diff --git a/grub-core/script/main.c b/grub-core/script/main.c new file mode 100644 index 000000000..482bb3fef --- /dev/null +++ b/grub-core/script/main.c @@ -0,0 +1,88 @@ +/* + * 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 + +grub_err_t +grub_normal_parse_line (char *line, grub_reader_getline_t getline) +{ + struct grub_script *parsed_script; + + /* Parse the script. */ + parsed_script = grub_script_parse (line, getline); + + if (parsed_script) + { + /* Execute the command(s). */ + grub_script_execute (parsed_script); + + /* The parsed script was executed, throw it away. */ + grub_script_unref (parsed_script); + } + + return grub_errno; +} + +static grub_command_t cmd_break; +static grub_command_t cmd_continue; +static grub_command_t cmd_shift; +static grub_command_t cmd_setparams; +static grub_command_t cmd_return; + +void +grub_script_init (void) +{ + cmd_break = grub_register_command ("break", grub_script_break, + N_("[n]"), N_("Exit from loops")); + cmd_continue = grub_register_command ("continue", grub_script_break, + N_("[n]"), N_("Continue loops")); + cmd_shift = grub_register_command ("shift", grub_script_shift, + N_("[n]"), N_("Shift positional parameters.")); + cmd_setparams = grub_register_command ("setparams", grub_script_setparams, + N_("[VALUE]..."), + N_("Set positional parameters.")); + cmd_return = grub_register_command ("return", grub_script_return, + N_("[n]"), N_("Return from a function.")); +} + +void +grub_script_fini (void) +{ + if (cmd_break) + grub_unregister_command (cmd_break); + cmd_break = 0; + + if (cmd_continue) + grub_unregister_command (cmd_continue); + cmd_continue = 0; + + if (cmd_shift) + grub_unregister_command (cmd_shift); + cmd_shift = 0; + + if (cmd_setparams) + grub_unregister_command (cmd_setparams); + cmd_setparams = 0; + + if (cmd_return) + grub_unregister_command (cmd_return); + cmd_return = 0; +} diff --git a/script/parser.y b/grub-core/script/parser.y similarity index 69% rename from script/parser.y rename to grub-core/script/parser.y index e85ba624d..88c7fe9e3 100644 --- a/script/parser.y +++ b/grub-core/script/parser.y @@ -20,6 +20,7 @@ %{ #include #include +#include #define YYFREE grub_free #define YYMALLOC grub_malloc @@ -34,6 +35,11 @@ struct grub_script_arglist *arglist; struct grub_script_arg *arg; char *string; + struct { + unsigned offset; + struct grub_script_mem *memory; + struct grub_script *scripts; + }; } %token GRUB_PARSER_TOKEN_BAD @@ -70,15 +76,15 @@ %token GRUB_PARSER_TOKEN_WHILE "while" %token GRUB_PARSER_TOKEN_TIME "time" %token GRUB_PARSER_TOKEN_FUNCTION "function" -%token GRUB_PARSER_TOKEN_MENUENTRY "menuentry" %token GRUB_PARSER_TOKEN_NAME "name" %token GRUB_PARSER_TOKEN_WORD "word" +%type block block0 %type word argument arguments0 arguments1 %type script_init script %type grubcmd ifclause ifcmd forcmd whilecmd untilcmd -%type command commands1 menuentry statement +%type command commands1 statement %pure-parser %lex-param { struct grub_parser_param *state }; @@ -97,9 +103,7 @@ script: newlines0 } | script statement delimiter newlines0 { - struct grub_script_cmdblock *cmdblock; - cmdblock = (struct grub_script_cmdblock *) $1; - $$ = grub_script_add_cmd (state, cmdblock, $2); + $$ = grub_script_append_cmd (state, $1, $2); } | error { @@ -126,7 +130,6 @@ word: GRUB_PARSER_TOKEN_NAME { $$ = grub_script_add_arglist (state, 0, $1); } statement: command { $$ = $1; } | function { $$ = 0; } - | menuentry { $$ = $1; } ; argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); } @@ -144,10 +147,77 @@ argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); } | "until" { $$ = grub_script_add_arglist (state, 0, $1); } | "while" { $$ = grub_script_add_arglist (state, 0, $1); } | "function" { $$ = grub_script_add_arglist (state, 0, $1); } - | "menuentry" { $$ = grub_script_add_arglist (state, 0, $1); } | word { $$ = $1; } ; +/* + Block parameter is passed to commands in two forms: as unparsed + string and as pre-parsed grub_script object. Passing as grub_script + object makes memory management difficult, because: + + (1) Command may want to keep a reference to grub_script objects for + later use, so script framework may not free the grub_script + object after command completes. + + (2) Command may get called multiple times with same grub_script + object under loops, so we should not let command implementation + to free the grub_script object. + + To solve above problems, we rely on reference counting for + grub_script objects. Commands that want to keep the grub_script + object must take a reference to it. + + Other complexity comes with arbitrary nesting of grub_script + objects: a grub_script object may have commands with several block + parameters, and each block parameter may further contain multiple + block parameters nested. We use temporary variable, state->scripts + to collect nested child scripts (that are linked by siblings and + children members), and will build grub_scripts tree from bottom. + */ +block: "{" + { + grub_script_lexer_ref (state->lexerstate); + $$ = grub_script_lexer_record_start (state); + $$ = grub_script_mem_record (state); + + /* save currently known scripts. */ + $$ = state->scripts; + state->scripts = 0; + } + commands1 delimiters0 "}" + { + char *p; + struct grub_script_mem *memory; + struct grub_script *s = $2; + + memory = grub_script_mem_record_stop (state, $2); + if ((p = grub_script_lexer_record_stop (state, $2))) + *grub_strrchr (p, '}') = '\0'; + + $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p); + if (! $$ || ! ($$->script = grub_script_create ($3, memory))) + grub_script_mem_free (memory); + + else { + /* attach nested scripts to $$->script as children */ + $$->script->children = state->scripts; + + /* restore old scripts; append $$->script to siblings. */ + state->scripts = $2 ?: $$->script; + if (s) { + while (s->next_siblings) + s = s->next_siblings; + s->next_siblings = $$->script; + } + } + + grub_script_lexer_deref (state->lexerstate); + } +; +block0: /* Empty */ { $$ = 0; } + | block { $$ = $1; } +; + arguments0: /* Empty */ { $$ = 0; } | arguments1 { $$ = $1; } ; @@ -163,12 +233,17 @@ arguments1: argument arguments0 } ; -grubcmd: word arguments0 +grubcmd: word arguments0 block0 { - if ($1 && $2) { - $1->next = $2; - $1->argcount += $2->argcount; - $2->argcount = 0; + struct grub_script_arglist *x = $2; + + if ($3) + x = grub_script_add_arglist (state, $2, $3); + + if ($1 && x) { + $1->next = x; + $1->argcount += x->argcount; + x->argcount = 0; } $$ = grub_script_create_cmdline (state, $1); } @@ -185,20 +260,21 @@ command: grubcmd { $$ = $1; } /* A list of commands. */ commands1: newlines0 command { - $$ = grub_script_add_cmd (state, 0, $2); + $$ = grub_script_append_cmd (state, 0, $2); } | commands1 delimiters1 command { - struct grub_script_cmdblock *cmdblock; - cmdblock = (struct grub_script_cmdblock *) $1; - $$ = grub_script_add_cmd (state, cmdblock, $3); + $$ = grub_script_append_cmd (state, $1, $3); } ; -function: "function" "name" +function: "function" "name" { grub_script_lexer_ref (state->lexerstate); state->func_mem = grub_script_mem_record (state); + + $$ = state->scripts; + state->scripts = 0; } delimiters0 "{" commands1 delimiters1 "}" { @@ -206,30 +282,18 @@ function: "function" "name" state->func_mem = grub_script_mem_record_stop (state, state->func_mem); script = grub_script_create ($6, state->func_mem); - if (script) - grub_script_function_create ($2, script); + if (! script) + grub_script_mem_free (state->func_mem); + else { + script->children = state->scripts; + grub_script_function_create ($2, script); + } + state->scripts = $3; grub_script_lexer_deref (state->lexerstate); } ; -menuentry: "menuentry" - { - grub_script_lexer_ref (state->lexerstate); - } - arguments1 - { - grub_script_lexer_record_start (state); - } - delimiters0 "{" commands1 delimiters1 "}" - { - char *menu_entry; - menu_entry = grub_script_lexer_record_stop (state); - grub_script_lexer_deref (state->lexerstate); - $$ = grub_script_create_cmdmenu (state, $3, menu_entry, 0); - } -; - ifcmd: "if" { grub_script_lexer_ref (state->lexerstate); diff --git a/script/script.c b/grub-core/script/script.c similarity index 83% rename from script/script.c rename to grub-core/script/script.c index 4c87d9491..ad3018357 100644 --- a/script/script.c +++ b/grub-core/script/script.c @@ -54,7 +54,7 @@ grub_script_malloc (struct grub_parser_param *state, grub_size_t size) } /* Free all memory described by MEM. */ -static void +void grub_script_mem_free (struct grub_script_mem *mem) { struct grub_script_mem *memfree; @@ -94,9 +94,21 @@ grub_script_mem_record_stop (struct grub_parser_param *state, void grub_script_free (struct grub_script *script) { - if (!script) + struct grub_script *s; + struct grub_script *t; + + if (! script) return; - grub_script_mem_free (script->mem); + + if (script->mem) + grub_script_mem_free (script->mem); + + s = script->children; + while (s) { + t = s->next_siblings; + grub_script_unref (s); + s = t; + } grub_free (script); } @@ -119,6 +131,8 @@ grub_script_arg_add (struct grub_parser_param *state, return arg; argpart->type = type; + argpart->script = 0; + len = grub_strlen (str) + 1; argpart->str = grub_script_malloc (state, len); if (!argpart->str) @@ -267,70 +281,40 @@ grub_script_create_cmdwhile (struct grub_parser_param *state, return (struct grub_script_cmd *) cmd; } -/* Create a command that adds a menu entry to the menu. Title is an - argument that is parsed to generate a string that can be used as - the title. The sourcecode for this entry is passed in SOURCECODE. - The options for this entry are passed in OPTIONS. */ +/* Create a chain of commands. LAST contains the command that should + be added at the end of LIST's list. If LIST is zero, a new list + will be created. */ struct grub_script_cmd * -grub_script_create_cmdmenu (struct grub_parser_param *state, - struct grub_script_arglist *arglist, - char *sourcecode, int options) -{ - struct grub_script_cmd_menuentry *cmd; - - cmd = grub_script_malloc (state, sizeof (*cmd)); - if (!cmd) - return 0; - - cmd->cmd.exec = grub_script_execute_menuentry; - cmd->cmd.next = 0; - cmd->sourcecode = sourcecode; - cmd->arglist = arglist; - cmd->options = options; - - return (struct grub_script_cmd *) cmd; -} - -/* Create a block of commands. CMD contains the command that should - be added at the end of CMDBLOCK's list. If CMDBLOCK is zero, a new - cmdblock will be created. */ -struct grub_script_cmd * -grub_script_add_cmd (struct grub_parser_param *state, - struct grub_script_cmdblock *cmdblock, - struct grub_script_cmd *cmd) +grub_script_append_cmd (struct grub_parser_param *state, + struct grub_script_cmd *list, + struct grub_script_cmd *last) { struct grub_script_cmd *ptr; - grub_dprintf ("scripting", "cmdblock\n"); + grub_dprintf ("scripting", "append command\n"); - if (!cmd) - return (struct grub_script_cmd *) cmdblock; + if (! last) + return list; - if (!cmdblock) + if (! list) { - cmdblock = grub_script_malloc (state, sizeof (*cmdblock)); - if (!cmdblock) + list = grub_script_malloc (state, sizeof (*list)); + if (! list) return 0; - cmdblock->cmd.exec = grub_script_execute_cmdblock; - cmdblock->cmd.next = 0; - cmdblock->cmdlist = cmd; - cmd->next = 0; + list->exec = grub_script_execute_cmdlist; + list->next = last; } else { - if (!cmdblock->cmdlist) - cmdblock->cmdlist = cmd; - else - { - ptr = cmdblock->cmdlist; - while (ptr->next) - ptr = ptr->next; - ptr->next = cmd; - } + ptr = list; + while (ptr->next) + ptr = ptr->next; + + ptr->next = last; } - return (struct grub_script_cmd *) cmdblock; + return list; } @@ -341,16 +325,14 @@ grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem) struct grub_script *parsed; parsed = grub_malloc (sizeof (*parsed)); - if (!parsed) - { - grub_script_mem_free (mem); - grub_free (cmd); - - return 0; - } + if (! parsed) + return 0; parsed->mem = mem; parsed->cmd = cmd; + parsed->refcnt = 0; + parsed->children = 0; + parsed->next_siblings = 0; return parsed; } @@ -365,13 +347,16 @@ grub_script_parse (char *script, grub_reader_getline_t getline) struct grub_lexer_param *lexstate; struct grub_parser_param *parsestate; - parsed = grub_malloc (sizeof (*parsed)); + parsed = grub_script_create (0, 0); if (!parsed) return 0; parsestate = grub_zalloc (sizeof (*parsestate)); if (!parsestate) - return 0; + { + grub_free (parsed); + return 0; + } /* Initialize the lexer. */ lexstate = grub_script_lexer_init (parsestate, script, getline); @@ -394,11 +379,13 @@ grub_script_parse (char *script, grub_reader_getline_t getline) grub_script_mem_free (memfree); grub_script_lexer_fini (lexstate); grub_free (parsestate); + grub_free (parsed); return 0; } parsed->mem = grub_script_mem_record_stop (parsestate, membackup); parsed->cmd = parsestate->parsed; + parsed->children = parsestate->scripts; grub_script_lexer_fini (lexstate); grub_free (parsestate); diff --git a/script/yylex.l b/grub-core/script/yylex.l similarity index 80% rename from script/yylex.l rename to grub-core/script/yylex.l index e9659832b..53ae4c54f 100644 --- a/script/yylex.l +++ b/grub-core/script/yylex.l @@ -58,6 +58,9 @@ #define YY_INPUT(buf,res,max) do { res = 0; } while (0) /* forward declarations */ +static int grub_lexer_unput (const char *input, yyscan_t yyscanner); +static int grub_lexer_resplit (const char *input, yyscan_t yyscanner); + static void grub_lexer_yyfree (void *, yyscan_t yyscanner); static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner); static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner); @@ -68,6 +71,8 @@ static void copy_string (struct grub_parser_param *, const char *, %top{ +#include + #include typedef size_t yy_size_t; @@ -99,7 +104,7 @@ typedef size_t yy_size_t; %option never-interactive %option noyyfree noyyalloc noyyrealloc -%option nounistd nostdinit nodefault noyylineno noyywrap +%option nounistd nostdinit nodefault noyylineno /* Reduce lexer size, by not defining these. */ %option noyy_top_state @@ -118,12 +123,17 @@ CHAR [^{}|&$;<> \t\n\'\"\\] DIGITS [[:digit:]]+ NAME [[:alpha:]_][[:alnum:]_]* -ESC \\. -VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} -DQSTR \"([^\\\"]|{ESC})*\" -SQSTR \'[^\']*\' +ESC \\(.|\n) +SQCHR [^\'] +DQCHR {ESC}|[^\\\"] +DQSTR \"{DQCHR}*\" +SQSTR \'{SQCHR}*\' +SPECIAL \?|\#|\*|\@ +VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|${SPECIAL}|$\{{SPECIAL}\} WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ +MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n)) + %x SPLIT %x DQUOTE %x SQUOTE @@ -147,7 +157,6 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ ">" { RECORD; return GRUB_PARSER_TOKEN_GT; } /* Reserved words */ -"!" { RECORD; return GRUB_PARSER_TOKEN_NOT; } "{" { RECORD; return GRUB_PARSER_TOKEN_LBR; } "}" { RECORD; return GRUB_PARSER_TOKEN_RBR; } "[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; } @@ -168,36 +177,33 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ "until" { RECORD; return GRUB_PARSER_TOKEN_UNTIL; } "while" { RECORD; return GRUB_PARSER_TOKEN_WHILE; } "function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; } -"menuentry" { RECORD; return GRUB_PARSER_TOKEN_MENUENTRY; } + +{MULTILINE} { + if (grub_lexer_unput (yytext, yyscanner)) + return GRUB_PARSER_TOKEN_BAD; + } {NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; } {WORD} { RECORD; - /* resplit yytext */ - grub_dprintf ("lexer", "word: [%s]\n", yytext); - yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); - if (yy_scan_string (yytext, yyscanner)) - { - yyextra->lexerstate->merge_start = 1; - yy_push_state (SPLIT, yyscanner); - } - else - { - grub_script_yyerror (yyextra, 0); - yypop_buffer_state (yyscanner); - return GRUB_PARSER_TOKEN_WORD; - } + yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); + if (grub_lexer_resplit (yytext, yyscanner)) + { + yypop_buffer_state (yyscanner); + return GRUB_PARSER_TOKEN_WORD; + } + yyextra->lexerstate->resplit = 1; } - -.|\n { - grub_script_yyerror (yyextra, "unrecognized token"); - return GRUB_PARSER_TOKEN_BAD; +. { + grub_script_yyerror (yyextra, yytext); + return GRUB_PARSER_TOKEN_BAD; } /* Split word into multiple args */ { \\. { COPY (yytext + 1, yyleng - 1); } + \\\n { /* ignore */ } \" { yy_push_state (DQUOTE, yyscanner); ARG (GRUB_SCRIPT_ARG_TYPE_TEXT); @@ -215,13 +221,14 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ <> { yy_pop_state (yyscanner); yypop_buffer_state (yyscanner); + yyextra->lexerstate->resplit = 0; yyextra->lexerstate->merge_end = 1; ARG (GRUB_SCRIPT_ARG_TYPE_TEXT); } } { - \? | + {SPECIAL} | {DIGITS} | {NAME} { COPY (yytext, yyleng); @@ -231,7 +238,7 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ else ARG (GRUB_SCRIPT_ARG_TYPE_DQVAR); } - \{\?\} | + \{{SPECIAL}\} | \{{DIGITS}\} | \{{NAME}\} { yytext[yyleng - 1] = '\0'; @@ -272,15 +279,20 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ <> { yypop_buffer_state (yyscanner); - if (! grub_script_lexer_yywrap (yyextra)) - { - yyextra->lexerstate->eof = 1; - return GRUB_PARSER_TOKEN_EOF; - } + yyextra->lexerstate->eof = 1; + return GRUB_PARSER_TOKEN_EOF; } - %% +int +yywrap (yyscan_t yyscanner) +{ + if (yyget_extra (yyscanner)->lexerstate->resplit) + return 1; + + return grub_script_lexer_yywrap (yyget_extra (yyscanner), 0); +} + static void grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused))) { @@ -300,8 +312,6 @@ grub_lexer_yyrealloc (void *ptr, yy_size_t size, return grub_realloc (ptr, size); } -#define MAX(a,b) ((a) < (b) ? (b) : (a)) - static void copy_string (struct grub_parser_param *parser, const char *str, unsigned hint) { int size; @@ -311,7 +321,7 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi len = hint ? hint : grub_strlen (str); if (parser->lexerstate->used + len >= parser->lexerstate->size) { - size = MAX (len, parser->lexerstate->size) * 2; + size = grub_max (len, parser->lexerstate->size) * 2; ptr = grub_realloc (parser->lexerstate->text, size); if (!ptr) { @@ -325,3 +335,34 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi grub_strcpy (parser->lexerstate->text + parser->lexerstate->used - 1, str); parser->lexerstate->used += len; } + +static int +grub_lexer_resplit (const char *text, yyscan_t yyscanner) +{ + /* resplit text */ + if (yy_scan_string (text, yyscanner)) + { + yyget_extra (yyscanner)->lexerstate->merge_start = 1; + yy_push_state (SPLIT, yyscanner); + return 0; + } + grub_script_yyerror (yyget_extra (yyscanner), 0); + return 1; +} + +static int +grub_lexer_unput (const char *text, yyscan_t yyscanner) +{ + struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate; + + if (lexerstate->prefix) + grub_free (lexerstate->prefix); + + lexerstate->prefix = grub_strdup (text); + if (! lexerstate->prefix) + { + grub_script_yyerror (yyget_extra (yyscanner), "out of memory"); + return 1; + } + return 0; +} diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c new file mode 100644 index 000000000..5bc3f578c --- /dev/null +++ b/grub-core/term/at_keyboard.c @@ -0,0 +1,631 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + * 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 + +static short at_keyboard_status = 0; +static int e0_received = 0; +static int f0_received = 0; + +static grub_uint8_t led_status; + +#define KEYBOARD_LED_SCROLL (1 << 0) +#define KEYBOARD_LED_NUM (1 << 1) +#define KEYBOARD_LED_CAPS (1 << 2) + +static grub_uint8_t grub_keyboard_controller_orig; +static grub_uint8_t grub_keyboard_orig_set; +static grub_uint8_t current_set; + +static const grub_uint8_t set1_mapping[128] = + { + /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, + /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, + /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, + /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, + /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, + /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, + /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, + /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, + /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, + /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, + /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, + /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, + /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, + /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, + /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, + /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, + /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, + /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, + /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, + /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, + /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, + /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, + /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, + /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, + /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, + /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, + /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, + /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, + /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, + /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, + /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, + /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, + /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, + /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, + /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, + /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, + /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, + /* 0x54 */ 0, 0, + /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, + /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, + /* 0x5a */ 0, 0, + /* 0x5c */ 0, 0, + /* 0x5e */ 0, 0, + /* 0x60 */ 0, 0, + /* 0x62 */ 0, 0, + /* OLPC keys. Just mapped to normal keys. */ + /* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP, + /* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT, + /* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT + }; + +static const struct +{ + grub_uint8_t from, to; +} set1_e0_mapping[] = + { + {0x1c, GRUB_KEYBOARD_KEY_NUMENTER}, + {0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, + {0x35, GRUB_KEYBOARD_KEY_NUMSLASH }, + {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT}, + {0x47, GRUB_KEYBOARD_KEY_HOME}, + {0x48, GRUB_KEYBOARD_KEY_UP}, + {0x49, GRUB_KEYBOARD_KEY_NPAGE}, + {0x4b, GRUB_KEYBOARD_KEY_LEFT}, + {0x4d, GRUB_KEYBOARD_KEY_RIGHT}, + {0x4f, GRUB_KEYBOARD_KEY_END}, + {0x50, GRUB_KEYBOARD_KEY_DOWN}, + {0x51, GRUB_KEYBOARD_KEY_PPAGE}, + {0x52, GRUB_KEYBOARD_KEY_INSERT}, + {0x53, GRUB_KEYBOARD_KEY_DELETE}, + }; + +static const grub_uint8_t set2_mapping[256] = + { + /* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9, + /* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5, + /* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1, + /* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12, + /* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10, + /* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6, + /* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB, + /* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0, + /* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT, + /* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0, + /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q, + /* 0x16 */ GRUB_KEYBOARD_KEY_1, 0, + /* 0x18 */ 0, 0, + /* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S, + /* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W, + /* 0x1e */ GRUB_KEYBOARD_KEY_2, 0, + /* 0x20 */ 0, GRUB_KEYBOARD_KEY_C, + /* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D, + /* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4, + /* 0x26 */ GRUB_KEYBOARD_KEY_3, 0, + /* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE, + /* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F, + /* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R, + /* 0x2e */ GRUB_KEYBOARD_KEY_5, 0, + /* 0x30 */ 0, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H, + /* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y, + /* 0x36 */ GRUB_KEYBOARD_KEY_6, 0, + /* 0x38 */ 0, 0, + /* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J, + /* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7, + /* 0x3e */ GRUB_KEYBOARD_KEY_8, 0, + /* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA, + /* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I, + /* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0, + /* 0x46 */ GRUB_KEYBOARD_KEY_9, 0, + /* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT, + /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L, + /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P, + /* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0, + /* 0x50 */ 0, 0, + /* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0, + /* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x56 */ 0, 0, + /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT, + /* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x5e */ 0, 0, + /* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND, + /* 0x62 */ 0, 0, + /* 0x64 */ 0, 0, + /* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0, + /* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1, + /* 0x6a */ 0, GRUB_KEYBOARD_KEY_NUM4, + /* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, 0, + /* 0x6e */ 0, 0, + /* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0, + /* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5, + /* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8, + /* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS, + /* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS, + /* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9, + /* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0, + /* 0x80 */ 0, 0, + /* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7, + }; + +static const struct +{ + grub_uint8_t from, to; +} set2_e0_mapping[] = + { + {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT}, + {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, + {0x4a, GRUB_KEYBOARD_KEY_NUMSLASH}, + {0x5a, GRUB_KEYBOARD_KEY_NUMENTER}, + {0x69, GRUB_KEYBOARD_KEY_END}, + {0x6b, GRUB_KEYBOARD_KEY_LEFT}, + {0x6c, GRUB_KEYBOARD_KEY_HOME}, + {0x70, GRUB_KEYBOARD_KEY_INSERT}, + {0x71, GRUB_KEYBOARD_KEY_DELETE}, + {0x72, GRUB_KEYBOARD_KEY_DOWN}, + {0x74, GRUB_KEYBOARD_KEY_RIGHT}, + {0x75, GRUB_KEYBOARD_KEY_UP}, + {0x7a, GRUB_KEYBOARD_KEY_NPAGE}, + {0x7d, GRUB_KEYBOARD_KEY_PPAGE}, + }; + +static void +keyboard_controller_wait_until_ready (void) +{ + while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))); +} + +static grub_uint8_t +wait_ack (void) +{ + grub_uint64_t endtime; + grub_uint8_t ack; + + endtime = grub_get_time_ms () + 20; + do + ack = grub_inb (KEYBOARD_REG_DATA); + while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK + && grub_get_time_ms () < endtime); + return ack; +} + +static int +at_command (grub_uint8_t data) +{ + unsigned i; + for (i = 0; i < GRUB_AT_TRIES; i++) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); + grub_outb (data, KEYBOARD_REG_STATUS); + ack = wait_ack (); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) + break; + return 0; + } + return (i != GRUB_AT_TRIES); +} + +static void +grub_keyboard_controller_write (grub_uint8_t c) +{ + at_command (KEYBOARD_COMMAND_WRITE); + keyboard_controller_wait_until_ready (); + grub_outb (c, KEYBOARD_REG_DATA); +} + +#if !defined (GRUB_MACHINE_MIPS_YEELOONG) && !defined (GRUB_MACHINE_QEMU) + +static grub_uint8_t +grub_keyboard_controller_read (void) +{ + at_command (KEYBOARD_COMMAND_READ); + keyboard_controller_wait_until_ready (); + return grub_inb (KEYBOARD_REG_DATA); +} + +#endif + +static int +write_mode (int mode) +{ + unsigned i; + for (i = 0; i < GRUB_AT_TRIES; i++) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); + grub_outb (0xf0, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + grub_outb (mode, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + ack = wait_ack (); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) + break; + return 0; + } + + return (i != GRUB_AT_TRIES); +} + +static int +query_mode (void) +{ + grub_uint8_t ret; + int e; + + e = write_mode (0); + if (!e) + return 0; + + keyboard_controller_wait_until_ready (); + + do + ret = grub_inb (KEYBOARD_REG_DATA); + while (ret == GRUB_AT_ACK); + + /* QEMU translates the set even in no-translate mode. */ + if (ret == 0x43 || ret == 1) + return 1; + if (ret == 0x41 || ret == 2) + return 2; + if (ret == 0x3f || ret == 3) + return 3; + return 0; +} + +static void +set_scancodes (void) +{ + /* You must have visited computer museum. Keyboard without scancode set + knowledge. Assume XT. */ + if (!grub_keyboard_orig_set) + { + grub_dprintf ("atkeyb", "No sets support assumed\n"); + current_set = 1; + return; + } + + grub_keyboard_controller_write (grub_keyboard_controller_orig + & ~KEYBOARD_AT_TRANSLATE); + + write_mode (2); + current_set = query_mode (); + grub_dprintf ("atkeyb", "returned set %d\n", current_set); + if (current_set == 2) + return; + + write_mode (1); + current_set = query_mode (); + grub_dprintf ("atkeyb", "returned set %d\n", current_set); + if (current_set == 1) + return; + grub_printf ("No supported scancode set found\n"); +} + +static void +keyboard_controller_led (grub_uint8_t leds) +{ + keyboard_controller_wait_until_ready (); + grub_outb (0xed, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + grub_outb (leds & 0x7, KEYBOARD_REG_DATA); +} + +static int +fetch_key (int *is_break) +{ + int was_ext = 0; + grub_uint8_t at_key; + int ret = 0; + + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + return -1; + at_key = grub_inb (KEYBOARD_REG_DATA); + if (at_key == 0xe0) + { + e0_received = 1; + return -1; + } + + if ((current_set == 2 || current_set == 3) && at_key == 0xf0) + { + f0_received = 1; + return -1; + } + + /* Setting LEDs may generate ACKs. */ + if (at_key == GRUB_AT_ACK) + return -1; + + was_ext = e0_received; + e0_received = 0; + + switch (current_set) + { + case 1: + *is_break = !!(at_key & 0x80); + if (!was_ext) + ret = set1_mapping[at_key & 0x7f]; + else + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++) + if (set1_e0_mapping[i].from == (at_key & 0x7f)) + { + ret = set1_e0_mapping[i].to; + break; + } + } + break; + case 2: + *is_break = f0_received; + f0_received = 0; + if (!was_ext) + ret = set2_mapping[at_key]; + else + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++) + if (set2_e0_mapping[i].from == at_key) + { + ret = set2_e0_mapping[i].to; + break; + } + } + break; + default: + return -1; + } + if (!ret) + { + if (was_ext) + grub_printf ("Unknown key 0xe0+0x%02x from set %d\n", + at_key, current_set); + else + grub_printf ("Unknown key 0x%02x from set %d\n", + at_key, current_set); + return -1; + } + return ret; +} + +/* FIXME: This should become an interrupt service routine. For now + it's just used to catch events from control keys. */ +static int +grub_keyboard_isr (grub_keyboard_key_t key, int is_break) +{ + if (!is_break) + switch (key) + { + case GRUB_KEYBOARD_KEY_LEFT_SHIFT: + at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_SHIFT: + at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_CTRL: + at_keyboard_status |= GRUB_TERM_STATUS_LCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_CTRL: + at_keyboard_status |= GRUB_TERM_STATUS_RCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_ALT: + at_keyboard_status |= GRUB_TERM_STATUS_RALT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_ALT: + at_keyboard_status |= GRUB_TERM_STATUS_LALT; + return 1; + default: + return 0; + } + else + switch (key) + { + case GRUB_KEYBOARD_KEY_LEFT_SHIFT: + at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_SHIFT: + at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_CTRL: + at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_CTRL: + at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_ALT: + at_keyboard_status &= ~GRUB_TERM_STATUS_RALT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_ALT: + at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; + return 1; + default: + return 0; + } +} + +/* If there is a raw key pending, return it; otherwise return -1. */ +static int +grub_keyboard_getkey (void) +{ + int key; + int is_break; + + key = fetch_key (&is_break); + if (key == -1) + return -1; + + if (grub_keyboard_isr (key, is_break)) + return -1; + if (is_break) + return -1; + return key; +} + +/* If there is a character pending, return it; + otherwise return GRUB_TERM_NO_KEY. */ +static int +grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) +{ + int code; + code = grub_keyboard_getkey (); + if (code == -1) + return GRUB_TERM_NO_KEY; +#ifdef DEBUG_AT_KEYBOARD + grub_dprintf ("atkeyb", "Detected key 0x%x\n", key); +#endif + switch (code) + { + case GRUB_KEYBOARD_KEY_CAPS_LOCK: + at_keyboard_status ^= GRUB_TERM_STATUS_CAPS; + led_status ^= KEYBOARD_LED_CAPS; + keyboard_controller_led (led_status); + +#ifdef DEBUG_AT_KEYBOARD + grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); +#endif + return GRUB_TERM_NO_KEY; + case GRUB_KEYBOARD_KEY_NUM_LOCK: + at_keyboard_status ^= GRUB_TERM_STATUS_NUM; + led_status ^= KEYBOARD_LED_NUM; + keyboard_controller_led (led_status); + +#ifdef DEBUG_AT_KEYBOARD + grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); +#endif + return GRUB_TERM_NO_KEY; + case GRUB_KEYBOARD_KEY_SCROLL_LOCK: + at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL; + led_status ^= KEYBOARD_LED_SCROLL; + keyboard_controller_led (led_status); + return GRUB_TERM_NO_KEY; + default: + return grub_term_map_key (code, at_keyboard_status); + } +} + +static grub_err_t +grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unused))) +{ + at_keyboard_status = 0; + /* Drain input buffer. */ + while (1) + { + keyboard_controller_wait_until_ready (); + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + break; + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + } +#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_QEMU) + grub_keyboard_controller_orig = 0; + grub_keyboard_orig_set = 2; +#else + grub_keyboard_controller_orig = grub_keyboard_controller_read (); + grub_keyboard_orig_set = query_mode (); +#endif + set_scancodes (); + keyboard_controller_led (led_status); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) +{ + if (grub_keyboard_orig_set) + write_mode (grub_keyboard_orig_set); + grub_keyboard_controller_write (grub_keyboard_controller_orig); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_at_fini_hw (int noreturn __attribute__ ((unused))) +{ + return grub_keyboard_controller_fini (NULL); +} + +static grub_err_t +grub_at_restore_hw (void) +{ + /* Drain input buffer. */ + while (1) + { + keyboard_controller_wait_until_ready (); + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + break; + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + } + set_scancodes (); + keyboard_controller_led (led_status); + + return GRUB_ERR_NONE; +} + + +static struct grub_term_input grub_at_keyboard_term = + { + .name = "at_keyboard", + .init = grub_keyboard_controller_init, + .fini = grub_keyboard_controller_fini, + .getkey = grub_at_keyboard_getkey + }; + +GRUB_MOD_INIT(at_keyboard) +{ + grub_term_register_input ("at_keyboard", &grub_at_keyboard_term); + grub_loader_register_preboot_hook (grub_at_fini_hw, grub_at_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE); +} + +GRUB_MOD_FINI(at_keyboard) +{ + grub_keyboard_controller_fini (NULL); + grub_term_unregister_input (&grub_at_keyboard_term); +} diff --git a/term/efi/console.c b/grub-core/term/efi/console.c similarity index 69% rename from term/efi/console.c rename to grub-core/term/efi/console.c index dca002910..8fd89b093 100644 --- a/term/efi/console.c +++ b/grub-core/term/efi/console.c @@ -24,12 +24,6 @@ #include #include -static const grub_uint8_t -grub_console_standard_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_YELLOW, - GRUB_EFI_BACKGROUND_BLACK); - -static int read_key = -1; - static grub_uint32_t map_char (grub_uint32_t c) { @@ -79,6 +73,9 @@ grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)), grub_efi_simple_text_output_interface_t *o; unsigned i, j; + if (grub_efi_is_finished) + return; + o = grub_efi_system_table->con_out; /* For now, do not try to use a surrogate pair. */ @@ -100,133 +97,39 @@ grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)), efi_call_2 (o->output_string, o, str); } +const unsigned efi_codes[] = + { + 0, GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_RIGHT, + GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_END, GRUB_TERM_KEY_INSERT, + GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1, + GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + GRUB_TERM_KEY_F10, 0, 0, '\e' + }; + + static int -grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) +grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) { grub_efi_simple_input_interface_t *i; grub_efi_input_key_t key; grub_efi_status_t status; - if (read_key >= 0) - return 1; + if (grub_efi_is_finished) + return 0; i = grub_efi_system_table->con_in; status = efi_call_2 (i->read_key_stroke, i, &key); -#if 0 - switch (status) - { - case GRUB_EFI_SUCCESS: - { - grub_uint16_t xy; - xy = grub_getxy (); - grub_gotoxy (0, 0); - grub_printf ("scan_code=%x,unicode_char=%x ", - (unsigned) key.scan_code, - (unsigned) key.unicode_char); - grub_gotoxy (xy >> 8, xy & 0xff); - } - break; + if (status != GRUB_EFI_SUCCESS) + return GRUB_TERM_NO_KEY; - case GRUB_EFI_NOT_READY: - //grub_printf ("not ready "); - break; + if (key.scan_code == 0) + return key.unicode_char; + else if (key.scan_code < ARRAY_SIZE (efi_codes)) + return efi_codes[key.scan_code]; - default: - //grub_printf ("device error "); - break; - } -#endif - - if (status == GRUB_EFI_SUCCESS) - { - switch (key.scan_code) - { - case 0x00: - read_key = key.unicode_char; - break; - case 0x01: - read_key = GRUB_TERM_UP; - break; - case 0x02: - read_key = GRUB_TERM_DOWN; - break; - case 0x03: - read_key = GRUB_TERM_RIGHT; - break; - case 0x04: - read_key = GRUB_TERM_LEFT; - break; - case 0x05: - read_key = GRUB_TERM_HOME; - break; - case 0x06: - read_key = GRUB_TERM_END; - break; - case 0x07: - break; - case 0x08: - read_key = GRUB_TERM_DC; - break; - case 0x09: - break; - case 0x0a: - break; - case 0x0b: - read_key = 24; - break; - case 0x0c: - read_key = 1; - break; - case 0x0d: - read_key = 5; - break; - case 0x0e: - read_key = 3; - break; - case 0x17: - read_key = '\e'; - break; - default: - break; - } - } - - return read_key; -} - -static int -grub_console_getkey (struct grub_term_input *term) -{ - grub_efi_simple_input_interface_t *i; - grub_efi_boot_services_t *b; - grub_efi_uintn_t index; - grub_efi_status_t status; - int key; - - if (read_key >= 0) - { - key = read_key; - read_key = -1; - return key; - } - - i = grub_efi_system_table->con_in; - b = grub_efi_system_table->boot_services; - - do - { - status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index); - if (status != GRUB_EFI_SUCCESS) - return -1; - - grub_console_checkkey (term); - } - while (read_key < 0); - - key = read_key; - read_key = -1; - return key; + return GRUB_TERM_NO_KEY; } static grub_uint16_t @@ -236,7 +139,8 @@ grub_console_getwh (struct grub_term_output *term __attribute__ ((unused))) grub_efi_uintn_t columns, rows; o = grub_efi_system_table->con_out; - if (efi_call_4 (o->query_mode, o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS) + if (grub_efi_is_finished || efi_call_4 (o->query_mode, o, o->mode->mode, + &columns, &rows) != GRUB_EFI_SUCCESS) { /* Why does this fail? */ columns = 80; @@ -251,6 +155,9 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused))) { grub_efi_simple_text_output_interface_t *o; + if (grub_efi_is_finished) + return 0; + o = grub_efi_system_table->con_out; return ((o->mode->cursor_column << 8) | o->mode->cursor_row); } @@ -261,6 +168,9 @@ grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)), { grub_efi_simple_text_output_interface_t *o; + if (grub_efi_is_finished) + return; + o = grub_efi_system_table->con_out; efi_call_3 (o->set_cursor_position, o, x, y); } @@ -271,6 +181,9 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused))) grub_efi_simple_text_output_interface_t *o; grub_efi_int32_t orig_attr; + if (grub_efi_is_finished) + return; + o = grub_efi_system_table->con_out; orig_attr = o->mode->attribute; efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK); @@ -284,17 +197,21 @@ grub_console_setcolorstate (struct grub_term_output *term, { grub_efi_simple_text_output_interface_t *o; + if (grub_efi_is_finished) + return; + o = grub_efi_system_table->con_out; switch (state) { case GRUB_TERM_COLOR_STANDARD: - efi_call_2 (o->set_attributes, o, grub_console_standard_color); + efi_call_2 (o->set_attributes, o, GRUB_TERM_DEFAULT_STANDARD_COLOR + & 0x7f); break; case GRUB_TERM_COLOR_NORMAL: - efi_call_2 (o->set_attributes, o, term->normal_color); + efi_call_2 (o->set_attributes, o, term->normal_color & 0x7f); break; case GRUB_TERM_COLOR_HIGHLIGHT: - efi_call_2 (o->set_attributes, o, term->highlight_color); + efi_call_2 (o->set_attributes, o, term->highlight_color & 0x7f); break; default: break; @@ -307,6 +224,9 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), { grub_efi_simple_text_output_interface_t *o; + if (grub_efi_is_finished) + return; + o = grub_efi_system_table->con_out; efi_call_2 (o->enable_cursor, o, on); } @@ -328,7 +248,6 @@ grub_efi_console_fini (struct grub_term_output *term) static struct grub_term_input grub_console_term_input = { .name = "console", - .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, }; @@ -344,10 +263,8 @@ static struct grub_term_output grub_console_term_output = .cls = grub_console_cls, .setcolorstate = grub_console_setcolorstate, .setcursor = grub_console_setcursor, - .normal_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_LIGHTGRAY, - GRUB_EFI_BACKGROUND_BLACK), - .highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_BLACK, - GRUB_EFI_BACKGROUND_LIGHTGRAY), + .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR, + .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR, .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS }; diff --git a/term/gfxterm.c b/grub-core/term/gfxterm.c similarity index 98% rename from term/gfxterm.c rename to grub-core/term/gfxterm.c index bf9705abd..9a10d47b0 100644 --- a/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -405,9 +405,16 @@ destroy_window (void) static grub_err_t grub_gfxterm_term_fini (struct grub_term_output *term __attribute__ ((unused))) { + unsigned i; destroy_window (); grub_video_restore (); + for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) + { + grub_free (virtual_screen.text_buffer[i].code); + virtual_screen.text_buffer[i].code = 0; + } + /* Clear error state. */ grub_errno = GRUB_ERR_NONE; return GRUB_ERR_NONE; @@ -793,13 +800,8 @@ scroll_up (void) unsigned int i; /* Clear first line in text buffer. */ - for (i = 0; - i < virtual_screen.columns; - i++) - { - virtual_screen.text_buffer[i].code = 0; - clear_char (&(virtual_screen.text_buffer[i])); - } + for (i = 0; i < virtual_screen.columns; i++) + grub_free (virtual_screen.text_buffer[i].code); /* Scroll text buffer with one line to up. */ grub_memmove (virtual_screen.text_buffer, @@ -1111,11 +1113,10 @@ static const struct grub_arg_option background_image_cmd_options[] = }; static grub_err_t -grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)), - int argc, - char **args) +grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, + int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; /* Check that we have video adapter active. */ if (grub_video_get_info(NULL) != GRUB_ERR_NONE) @@ -1206,8 +1207,7 @@ GRUB_MOD_INIT(gfxterm) grub_term_register_output ("gfxterm", &grub_video_term); background_image_cmd_handle = grub_register_extcmd ("background_image", - grub_gfxterm_background_image_cmd, - GRUB_COMMAND_FLAG_BOTH, + grub_gfxterm_background_image_cmd, 0, N_("[-m (stretch|normal)] FILE"), N_("Load background image for active terminal."), background_image_cmd_options); diff --git a/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c similarity index 79% rename from term/i386/pc/console.c rename to grub-core/term/i386/pc/console.c index 19a8e3814..0efeafe4e 100644 --- a/term/i386/pc/console.c +++ b/grub-core/term/i386/pc/console.c @@ -24,33 +24,18 @@ static const struct grub_machine_bios_data_area *bios_data_area = (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; -#define KEYBOARD_LEFT_SHIFT (1 << 0) -#define KEYBOARD_RIGHT_SHIFT (1 << 1) -#define KEYBOARD_CTRL (1 << 2) -#define KEYBOARD_ALT (1 << 3) - static int grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) { - grub_uint8_t status = bios_data_area->keyboard_flag_lower; - int mods = 0; - - if (status & (KEYBOARD_LEFT_SHIFT | KEYBOARD_RIGHT_SHIFT)) - mods |= GRUB_TERM_STATUS_SHIFT; - if (status & KEYBOARD_CTRL) - mods |= GRUB_TERM_STATUS_CTRL; - if (status & KEYBOARD_ALT) - mods |= GRUB_TERM_STATUS_ALT; - - return mods; + /* conveniently GRUB keystatus is modelled after BIOS one. */ + return bios_data_area->keyboard_flag_lower & ~0x80; } static struct grub_term_input grub_console_term_input = { .name = "console", - .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, - .getkeystatus = grub_console_getkeystatus, + .getkeystatus = grub_console_getkeystatus }; static struct grub_term_output grub_console_term_output = diff --git a/term/i386/pc/vga_text.c b/grub-core/term/i386/pc/vga_text.c similarity index 100% rename from term/i386/pc/vga_text.c rename to grub-core/term/i386/pc/vga_text.c diff --git a/term/i386/vga_common.c b/grub-core/term/i386/vga_common.c similarity index 87% rename from term/i386/vga_common.c rename to grub-core/term/i386/vga_common.c index 02fb5c02d..0c217697b 100644 --- a/term/i386/vga_common.c +++ b/grub-core/term/i386/vga_common.c @@ -34,13 +34,13 @@ grub_console_setcolorstate (struct grub_term_output *term, { switch (state) { case GRUB_TERM_COLOR_STANDARD: - grub_console_cur_color = GRUB_TERM_DEFAULT_STANDARD_COLOR; + grub_console_cur_color = GRUB_TERM_DEFAULT_STANDARD_COLOR & 0x7f; break; case GRUB_TERM_COLOR_NORMAL: - grub_console_cur_color = term->normal_color; + grub_console_cur_color = term->normal_color & 0x7f; break; case GRUB_TERM_COLOR_HIGHLIGHT: - grub_console_cur_color = term->highlight_color; + grub_console_cur_color = term->highlight_color & 0x7f; break; default: break; diff --git a/term/ieee1275/ofconsole.c b/grub-core/term/ieee1275/ofconsole.c similarity index 87% rename from term/ieee1275/ofconsole.c rename to grub-core/term/ieee1275/ofconsole.c index 604906ceb..2b0bddbbb 100644 --- a/term/ieee1275/ofconsole.c +++ b/grub-core/term/ieee1275/ofconsole.c @@ -29,8 +29,7 @@ static grub_ieee1275_ihandle_t stdout_ihandle; static grub_ieee1275_ihandle_t stdin_ihandle; -static grub_uint8_t grub_ofconsole_width; -static grub_uint8_t grub_ofconsole_height; +extern struct grub_terminfo_output_state grub_ofconsole_terminfo_output; struct color { @@ -55,7 +54,7 @@ static struct color colors[] = }; static void -put (const int c) +put (struct grub_term_output *term __attribute__ ((unused)), const int c) { char chr = c; @@ -63,7 +62,7 @@ put (const int c) } static int -readkey (void) +readkey (struct grub_term_input *term __attribute__ ((unused))) { grub_uint8_t c; grub_ssize_t actual = 0; @@ -91,7 +90,8 @@ grub_ofconsole_dimensions (void) if (! grub_ieee1275_get_property (options, "screen-#columns", val, lval, 0)) - grub_ofconsole_width = (grub_uint8_t) grub_strtoul (val, 0, 10); + grub_ofconsole_terminfo_output.width + = (grub_uint8_t) grub_strtoul (val, 0, 10); } if (! grub_ieee1275_get_property_length (options, "screen-#rows", &lval) && lval >= 0 && lval < 1024) @@ -99,27 +99,27 @@ grub_ofconsole_dimensions (void) char val[lval]; if (! grub_ieee1275_get_property (options, "screen-#rows", val, lval, 0)) - grub_ofconsole_height = (grub_uint8_t) grub_strtoul (val, 0, 10); + grub_ofconsole_terminfo_output.height + = (grub_uint8_t) grub_strtoul (val, 0, 10); } } /* Use a small console by default. */ - if (! grub_ofconsole_width) - grub_ofconsole_width = 80; - if (! grub_ofconsole_height) - grub_ofconsole_height = 24; -} - -static grub_uint16_t -grub_ofconsole_getwh (struct grub_term_output *term __attribute__ ((unused))) -{ - return (grub_ofconsole_width << 8) | grub_ofconsole_height; + if (! grub_ofconsole_terminfo_output.width) + grub_ofconsole_terminfo_output.width = 80; + if (! grub_ofconsole_terminfo_output.height) + grub_ofconsole_terminfo_output.height = 24; } static void -grub_ofconsole_setcursor (struct grub_term_output *term __attribute__ ((unused)), +grub_ofconsole_setcursor (struct grub_term_output *term, int on) { + grub_terminfo_setcursor (term, on); + + if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF)) + return; + /* Understood by the Open Firmware flavour in OLPC. */ if (on) grub_ieee1275_interpret ("cursor-on", 0); @@ -182,14 +182,15 @@ struct grub_terminfo_input_state grub_ofconsole_terminfo_input = struct grub_terminfo_output_state grub_ofconsole_terminfo_output = { - .put = put + .put = put, + .width = 80, + .height = 24 }; static struct grub_term_input grub_ofconsole_term_input = { .name = "ofconsole", .init = grub_ofconsole_init_input, - .checkkey = grub_terminfo_checkkey, .getkey = grub_terminfo_getkey, .data = &grub_ofconsole_terminfo_input }; @@ -200,7 +201,7 @@ static struct grub_term_output grub_ofconsole_term_output = .init = grub_ofconsole_init_output, .putchar = grub_terminfo_putchar, .getxy = grub_terminfo_getxy, - .getwh = grub_ofconsole_getwh, + .getwh = grub_terminfo_getwh, .gotoxy = grub_terminfo_gotoxy, .cls = grub_terminfo_cls, .setcolorstate = grub_terminfo_setcolorstate, diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c new file mode 100644 index 000000000..4be528df8 --- /dev/null +++ b/grub-core/term/ns8250.c @@ -0,0 +1,278 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,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 + +#ifdef GRUB_MACHINE_PCBIOS +#include +static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; +#define GRUB_SERIAL_PORT_NUM 4 +#else +#include +static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS; +#define GRUB_SERIAL_PORT_NUM (ARRAY_SIZE(serial_hw_io_addr)) +#endif + +/* Convert speed to divisor. */ +static unsigned short +serial_get_divisor (unsigned int speed) +{ + unsigned int i; + + /* The structure for speed vs. divisor. */ + struct divisor + { + unsigned int speed; + unsigned short div; + }; + + /* The table which lists common configurations. */ + /* 1843200 / (speed * 16) */ + static struct divisor divisor_tab[] = + { + { 2400, 0x0030 }, + { 4800, 0x0018 }, + { 9600, 0x000C }, + { 19200, 0x0006 }, + { 38400, 0x0003 }, + { 57600, 0x0002 }, + { 115200, 0x0001 } + }; + + /* Set the baud rate. */ + for (i = 0; i < ARRAY_SIZE (divisor_tab); i++) + if (divisor_tab[i].speed == speed) + /* UART in Yeeloong runs twice the usual rate. */ +#ifdef GRUB_MACHINE_MIPS_YEELOONG + return 2 * divisor_tab[i].div; +#else + return divisor_tab[i].div; +#endif + return 0; +} + +static void +do_real_config (struct grub_serial_port *port) +{ + int divisor; + unsigned char status = 0; + const unsigned char parities[] = { + [GRUB_SERIAL_PARITY_NONE] = UART_NO_PARITY, + [GRUB_SERIAL_PARITY_ODD] = UART_ODD_PARITY, + [GRUB_SERIAL_PARITY_EVEN] = UART_EVEN_PARITY + }; + const unsigned char stop_bits[] = { + [GRUB_SERIAL_STOP_BITS_1] = UART_1_STOP_BIT, + [GRUB_SERIAL_STOP_BITS_2] = UART_2_STOP_BITS, + }; + + if (port->configured) + return; + + port->broken = 0; + + divisor = serial_get_divisor (port->config.speed); + + /* Turn off the interrupt. */ + grub_outb (0, port->port + UART_IER); + + /* Set DLAB. */ + grub_outb (UART_DLAB, port->port + UART_LCR); + + /* Set the baud rate. */ + grub_outb (divisor & 0xFF, port->port + UART_DLL); + grub_outb (divisor >> 8, port->port + UART_DLH); + + /* Set the line status. */ + status |= (parities[port->config.parity] + | (port->config.word_len - 5) + | stop_bits[port->config.stop_bits]); + grub_outb (status, port->port + UART_LCR); + + /* In Yeeloong serial port has only 3 wires. */ +#ifndef GRUB_MACHINE_MIPS_YEELOONG + /* Enable the FIFO. */ + grub_outb (UART_ENABLE_FIFO_TRIGGER1, port->port + UART_FCR); + + /* Turn on DTR and RTS. */ + grub_outb (UART_ENABLE_DTRRTS, port->port + UART_MCR); +#else + /* Enable the FIFO. */ + grub_outb (UART_ENABLE_FIFO_TRIGGER14, port->port + UART_FCR); + + /* Turn on DTR, RTS, and OUT2. */ + grub_outb (UART_ENABLE_DTRRTS | UART_ENABLE_OUT2, port->port + UART_MCR); +#endif + + /* Drain the input buffer. */ + while (grub_inb (port->port + UART_LSR) & UART_DATA_READY) + grub_inb (port->port + UART_RX); + + port->configured = 1; +} + +/* Fetch a key. */ +static int +serial_hw_fetch (struct grub_serial_port *port) +{ + do_real_config (port); + if (grub_inb (port->port + UART_LSR) & UART_DATA_READY) + return grub_inb (port->port + UART_RX); + + return -1; +} + +/* Put a character. */ +static void +serial_hw_put (struct grub_serial_port *port, const int c) +{ + grub_uint64_t endtime; + + do_real_config (port); + + if (port->broken > 5) + endtime = grub_get_time_ms (); + else if (port->broken > 1) + endtime = grub_get_time_ms () + 50; + else + endtime = grub_get_time_ms () + 200; + /* Wait until the transmitter holding register is empty. */ + while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0) + { + if (grub_get_time_ms () > endtime) + { + port->broken++; + /* There is something wrong. But what can I do? */ + return; + } + } + + if (port->broken) + port->broken--; + + grub_outb (c, port->port + UART_TX); +} + +/* Initialize a serial device. PORT is the port number for a serial device. + SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600, + 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used + for the device. Likewise, PARITY is the type of the parity and + STOP_BIT_LEN is the length of the stop bit. The possible values for + WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as + macros. */ +static grub_err_t +serial_hw_configure (struct grub_serial_port *port, + struct grub_serial_config *config) +{ + unsigned short divisor; + + divisor = serial_get_divisor (config->speed); + if (divisor == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); + + if (config->parity != GRUB_SERIAL_PARITY_NONE + && config->parity != GRUB_SERIAL_PARITY_ODD + && config->parity != GRUB_SERIAL_PARITY_EVEN) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity"); + + if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1 + && config->stop_bits != GRUB_SERIAL_STOP_BITS_2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits"); + + if (config->word_len < 5 || config->word_len > 8) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length"); + + port->config = *config; + port->configured = 0; + + /* FIXME: should check if the serial terminal was found. */ + + return GRUB_ERR_NONE; +} + +struct grub_serial_driver grub_ns8250_driver = + { + .configure = serial_hw_configure, + .fetch = serial_hw_fetch, + .put = serial_hw_put + }; + +static char com_names[GRUB_SERIAL_PORT_NUM][20]; +static struct grub_serial_port com_ports[GRUB_SERIAL_PORT_NUM]; + +void +grub_ns8250_init (void) +{ + unsigned i; + for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++) + if (serial_hw_io_addr[i]) + { + grub_err_t err; + grub_snprintf (com_names[i], sizeof (com_names[i]), "com%d", i); + com_ports[i].name = com_names[i]; + com_ports[i].driver = &grub_ns8250_driver; + com_ports[i].port = serial_hw_io_addr[i]; + err = grub_serial_config_defaults (&com_ports[i]); + if (err) + grub_print_error (); + + grub_serial_register (&com_ports[i]); + } +} + +/* Return the port number for the UNITth serial device. */ +grub_port_t +grub_ns8250_hw_get_port (const unsigned int unit) +{ + if (unit < GRUB_SERIAL_PORT_NUM) + return serial_hw_io_addr[unit]; + else + return 0; +} + +char * +grub_serial_ns8250_add_port (grub_port_t port) +{ + struct grub_serial_port *p; + unsigned i; + for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++) + if (com_ports[i].port == port) + return com_names[i]; + p = grub_malloc (sizeof (*p)); + if (!p) + return NULL; + p->name = grub_xasprintf ("port%lx", (unsigned long) port); + if (!p->name) + { + grub_free (p); + return NULL; + } + p->driver = &grub_ns8250_driver; + grub_serial_config_defaults (p); + p->port = port; + grub_serial_register (p); + + return p->name; +} diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c new file mode 100644 index 000000000..d36388359 --- /dev/null +++ b/grub-core/term/serial.c @@ -0,0 +1,369 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,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 +#include + +#define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports)) + +/* Argument options. */ +static const struct grub_arg_option options[] = +{ + {"unit", 'u', 0, N_("Set the serial unit."), 0, ARG_TYPE_INT}, + {"port", 'p', 0, N_("Set the serial port address."), 0, ARG_TYPE_STRING}, + {"speed", 's', 0, N_("Set the serial port speed."), 0, ARG_TYPE_INT}, + {"word", 'w', 0, N_("Set the serial port word length."), 0, ARG_TYPE_INT}, + {"parity", 'r', 0, N_("Set the serial port parity."), 0, ARG_TYPE_STRING}, + {"stop", 't', 0, N_("Set the serial port stop bits."), 0, ARG_TYPE_INT}, + {0, 0, 0, 0, 0, 0} +}; + +struct grub_serial_port *grub_serial_ports; + +struct grub_serial_output_state +{ + struct grub_terminfo_output_state tinfo; + struct grub_serial_port *port; +}; + +struct grub_serial_input_state +{ + struct grub_terminfo_input_state tinfo; + struct grub_serial_port *port; +}; + +static void +serial_put (grub_term_output_t term, const int c) +{ + struct grub_serial_output_state *data = term->data; + data->port->driver->put (data->port, c); +} + +static int +serial_fetch (grub_term_input_t term) +{ + struct grub_serial_input_state *data = term->data; + return data->port->driver->fetch (data->port); +} + +const struct grub_serial_input_state grub_serial_terminfo_input_template = + { + .tinfo = + { + .readkey = serial_fetch + } + }; + +const struct grub_serial_output_state grub_serial_terminfo_output_template = + { + .tinfo = + { + .put = serial_put, + .width = 80, + .height = 24 + } + }; + +struct grub_serial_input_state grub_serial_terminfo_input; + +struct grub_serial_output_state grub_serial_terminfo_output; + +int registered = 0; + +static struct grub_term_input grub_serial_term_input = +{ + .name = "serial", + .init = grub_terminfo_input_init, + .getkey = grub_terminfo_getkey, + .data = &grub_serial_terminfo_input +}; + +static struct grub_term_output grub_serial_term_output = +{ + .name = "serial", + .putchar = grub_terminfo_putchar, + .getwh = grub_terminfo_getwh, + .getxy = grub_terminfo_getxy, + .gotoxy = grub_terminfo_gotoxy, + .cls = grub_terminfo_cls, + .setcolorstate = grub_terminfo_setcolorstate, + .setcursor = grub_terminfo_setcursor, + .flags = GRUB_TERM_CODE_TYPE_ASCII, + .data = &grub_serial_terminfo_output, + .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR, + .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR, +}; + + + +static struct grub_serial_port * +grub_serial_find (char *name) +{ + struct grub_serial_port *port; + + FOR_SERIAL_PORTS (port) + if (grub_strcmp (port->name, name) == 0) + break; + +#ifndef GRUB_MACHINE_EMU + if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0 + && grub_isdigit (name [sizeof ("port") - 1])) + { + name = grub_serial_ns8250_add_port (grub_strtoul (&name[sizeof ("port") - 1], + 0, 16)); + if (!name) + return NULL; + + FOR_SERIAL_PORTS (port) + if (grub_strcmp (port->name, name) == 0) + break; + } +#endif + + return port; +} + +static grub_err_t +grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + char pname[40]; + char *name = NULL; + struct grub_serial_port *port; + struct grub_serial_config config; + grub_err_t err; + + if (state[0].set) + { + grub_snprintf (pname, sizeof (pname), "com%ld", + grub_strtoul (state[0].arg, 0, 0)); + name = pname; + } + + if (state[1].set) + { + grub_snprintf (pname, sizeof (pname), "port%lx", + grub_strtoul (state[1].arg, 0, 0)); + name = pname; + } + + if (argc >= 1) + name = args[0]; + + if (!name) + name = "com0"; + + port = grub_serial_find (name); + if (!port) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown serial port"); + + config = port->config; + + if (state[2].set) + config.speed = grub_strtoul (state[2].arg, 0, 0); + + if (state[3].set) + config.word_len = grub_strtoul (state[3].arg, 0, 0); + + if (state[4].set) + { + if (! grub_strcmp (state[4].arg, "no")) + config.parity = GRUB_SERIAL_PARITY_NONE; + else if (! grub_strcmp (state[4].arg, "odd")) + config.parity = GRUB_SERIAL_PARITY_ODD; + else if (! grub_strcmp (state[4].arg, "even")) + config.parity = GRUB_SERIAL_PARITY_EVEN; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity"); + } + + if (state[5].set) + { + if (! grub_strcmp (state[5].arg, "1")) + config.stop_bits = GRUB_SERIAL_STOP_BITS_1; + else if (! grub_strcmp (state[5].arg, "2")) + config.stop_bits = GRUB_SERIAL_STOP_BITS_2; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits"); + } + + /* Initialize with new settings. */ + err = port->driver->configure (port, &config); + if (err) + return err; +#ifndef GRUB_MACHINE_EMU + /* Compatibility kludge. */ + if (port->driver == &grub_ns8250_driver) + { + if (!registered) + { + grub_terminfo_output_register (&grub_serial_term_output, "vt100"); + + grub_term_register_input ("serial", &grub_serial_term_input); + grub_term_register_output ("serial", &grub_serial_term_output); + } + grub_serial_terminfo_output.port = port; + grub_serial_terminfo_input.port = port; + registered = 1; + } +#endif + return GRUB_ERR_NONE; +} + +grub_err_t +grub_serial_register (struct grub_serial_port *port) +{ + struct grub_term_input *in; + struct grub_term_output *out; + struct grub_serial_input_state *indata; + struct grub_serial_output_state *outdata; + + in = grub_malloc (sizeof (*in)); + if (!in) + return grub_errno; + + indata = grub_malloc (sizeof (*indata)); + if (!indata) + { + grub_free (in); + return grub_errno; + } + + grub_memcpy (in, &grub_serial_term_input, sizeof (*in)); + in->data = indata; + in->name = grub_xasprintf ("serial_%s", port->name); + grub_memcpy (indata, &grub_serial_terminfo_input, sizeof (*indata)); + + if (!in->name) + { + grub_free (in); + grub_free (indata); + return grub_errno; + } + + out = grub_malloc (sizeof (*out)); + if (!out) + { + grub_free (in); + grub_free (indata); + grub_free ((char *) in->name); + return grub_errno; + } + + outdata = grub_malloc (sizeof (*outdata)); + if (!outdata) + { + grub_free (in); + grub_free (indata); + grub_free ((char *) in->name); + grub_free (out); + return grub_errno; + } + + grub_memcpy (out, &grub_serial_term_output, sizeof (*out)); + out->data = outdata; + out->name = in->name; + grub_memcpy (outdata, &grub_serial_terminfo_output, sizeof (*outdata)); + + grub_list_push (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port)); + ((struct grub_serial_input_state *) in->data)->port = port; + ((struct grub_serial_output_state *) out->data)->port = port; + port->term_in = in; + port->term_out = out; + grub_terminfo_output_register (out, "vt100"); +#ifdef GRUB_MACHINE_MIPS_YEELOONG + if (grub_strcmp (port->name, "com0") == 0) + { + grub_term_register_input_active ("serial_*", in); + grub_term_register_output_active ("serial_*", out); + } + else +#endif + { + grub_term_register_input ("serial_*", in); + grub_term_register_output ("serial_*", out); + } + + return GRUB_ERR_NONE; +} + +void +grub_serial_unregister (struct grub_serial_port *port) +{ + if (port->driver->fini) + port->driver->fini (port); + + if (port->term_in) + grub_term_unregister_input (port->term_in); + if (port->term_out) + grub_term_unregister_output (port->term_out); + + grub_list_remove (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port)); +} + +void +grub_serial_unregister_driver (struct grub_serial_driver *driver) +{ + struct grub_serial_port *port, *next; + for (port = grub_serial_ports; port; port = next) + { + next = port->next; + if (port->driver == driver) + grub_serial_unregister (port); + } +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(serial) +{ + cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0, + N_("[OPTIONS...]"), + N_("Configure serial port."), options); + grub_memcpy (&grub_serial_terminfo_output, + &grub_serial_terminfo_output_template, + sizeof (grub_serial_terminfo_output)); + + grub_memcpy (&grub_serial_terminfo_input, + &grub_serial_terminfo_input_template, + sizeof (grub_serial_terminfo_input)); + +#ifndef GRUB_MACHINE_EMU + grub_ns8250_init (); +#endif +} + +GRUB_MOD_FINI(serial) +{ + while (grub_serial_ports) + grub_serial_unregister (grub_serial_ports); + if (registered) + { + grub_term_unregister_input (&grub_serial_term_input); + grub_term_unregister_output (&grub_serial_term_output); + } + grub_unregister_extcmd (cmd); +} diff --git a/term/terminfo.c b/grub-core/term/terminfo.c similarity index 80% rename from term/terminfo.c rename to grub-core/term/terminfo.c index ff54e5dba..d01811959 100644 --- a/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -195,7 +195,7 @@ putstr (struct grub_term_output *term, const char *str) struct grub_terminfo_output_state *data = (struct grub_terminfo_output_state *) term->data; while (*str) - data->put (*str++); + data->put (term, *str++); } grub_uint16_t @@ -225,7 +225,7 @@ grub_terminfo_gotoxy (struct grub_term_output *term, else { if ((y == data->ypos) && (x == data->xpos - 1)) - data->put ('\b'); + data->put (term, '\b'); } data->xpos = x; @@ -348,20 +348,30 @@ grub_terminfo_putchar (struct grub_term_output *term, data->xpos = 0; if (data->ypos < grub_term_height (term) - 1) data->ypos++; - data->put ('\r'); - data->put ('\n'); + data->put (term, '\r'); + data->put (term, '\n'); } data->xpos += c->estimated_width; break; } - data->put (c->base); + data->put (term, c->base); +} + +grub_uint16_t +grub_terminfo_getwh (struct grub_term_output *term) +{ + struct grub_terminfo_output_state *data + = (struct grub_terminfo_output_state *) term->data; + + return (data->width << 8) | data->height; } #define ANSI_C0 0x9b static void -grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) +grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, + int (*readkey) (struct grub_term_input *term)) { int c; @@ -371,7 +381,7 @@ grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) /* On 9600 we have to wait up to 12 milliseconds. */ \ start = grub_get_time_ms (); \ do \ - c = readkey (); \ + c = readkey (term); \ while (c == -1 && grub_get_time_ms () - start < 12); \ if (c == -1) \ return; \ @@ -380,7 +390,7 @@ grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) (*len)++; \ } - c = readkey (); + c = readkey (term); if (c < 0) { *len = 0; @@ -402,34 +412,34 @@ grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) static struct { char key; - char ascii; + unsigned ascii; } three_code_table[] = { - {'4', GRUB_TERM_DC}, - {'A', GRUB_TERM_UP}, - {'B', GRUB_TERM_DOWN}, - {'C', GRUB_TERM_RIGHT}, - {'D', GRUB_TERM_LEFT}, - {'F', GRUB_TERM_END}, - {'H', GRUB_TERM_HOME}, - {'K', GRUB_TERM_END}, - {'P', GRUB_TERM_DC}, - {'?', GRUB_TERM_PPAGE}, - {'/', GRUB_TERM_NPAGE} + {'4', GRUB_TERM_KEY_DC}, + {'A', GRUB_TERM_KEY_UP}, + {'B', GRUB_TERM_KEY_DOWN}, + {'C', GRUB_TERM_KEY_RIGHT}, + {'D', GRUB_TERM_KEY_LEFT}, + {'F', GRUB_TERM_KEY_END}, + {'H', GRUB_TERM_KEY_HOME}, + {'K', GRUB_TERM_KEY_END}, + {'P', GRUB_TERM_KEY_DC}, + {'?', GRUB_TERM_KEY_PPAGE}, + {'/', GRUB_TERM_KEY_NPAGE} }; static struct { char key; - char ascii; + unsigned ascii; } four_code_table[] = { - {'1', GRUB_TERM_HOME}, - {'3', GRUB_TERM_DC}, - {'5', GRUB_TERM_PPAGE}, - {'6', GRUB_TERM_NPAGE} + {'1', GRUB_TERM_KEY_HOME}, + {'3', GRUB_TERM_KEY_DC}, + {'5', GRUB_TERM_KEY_PPAGE}, + {'6', GRUB_TERM_KEY_NPAGE} }; unsigned i; @@ -466,37 +476,30 @@ grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) #undef CONTINUE_READ } -/* The terminfo version of checkkey. */ -int -grub_terminfo_checkkey (struct grub_term_input *termi) -{ - struct grub_terminfo_input_state *data - = (struct grub_terminfo_input_state *) (termi->data); - if (data->npending) - return data->input_buf[0]; - - grub_terminfo_readkey (data->input_buf, &data->npending, data->readkey); - - if (data->npending) - return data->input_buf[0]; - - return -1; -} - /* The terminfo version of getkey. */ int grub_terminfo_getkey (struct grub_term_input *termi) { struct grub_terminfo_input_state *data = (struct grub_terminfo_input_state *) (termi->data); - int ret; - while (! data->npending) - grub_terminfo_readkey (data->input_buf, &data->npending, data->readkey); + if (data->npending) + { + data->npending--; + grub_memmove (data->input_buf, data->input_buf + 1, data->npending); + return data->input_buf[0]; + } - ret = data->input_buf[0]; - data->npending--; - grub_memmove (data->input_buf, data->input_buf + 1, data->npending); - return ret; + grub_terminfo_readkey (termi, data->input_buf, + &data->npending, data->readkey); + + if (data->npending) + { + data->npending--; + grub_memmove (data->input_buf, data->input_buf + 1, data->npending); + return data->input_buf[0]; + } + + return GRUB_TERM_NO_KEY; } grub_err_t @@ -543,85 +546,96 @@ print_terminfo (void) return GRUB_ERR_NONE; } +static const struct grub_arg_option options[] = +{ + {"ascii", 'a', 0, N_("Terminal is ASCII-only [default]."), 0, ARG_TYPE_NONE}, + {"utf8", 'u', 0, N_("Terminal is logical-ordered UTF-8."), 0, ARG_TYPE_NONE}, + {"visual-utf8", 'v', 0, N_("Terminal is visually-ordered UTF-8."), 0, + ARG_TYPE_NONE}, + {"geometry", 'g', 0, N_("Terminal has given geometry."), + N_("WIDTHxHEIGHT."), ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} +}; + +enum + { + OPTION_ASCII, + OPTION_UTF8, + OPTION_VISUAL_UTF8, + OPTION_GEOMETRY + }; + static grub_err_t -grub_cmd_terminfo (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) +grub_cmd_terminfo (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_term_output *cur; int encoding = GRUB_TERM_CODE_TYPE_ASCII; - int i; - char *name = NULL, *type = NULL; + struct grub_arg_list *state = ctxt->state; + int w = 0, h = 0; if (argc == 0) return print_terminfo (); - for (i = 0; i < argc; i++) + if (state[OPTION_ASCII].set) + encoding = GRUB_TERM_CODE_TYPE_ASCII; + + if (state[OPTION_UTF8].set) + encoding = GRUB_TERM_CODE_TYPE_UTF8_LOGICAL; + + if (state[OPTION_VISUAL_UTF8].set) + encoding = GRUB_TERM_CODE_TYPE_UTF8_VISUAL; + + if (state[OPTION_GEOMETRY].set) { - if (grub_strcmp (args[i], "-a") == 0 - || grub_strcmp (args[i], "--ascii") == 0) - { - encoding = GRUB_TERM_CODE_TYPE_ASCII; - continue; - } - if (grub_strcmp (args[i], "-u") == 0 - || grub_strcmp (args[i], "--utf8") == 0) - { - encoding = GRUB_TERM_CODE_TYPE_UTF8_LOGICAL; - continue; - } - if (grub_strcmp (args[i], "-v") == 0 - || grub_strcmp (args[i], "--visual-utf8") == 0) - { - encoding = GRUB_TERM_CODE_TYPE_UTF8_VISUAL; - continue; - } - if (!name) - { - name = args[i]; - continue; - } - if (!type) - { - type = args[i]; - continue; - } - - return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters"); + char *ptr = state[OPTION_GEOMETRY].arg; + w = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr != 'x') + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "incorrect geometry specification"); + ptr++; + h = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; } - if (name == NULL) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few parameters"); - for (cur = terminfo_outputs; cur; cur = ((struct grub_terminfo_output_state *) cur->data)->next) - if (grub_strcmp (name, cur->name) == 0) + if (grub_strcmp (args[0], cur->name) == 0) { cur->flags = (cur->flags & ~GRUB_TERM_CODE_TYPE_MASK) | encoding; - if (!type) + + if (w && h) + { + struct grub_terminfo_output_state *data + = (struct grub_terminfo_output_state *) cur->data; + data->width = w; + data->height = h; + } + + if (argc == 1) return GRUB_ERR_NONE; - return grub_terminfo_set_current (cur, type); + return grub_terminfo_set_current (cur, args[1]); } + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no terminal %s found or it's not handled by terminfo", - name); + args[0]); } -static grub_command_t cmd; +static grub_extcmd_t cmd; GRUB_MOD_INIT(terminfo) { - cmd = grub_register_command ("terminfo", grub_cmd_terminfo, - N_("[[-a|-u|-v] TERM [TYPE]]"), - N_("Set terminfo type of TERM to TYPE.\n" - "-a, --ascii Terminal is ASCII-only [default].\n" - "-u, --utf8 Terminal is logical-ordered UTF-8.\n" - "-v, --visual-utf8 Terminal is visually-ordered UTF-8.") - - ); + cmd = grub_register_extcmd ("terminfo", grub_cmd_terminfo, 0, + N_("[[-a|-u|-v] [-g WxH] TERM [TYPE]]"), + N_("Set terminfo type of TERM to TYPE.\n"), + options); } GRUB_MOD_FINI(terminfo) { - grub_unregister_command (cmd); + grub_unregister_extcmd (cmd); } diff --git a/term/tparm.c b/grub-core/term/tparm.c similarity index 100% rename from term/tparm.c rename to grub-core/term/tparm.c diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c new file mode 100644 index 000000000..30ed8f9c2 --- /dev/null +++ b/grub-core/term/usb_keyboard.c @@ -0,0 +1,470 @@ +/* Support for the HID Boot Protocol. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 + * 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 + + + +enum + { + KEY_NO_KEY = 0x00, + KEY_ERR_BUFFER = 0x01, + KEY_ERR_POST = 0x02, + KEY_ERR_UNDEF = 0x03, + KEY_CAPS_LOCK = 0x39, + KEY_NUM_LOCK = 0x53, + }; + +enum + { + LED_NUM_LOCK = 0x01, + LED_CAPS_LOCK = 0x02 + }; + +/* Valid values for bRequest. See HID definition version 1.11 section 7.2. */ +#define USB_HID_GET_REPORT 0x01 +#define USB_HID_GET_IDLE 0x02 +#define USB_HID_GET_PROTOCOL 0x03 +#define USB_HID_SET_REPORT 0x09 +#define USB_HID_SET_IDLE 0x0A +#define USB_HID_SET_PROTOCOL 0x0B + +#define USB_HID_BOOT_SUBCLASS 0x01 +#define USB_HID_KBD_PROTOCOL 0x01 + +#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01 +#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02 +#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04 +#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10 +#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20 +#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 + +struct grub_usb_keyboard_data +{ + grub_usb_device_t usbdev; + grub_uint8_t status; + grub_uint16_t mods; + int interfno; + struct grub_usb_desc_endp *endp; + grub_usb_transfer_t transfer; + grub_uint8_t report[8]; + int dead; + int last_key; + grub_uint64_t repeat_time; + grub_uint8_t current_report[8]; + grub_uint8_t last_report[8]; + int index; + int max_index; +}; + +static int grub_usb_keyboard_getkey (struct grub_term_input *term); +static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term); + +static struct grub_term_input grub_usb_keyboard_term = + { + .getkey = grub_usb_keyboard_getkey, + .getkeystatus = grub_usb_keyboard_getkeystatus, + .next = 0 + }; + +static struct grub_term_input grub_usb_keyboards[16]; + +static int +interpret_status (grub_uint8_t data0) +{ + int mods = 0; + + /* Check Shift, Control, and Alt status. */ + if (data0 & GRUB_USB_KEYBOARD_LEFT_SHIFT) + mods |= GRUB_TERM_STATUS_LSHIFT; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + mods |= GRUB_TERM_STATUS_RSHIFT; + if (data0 & GRUB_USB_KEYBOARD_LEFT_CTRL) + mods |= GRUB_TERM_STATUS_LCTRL; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_CTRL) + mods |= GRUB_TERM_STATUS_RCTRL; + if (data0 & GRUB_USB_KEYBOARD_LEFT_ALT) + mods |= GRUB_TERM_STATUS_LALT; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_ALT) + mods |= GRUB_TERM_STATUS_RALT; + + return mods; +} + +static void +grub_usb_keyboard_detach (grub_usb_device_t usbdev, + int config __attribute__ ((unused)), + int interface __attribute__ ((unused))) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++) + { + struct grub_usb_keyboard_data *data = grub_usb_keyboards[i].data; + + if (!data) + continue; + + if (data->usbdev != usbdev) + continue; + + if (data->transfer) + grub_usb_cancel_transfer (data->transfer); + + grub_term_unregister_input (&grub_usb_keyboards[i]); + grub_free ((char *) grub_usb_keyboards[i].name); + grub_usb_keyboards[i].name = NULL; + grub_free (grub_usb_keyboards[i].data); + grub_usb_keyboards[i].data = 0; + } +} + +static int +grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) +{ + unsigned curnum; + struct grub_usb_keyboard_data *data; + struct grub_usb_desc_endp *endp = NULL; + int j; + + grub_dprintf ("usb_keyboard", "%x %x %x %d %d\n", + usbdev->descdev.class, usbdev->descdev.subclass, + usbdev->descdev.protocol, configno, interfno); + + for (curnum = 0; curnum < ARRAY_SIZE (grub_usb_keyboards); curnum++) + if (!grub_usb_keyboards[curnum].data) + break; + + if (curnum == ARRAY_SIZE (grub_usb_keyboards)) + return 0; + + if (usbdev->descdev.class != 0 + || usbdev->descdev.subclass != 0 || usbdev->descdev.protocol != 0) + return 0; + + if (usbdev->config[configno].interf[interfno].descif->subclass + != USB_HID_BOOT_SUBCLASS + || usbdev->config[configno].interf[interfno].descif->protocol + != USB_HID_KBD_PROTOCOL) + return 0; + + for (j = 0; j < usbdev->config[configno].interf[interfno].descif->endpointcnt; + j++) + { + endp = &usbdev->config[configno].interf[interfno].descendp[j]; + + if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) + == GRUB_USB_EP_INTERRUPT) + break; + } + if (j == usbdev->config[configno].interf[interfno].descif->endpointcnt) + return 0; + + grub_dprintf ("usb_keyboard", "HID found!\n"); + + data = grub_malloc (sizeof (*data)); + if (!data) + { + grub_print_error (); + return 0; + } + + data->usbdev = usbdev; + data->interfno = interfno; + data->endp = endp; + + /* Configure device */ + grub_usb_set_configuration (usbdev, configno + 1); + + /* Place the device in boot mode. */ + grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + USB_HID_SET_PROTOCOL, 0, interfno, 0, 0); + + /* Reports every time an event occurs and not more often than that. */ + grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + USB_HID_SET_IDLE, 0<<8, interfno, 0, 0); + + grub_memcpy (&grub_usb_keyboards[curnum], &grub_usb_keyboard_term, + sizeof (grub_usb_keyboards[curnum])); + grub_usb_keyboards[curnum].data = data; + usbdev->config[configno].interf[interfno].detach_hook + = grub_usb_keyboard_detach; + grub_usb_keyboards[curnum].name = grub_xasprintf ("usb_keyboard%d", curnum); + if (!grub_usb_keyboards[curnum].name) + { + grub_print_error (); + return 0; + } + + /* Test showed that getting report may make the keyboard go nuts. + Moreover since we're reattaching keyboard it usually sends + an initial message on interrupt pipe and so we retrieve + the same keystatus. + */ +#if 0 + { + grub_uint8_t report[8]; + grub_usb_err_t err; + grub_memset (report, 0, sizeof (report)); + err = grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_IN, + USB_HID_GET_REPORT, 0x0100, interfno, + sizeof (report), (char *) report); + if (err) + data->status = 0; + else + data->status = report[0]; + } +#else + data->status = 0; +#endif + + data->transfer = grub_usb_bulk_read_background (usbdev, + data->endp->endp_addr, + sizeof (data->report), + (char *) data->report); + if (!data->transfer) + { + grub_print_error (); + return 0; + } + + data->last_key = -1; + data->mods = 0; + data->dead = 0; + + grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]); + + return 1; +} + + + +static void +send_leds (struct grub_usb_keyboard_data *termdata) +{ + char report[1]; + report[0] = 0; + if (termdata->mods & GRUB_TERM_STATUS_CAPS) + report[0] |= LED_CAPS_LOCK; + if (termdata->mods & GRUB_TERM_STATUS_NUM) + report[0] |= LED_NUM_LOCK; + grub_usb_control_msg (termdata->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + USB_HID_SET_REPORT, 0x0200, termdata->interfno, + sizeof (report), (char *) report); + grub_errno = GRUB_ERR_NONE; +} + +static int +parse_keycode (struct grub_usb_keyboard_data *termdata) +{ + int index = termdata->index; + int i, keycode; + + /* Sanity check */ + if (index < 2) + index = 2; + + for ( ; index < termdata->max_index; index++) + { + keycode = termdata->current_report[index]; + + if (keycode == KEY_NO_KEY + || keycode == KEY_ERR_BUFFER + || keycode == KEY_ERR_POST + || keycode == KEY_ERR_UNDEF) + { + /* Don't parse (rest of) this report */ + termdata->index = 0; + if (keycode != KEY_NO_KEY) + /* Don't replace last report with current faulty report + * in future ! */ + grub_memcpy (termdata->current_report, + termdata->last_report, + sizeof (termdata->report)); + return GRUB_TERM_NO_KEY; + } + + /* Try to find current keycode in last report. */ + for (i = 2; i < 8; i++) + if (keycode == termdata->last_report[i]) + break; + if (i < 8) + /* Keycode is in last report, it means it was not released, + * ignore it. */ + continue; + + if (keycode == KEY_CAPS_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_CAPS; + send_leds (termdata); + continue; + } + + if (keycode == KEY_NUM_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_NUM; + send_leds (termdata); + continue; + } + + termdata->last_key = grub_term_map_key (keycode, + interpret_status (termdata->current_report[0]) + | termdata->mods); + termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL; + + grub_errno = GRUB_ERR_NONE; + + index++; + if (index >= termdata->max_index) + termdata->index = 0; + else + termdata->index = index; + + return termdata->last_key; + } + + /* All keycodes parsed */ + termdata->index = 0; + return GRUB_TERM_NO_KEY; +} + +static int +grub_usb_keyboard_getkey (struct grub_term_input *term) +{ + grub_usb_err_t err; + struct grub_usb_keyboard_data *termdata = term->data; + grub_size_t actual; + int keycode = GRUB_TERM_NO_KEY; + + if (termdata->dead) + return GRUB_TERM_NO_KEY; + + if (termdata->index) + keycode = parse_keycode (termdata); + if (keycode != GRUB_TERM_NO_KEY) + return keycode; + + /* Poll interrupt pipe. */ + err = grub_usb_check_transfer (termdata->transfer, &actual); + + if (err == GRUB_USB_ERR_WAIT) + { + if (termdata->last_key != -1 + && grub_get_time_ms () > termdata->repeat_time) + { + termdata->repeat_time = grub_get_time_ms () + + GRUB_TERM_REPEAT_INTERVAL; + return termdata->last_key; + } + return GRUB_TERM_NO_KEY; + } + + if (!err && (actual >= 3)) + grub_memcpy (termdata->last_report, + termdata->current_report, + sizeof (termdata->report)); + + grub_memcpy (termdata->current_report, + termdata->report, + sizeof (termdata->report)); + + termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev, + termdata->endp->endp_addr, + sizeof (termdata->report), + (char *) termdata->report); + if (!termdata->transfer) + { + grub_printf ("%s failed. Stopped\n", term->name); + termdata->dead = 1; + } + + termdata->last_key = -1; + + grub_dprintf ("usb_keyboard", + "err = %d, actual = %" PRIuGRUB_SIZE + " report: 0x%02x 0x%02x 0x%02x 0x%02x" + " 0x%02x 0x%02x 0x%02x 0x%02x\n", + err, actual, + termdata->current_report[0], termdata->current_report[1], + termdata->current_report[2], termdata->current_report[3], + termdata->current_report[4], termdata->current_report[5], + termdata->current_report[6], termdata->current_report[7]); + + if (err || actual < 1) + return GRUB_TERM_NO_KEY; + + termdata->status = termdata->current_report[0]; + + if (actual < 3) + return GRUB_TERM_NO_KEY; + + termdata->index = 2; /* New data received. */ + termdata->max_index = actual; + + return parse_keycode (termdata); +} + +static int +grub_usb_keyboard_getkeystatus (struct grub_term_input *term) +{ + struct grub_usb_keyboard_data *termdata = term->data; + + return interpret_status (termdata->status) | termdata->mods; +} + +struct grub_usb_attach_desc attach_hook = +{ + .class = GRUB_USB_CLASS_HID, + .hook = grub_usb_keyboard_attach +}; + +GRUB_MOD_INIT(usb_keyboard) +{ + grub_usb_register_attach_hook_class (&attach_hook); +} + +GRUB_MOD_FINI(usb_keyboard) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++) + if (grub_usb_keyboards[i].data) + { + struct grub_usb_keyboard_data *data = grub_usb_keyboards[i].data; + + if (!data) + continue; + + if (data->transfer) + grub_usb_cancel_transfer (data->transfer); + + grub_term_unregister_input (&grub_usb_keyboards[i]); + grub_free ((char *) grub_usb_keyboards[i].name); + grub_usb_keyboards[i].name = NULL; + grub_free (grub_usb_keyboards[i].data); + grub_usb_keyboards[i].data = 0; + } + grub_usb_unregister_attach_hook_class (&attach_hook); +} diff --git a/grub-core/tests/boot/kbsd.init-i386.S b/grub-core/tests/boot/kbsd.init-i386.S new file mode 100644 index 000000000..7011c79ff --- /dev/null +++ b/grub-core/tests/boot/kbsd.init-i386.S @@ -0,0 +1,125 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#ifdef TARGET_NETBSD +#define SYSCALL_RESET 208 +#elif defined (TARGET_OPENBSD) +#define SYSCALL_RESET 55 +#else +#error unknown target +#endif + +#define MODE_RDRW 2 +#define FLAGS_NONE 0 +#define SYSCALL_OPEN 5 +#define SYSCALL_WRITE 4 +#define SYSCALL_EXIT 1 +#define SYSCALL_ARCH 165 +#define SYSCALL_INT 0x80 +#define SYSCALL_ARCH_IOPL 2 + +#define RESET_NOSYNC 0x4 +#define RESET_HALT 0x8 +#define RESET_POWEROFF 0x800 + +#define SHUTDOWN_PORT 0x8900 + + .section ".init", "ax" + .global start,_start +start: +_start: + /* open. */ + movl $SYSCALL_OPEN, %eax + pushl $FLAGS_NONE + pushl $MODE_RDRW + leal device, %ebx + pushl %ebx + pushl $0 + int $SYSCALL_INT + addl $16, %esp + movl %eax, %ecx + + /* write. */ + movl $SYSCALL_WRITE, %eax + pushl $(messageend-message) + leal message, %ebx + pushl %ebx + pushl %ecx + pushl $0 + int $SYSCALL_INT + addl $16, %esp + + /* IOPL. */ + movl $SYSCALL_ARCH, %eax + pushl $iopl_arg + pushl $SYSCALL_ARCH_IOPL + pushl $0 + int $SYSCALL_INT + addl $12, %esp + + movw $SHUTDOWN_PORT, %dx + movb $'S', %al + outb %al, %dx + movb $'h', %al + outb %al, %dx + movb $'u', %al + outb %al, %dx + movb $'t', %al + outb %al, %dx + movb $'d', %al + outb %al, %dx + movb $'o', %al + outb %al, %dx + movb $'w', %al + outb %al, %dx + movb $'n', %al + outb %al, %dx + + /* shutdown. */ + movl $SYSCALL_RESET, %eax + pushl $0 + pushl $(RESET_POWEROFF|RESET_HALT|RESET_NOSYNC) + pushl $0 + int $SYSCALL_INT + addl $8, %esp + + /* exit (1). Shouldn't be reached. */ + movl $SYSCALL_EXIT, %eax + pushl $1 + pushl $0 + int $SYSCALL_INT + .section ".fini", "ax" +1: jmp 1b + .section ".text", "ax" +1: jmp 1b + /* This section is needed for NetBSD to identify the binary. */ + .section ".note.netbsd.ident", "a" + .long 0x7 + .long 0x4 + .long 0x1 + .ascii "NetBSD" + .byte 0 + .data +device: + .ascii "/dev/console" + .byte 0 +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" +messageend: +iopl_arg: + .long 3 diff --git a/grub-core/tests/boot/kbsd.init-x86_64.S b/grub-core/tests/boot/kbsd.init-x86_64.S new file mode 100644 index 000000000..81f810e2c --- /dev/null +++ b/grub-core/tests/boot/kbsd.init-x86_64.S @@ -0,0 +1,111 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#define MODE_RDRW 2 +#define FLAGS_NONE 0 +#define SYSCALL_OPEN 5 +#define SYSCALL_WRITE 4 +#ifdef TARGET_NETBSD +#define SYSCALL_RESET 208 +#elif defined (TARGET_OPENBSD) +#define SYSCALL_RESET 55 +#else +#error unknown target +#endif +#define SYSCALL_EXIT 1 +#define SYSCALL_ARCH 165 +#define SYSCALL_INT 0x80 +#define SYSCALL_ARCH_IOPL 2 + +#define RESET_NOSYNC 0x4 +#define RESET_HALT 0x8 +#define RESET_POWEROFF 0x800 +#define SHUTDOWN_PORT 0x8900 + + .section ".init", "ax" + .global start,_start +start: +_start: + /* open. */ + movq $SYSCALL_OPEN, %rax + leaq device, %rdi + movq $MODE_RDRW, %rsi + movq $FLAGS_NONE, %rdx + syscall + movq %rax, %rdi + + /* write. */ + movq $SYSCALL_WRITE, %rax + movq $(messageend-message), %rdx + leaq message, %rsi + syscall + + /* IOPL. */ + movq $SYSCALL_ARCH, %rax + movq $SYSCALL_ARCH_IOPL, %rdi + leaq iopl_arg, %rsi + syscall + + movw $SHUTDOWN_PORT, %dx + movb $'S', %al + outb %al, %dx + movb $'h', %al + outb %al, %dx + movb $'u', %al + outb %al, %dx + movb $'t', %al + outb %al, %dx + movb $'d', %al + outb %al, %dx + movb $'o', %al + outb %al, %dx + movb $'w', %al + outb %al, %dx + movb $'n', %al + outb %al, %dx + + /* shutdown. */ + movq $SYSCALL_RESET, %rax + movq $(RESET_POWEROFF|RESET_HALT|RESET_NOSYNC), %rdi + movq $0, %rsi + syscall + + /* exit (1). Shouldn't be reached. */ + movq $SYSCALL_EXIT, %rax + movq $1, %rdi + syscall + .section ".fini", "ax" +1: jmp 1b + .section ".text", "ax" +1: jmp 1b + /* This section is needed for NetBSD to identify the binary. */ + .section ".note.netbsd.ident", "a" + .long 0x7 + .long 0x4 + .long 0x1 + .ascii "NetBSD" + .byte 0 + .data +device: + .ascii "/dev/console" + .byte 0 +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" +messageend: +iopl_arg: + .long 3 diff --git a/grub-core/tests/boot/kbsd.spec.txt b/grub-core/tests/boot/kbsd.spec.txt new file mode 100644 index 000000000..af171bc56 --- /dev/null +++ b/grub-core/tests/boot/kbsd.spec.txt @@ -0,0 +1,3 @@ +. type=dir + dev type=dir + console type=char device=0 mode=666 gid=0 uid=0 diff --git a/grub-core/tests/boot/kernel-8086.S b/grub-core/tests/boot/kernel-8086.S new file mode 100644 index 000000000..20040dabc --- /dev/null +++ b/grub-core/tests/boot/kernel-8086.S @@ -0,0 +1,69 @@ + +#define SHUTDOWN_PORT 0x8900 + + .text + .globl _start +_start: +base: + .code16 + jmp cont + +portmsg: + xorw %ax, %ax +1: + movb 0(%si), %al + test %ax, %ax + jz 1f + outb %al, %dx + incw %si + jmp 1b +1: + ret + +serialmsg: +1: + movb 0(%si), %bl + testb %bl, %bl + jz 1f + movw $0x3fd, %dx +2: + inb %dx, %al + testb $0x20, %al + jz 2b + + movw $0x3f8, %dx + movb %bl, %al + outb %al, %dx + incw %si + jmp 1b +1: + ret + +cont: +#ifdef TARGET_NTLDR + movw $0x2000, %ax +#elif defined (TARGET_CHAINLOADER) + xorw %ax, %ax +#else +#error unsupported target +#endif + movw %ax, %ds + lea message, %si + call serialmsg + lea shutdown, %si + movw $SHUTDOWN_PORT, %dx + call portmsg + +1: + hlt + jmp 1b + +shutdown: + .ascii "Shutdown" + .byte 0 +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" + .byte 0 + + . = base + 510 + .short 0xaa55 \ No newline at end of file diff --git a/grub-core/tests/boot/kernel-i386.S b/grub-core/tests/boot/kernel-i386.S new file mode 100644 index 000000000..904b0d4c7 --- /dev/null +++ b/grub-core/tests/boot/kernel-i386.S @@ -0,0 +1,89 @@ +#define ASM_FILE 1 +#ifdef TARGET_MULTIBOOT2 +#include +#elif defined (TARGET_MULTIBOOT) +#include +#endif + +#define SHUTDOWN_PORT 0x8900 + + .text + /* Align 32 bits boundary. */ + .align 8 + +#ifdef TARGET_MULTIBOOT2 + /* Multiboot header. */ +multiboot_header: + /* magic */ + .long MULTIBOOT2_HEADER_MAGIC + /* ISA: i386 */ + .long MULTIBOOT_ARCHITECTURE_I386 + /* Header length. */ + .long multiboot_header_end - multiboot_header + /* checksum */ + .long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (multiboot_header_end - multiboot_header)) + .short MULTIBOOT_HEADER_TAG_END + .short 0 + .long 8 +multiboot_header_end: +#elif defined (TARGET_MULTIBOOT) + /* Multiboot header. */ +multiboot_header: + /* magic */ + .long MULTIBOOT_HEADER_MAGIC + /* flags */ + .long 0 + /* checksum */ + .long -MULTIBOOT_HEADER_MAGIC +#endif + + .global start +portmsg: + xorl %eax, %eax +1: + movb 0(%esi), %al + test %eax, %eax + jz 1f + outb %al, %dx + incl %esi + jmp 1b +1: + ret + +serialmsg: +1: + movb 0(%esi), %bl + testb %bl, %bl + jz 1f + movw $0x3fd, %dx +2: + inb %dx, %al + testb $0x20, %al + jz 2b + + movw $0x3f8, %dx + movb %bl, %al + outb %al, %dx + incl %esi + jmp 1b +1: + ret + + .globl _start +_start: + lea message, %esi + call serialmsg + lea shutdown, %esi + movw $SHUTDOWN_PORT, %dx + call portmsg + +1: + hlt + jmp 1b + +shutdown: + .ascii "Shutdown" + .byte 0 +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" + .byte 0 diff --git a/grub-core/tests/boot/kfreebsd-aout.cfg b/grub-core/tests/boot/kfreebsd-aout.cfg new file mode 100644 index 000000000..31e34b4ee --- /dev/null +++ b/grub-core/tests/boot/kfreebsd-aout.cfg @@ -0,0 +1,4 @@ +kfreebsd /kfreebsd.aout +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/kfreebsd.cfg b/grub-core/tests/boot/kfreebsd.cfg new file mode 100644 index 000000000..f28ee7998 --- /dev/null +++ b/grub-core/tests/boot/kfreebsd.cfg @@ -0,0 +1,8 @@ +kfreebsd /kfreebsd -hv +kfreebsd_loadenv /kfreebsd_env +kfreebsd_module /mfsroot.gz type=mfs_root +set kFreeBSD.hw.hasbrokenint12=1 +fakebios +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/kfreebsd.init-i386.S b/grub-core/tests/boot/kfreebsd.init-i386.S new file mode 100644 index 000000000..12c94a036 --- /dev/null +++ b/grub-core/tests/boot/kfreebsd.init-i386.S @@ -0,0 +1,114 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#define MODE_RDRW 2 +#define FLAGS_NONE 0 +#define SYSCALL_OPEN 5 +#define SYSCALL_WRITE 4 +#define SYSCALL_RESET 55 +#define SYSCALL_FSYNC 95 +#define SYSCALL_ARCH 165 +#define SYSCALL_EXIT 1 +#define SYSCALL_ARCH_IOPL 4 +#define SYSCALL_INT 0x80 + +#define RESET_NOSYNC 0x4 +#define RESET_HALT 0x8 +#define RESET_POWEROFF 0x4000 +#define SHUTDOWN_PORT 0x8900 + + .section ".init", "ax" + .global start,_start +start: +_start: + /* open. */ + movl $SYSCALL_OPEN, %eax + pushl $FLAGS_NONE + pushl $MODE_RDRW + leal device, %ebx + pushl %ebx + pushl $0 + int $SYSCALL_INT + addl $16, %esp + movl %eax, %ecx + + /* write. */ + movl $SYSCALL_WRITE, %eax + pushl $(messageend-message) + leal message, %ebx + pushl %ebx + pushl %ecx + pushl $0 + int $SYSCALL_INT + addl $16, %esp + + /* fsync. */ + movl $SYSCALL_FSYNC, %eax + pushl %ecx + pushl $0 + int $SYSCALL_INT + addl $8, %esp + + /* IOPL. */ + movl $SYSCALL_ARCH, %eax + pushl $iopl_arg + pushl $SYSCALL_ARCH_IOPL + pushl $0 + int $SYSCALL_INT + addl $12, %esp + + movw $SHUTDOWN_PORT, %dx + movb $'S', %al + outb %al, %dx + movb $'h', %al + outb %al, %dx + movb $'u', %al + outb %al, %dx + movb $'t', %al + outb %al, %dx + movb $'d', %al + outb %al, %dx + movb $'o', %al + outb %al, %dx + movb $'w', %al + outb %al, %dx + movb $'n', %al + outb %al, %dx + + /* shutdown. */ + movl $SYSCALL_RESET, %eax + pushl $(RESET_POWEROFF|RESET_HALT|RESET_NOSYNC) + pushl $0 + int $SYSCALL_INT + addl $8, %esp + + /* exit (1). Shouldn't be reached. */ + movl $SYSCALL_EXIT, %eax + pushl $1 + pushl $0 + int $SYSCALL_INT +device: + .ascii "/dev/console" + .byte 0 +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" +messageend: +iopl_arg: + .long SHUTDOWN_PORT + .long 1 + .long 1 diff --git a/grub-core/tests/boot/kfreebsd.init-x86_64.S b/grub-core/tests/boot/kfreebsd.init-x86_64.S new file mode 100644 index 000000000..0a9ff511e --- /dev/null +++ b/grub-core/tests/boot/kfreebsd.init-x86_64.S @@ -0,0 +1,98 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#define MODE_RDRW 2 +#define FLAGS_NONE 0 +#define SYSCALL_ARCH 165 +#define SYSCALL_OPEN 5 +#define SYSCALL_WRITE 4 +#define SYSCALL_RESET 55 +#define SYSCALL_EXIT 1 +#define SYSCALL_ARCH_IOPL 4 +#define SYSCALL_FSYNC 95 + +#define RESET_NOSYNC 0x4 +#define RESET_HALT 0x8 +#define RESET_POWEROFF 0x4000 +#define SHUTDOWN_PORT 0x8900 + + .section ".init", "ax" + .global start,_start +start: +_start: + /* open. */ + movq $SYSCALL_OPEN, %rax + leaq device, %rdi + movq $MODE_RDRW, %rsi + movq $FLAGS_NONE, %rdx + syscall + movq %rax, %rdi + + /* write. */ + leaq message, %rsi + movq $SYSCALL_WRITE, %rax + movq $(messageend - message), %rdx + syscall + + /* fsync. */ + movq $SYSCALL_FSYNC, %rax + syscall + + /* IOPL. */ + movq $SYSCALL_ARCH, %rax + movq $SYSCALL_ARCH_IOPL, %rdi + leaq iopl_arg, %rsi + syscall + + movw $SHUTDOWN_PORT, %dx + movb $'S', %al + outb %al, %dx + movb $'h', %al + outb %al, %dx + movb $'u', %al + outb %al, %dx + movb $'t', %al + outb %al, %dx + movb $'d', %al + outb %al, %dx + movb $'o', %al + outb %al, %dx + movb $'w', %al + outb %al, %dx + movb $'n', %al + outb %al, %dx + + /* shutdown. */ + movq $SYSCALL_RESET, %rax + movq $(RESET_POWEROFF|RESET_HALT|RESET_NOSYNC), %rdi + syscall + + /* exit (1). Shouldn't be reached. */ + movq $SYSCALL_EXIT, %rax + movq $1, %rdi + syscall +device: + .ascii "/dev/console" + .byte 0 +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" +messageend: +iopl_arg: + .long SHUTDOWN_PORT + .long 1 + .long 1 diff --git a/grub-core/tests/boot/knetbsd.cfg b/grub-core/tests/boot/knetbsd.cfg new file mode 100644 index 000000000..f88a846e1 --- /dev/null +++ b/grub-core/tests/boot/knetbsd.cfg @@ -0,0 +1,5 @@ +knetbsd /knetbsd -h +knetbsd_module_elf /miniroot.gz +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/kopenbsd.cfg b/grub-core/tests/boot/kopenbsd.cfg new file mode 100644 index 000000000..132bec4b6 --- /dev/null +++ b/grub-core/tests/boot/kopenbsd.cfg @@ -0,0 +1,5 @@ +kopenbsd /kopenbsd -h +kopenbsd_ramdisk /ramdisk +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/kopenbsdlabel.txt b/grub-core/tests/boot/kopenbsdlabel.txt new file mode 100644 index 000000000..bb141133b --- /dev/null +++ b/grub-core/tests/boot/kopenbsdlabel.txt @@ -0,0 +1,3 @@ +# size offset fstype [fsize bsize bps/cpg] + a: 256 0 4.2BSD 0 0 1 + c: 256 0 unused 0 0 # "raw" part, don't edit diff --git a/grub-core/tests/boot/linux.cfg b/grub-core/tests/boot/linux.cfg new file mode 100644 index 000000000..f5bf6ac7d --- /dev/null +++ b/grub-core/tests/boot/linux.cfg @@ -0,0 +1,5 @@ +linux /linux console=ttyS0 root=/dev/ram0 +initrd /initrd +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/linux.init-i386.S b/grub-core/tests/boot/linux.init-i386.S new file mode 100644 index 000000000..5b0088e00 --- /dev/null +++ b/grub-core/tests/boot/linux.init-i386.S @@ -0,0 +1,79 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#define SYSCALL_WRITE 4 +#define SYSCALL_RESET 88 +#define SYSCALL_IOPL 110 +#define SYSCALL_EXIT 1 +#define SYSCALL_INT 0x80 + +#define STDOUT 1 +#define SHUTDOWN_MAGIC1 0xfee1dead +#define SHUTDOWN_MAGIC2 0x28121969 +#define SHUTDOWN_MAGIC3 0x4321fedc + +#define SHUTDOWN_PORT 0x8900 + + .text + .global start, _start +_start: +start: + /* write. */ + movl $SYSCALL_WRITE, %eax + movl $STDOUT, %ebx + leal message, %ecx + movl $(messageend-message), %edx + int $SYSCALL_INT + + movl $SYSCALL_IOPL, %eax + movl $3, %ebx + int $SYSCALL_INT + + movw $SHUTDOWN_PORT, %dx + movb $'S', %al + outb %al, %dx + movb $'h', %al + outb %al, %dx + movb $'u', %al + outb %al, %dx + movb $'t', %al + outb %al, %dx + movb $'d', %al + outb %al, %dx + movb $'o', %al + outb %al, %dx + movb $'w', %al + outb %al, %dx + movb $'n', %al + outb %al, %dx + + /* shutdown. */ + movl $SYSCALL_RESET, %eax + movl $SHUTDOWN_MAGIC1, %ebx + movl $SHUTDOWN_MAGIC2, %ecx + movl $SHUTDOWN_MAGIC3, %edx + int $SYSCALL_INT + + /* exit (1). Shouldn't be reached. */ + movl $SYSCALL_EXIT, %eax + movl $1, %ebx + int $SYSCALL_INT + .data +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" +messageend: diff --git a/grub-core/tests/boot/linux.init-x86_64.S b/grub-core/tests/boot/linux.init-x86_64.S new file mode 100644 index 000000000..fc32dfd91 --- /dev/null +++ b/grub-core/tests/boot/linux.init-x86_64.S @@ -0,0 +1,78 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#define SYSCALL_WRITE 1 +#define SYSCALL_RESET 169 +#define SYSCALL_IOPL 172 +#define SYSCALL_EXIT 60 + +#define STDOUT 1 +#define SHUTDOWN_MAGIC1 0xfee1dead +#define SHUTDOWN_MAGIC2 0x28121969 +#define SHUTDOWN_MAGIC3 0x4321fedc + +#define SHUTDOWN_PORT 0x8900 + + .text + .global start, _start +_start: +start: + /* write. */ + movq $SYSCALL_WRITE, %rax + movq $STDOUT, %rdi + leaq message, %rsi + movq $(messageend-message), %rdx + syscall + + movq $SYSCALL_IOPL, %rax + movq $3, %rdi + syscall + + movw $SHUTDOWN_PORT, %dx + movb $'S', %al + outb %al, %dx + movb $'h', %al + outb %al, %dx + movb $'u', %al + outb %al, %dx + movb $'t', %al + outb %al, %dx + movb $'d', %al + outb %al, %dx + movb $'o', %al + outb %al, %dx + movb $'w', %al + outb %al, %dx + movb $'n', %al + outb %al, %dx + + /* shutdown. */ + movq $SYSCALL_RESET, %rax + movq $SHUTDOWN_MAGIC1, %rdi + movq $SHUTDOWN_MAGIC2, %rsi + movq $SHUTDOWN_MAGIC3, %rdx + syscall + + /* exit(1). Shouldn't be reached. */ + movq $SYSCALL_EXIT, %rax + movq $1, %rdi + syscall + .data +message: + .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" +messageend: diff --git a/grub-core/tests/boot/linux16.cfg b/grub-core/tests/boot/linux16.cfg new file mode 100644 index 000000000..d7fbf961c --- /dev/null +++ b/grub-core/tests/boot/linux16.cfg @@ -0,0 +1,5 @@ +linux16 /linux console=ttyS0 root=/dev/ram0 +initrd16 /initrd +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/multiboot.cfg b/grub-core/tests/boot/multiboot.cfg new file mode 100644 index 000000000..0942ec67c --- /dev/null +++ b/grub-core/tests/boot/multiboot.cfg @@ -0,0 +1,4 @@ +multiboot /multiboot.elf +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/multiboot2.cfg b/grub-core/tests/boot/multiboot2.cfg new file mode 100644 index 000000000..2bec9e6d1 --- /dev/null +++ b/grub-core/tests/boot/multiboot2.cfg @@ -0,0 +1,4 @@ +multiboot2 /multiboot2.elf +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/ntldr.cfg b/grub-core/tests/boot/ntldr.cfg new file mode 100644 index 000000000..cd438a4bc --- /dev/null +++ b/grub-core/tests/boot/ntldr.cfg @@ -0,0 +1,4 @@ +ntldr /ntldr.bin +boot +# Shouln't happen +halt diff --git a/grub-core/tests/boot/pc-chainloader.cfg b/grub-core/tests/boot/pc-chainloader.cfg new file mode 100644 index 000000000..1e80a5b96 --- /dev/null +++ b/grub-core/tests/boot/pc-chainloader.cfg @@ -0,0 +1,4 @@ +chainloader /pc-chainloader.bin +boot +# Shouln't happen +halt diff --git a/tests/example_functional_test.c b/grub-core/tests/example_functional_test.c similarity index 95% rename from tests/example_functional_test.c rename to grub-core/tests/example_functional_test.c index 6802d2d53..525988145 100644 --- a/tests/example_functional_test.c +++ b/grub-core/tests/example_functional_test.c @@ -32,4 +32,4 @@ example_test (void) } /* Register example_test method as a functional test. */ -GRUB_FUNCTIONAL_TEST ("example_functional_test", example_test); +GRUB_FUNCTIONAL_TEST (example_functional_test, example_test); diff --git a/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c similarity index 91% rename from tests/lib/functional_test.c rename to grub-core/tests/lib/functional_test.c index 6aafe4dbb..521f4ad22 100644 --- a/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -22,7 +22,7 @@ #include static grub_err_t -grub_functional_test (struct grub_extcmd *cmd __attribute__ ((unused)), +grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { @@ -37,8 +37,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (functional_test) { - cmd = grub_register_extcmd ("functional_test", grub_functional_test, - GRUB_COMMAND_FLAG_CMDLINE, 0, + cmd = grub_register_extcmd ("functional_test", grub_functional_test, 0, 0, "Run all functional tests.", 0); } diff --git a/tests/lib/test.c b/grub-core/tests/lib/test.c similarity index 100% rename from tests/lib/test.c rename to grub-core/tests/lib/test.c diff --git a/commands/i386/pc/halt.c b/grub-core/tests/test_blockarg.c similarity index 54% rename from commands/i386/pc/halt.c rename to grub-core/tests/test_blockarg.c index 4c39612ae..41460fb7e 100644 --- a/commands/i386/pc/halt.c +++ b/grub-core/tests/test_blockarg.c @@ -1,7 +1,7 @@ -/* halt.c - command to halt the computer. */ +/* test_blockarg.c - print and execute block argument */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007,2009 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 @@ -18,41 +18,34 @@ */ #include +#include #include -#include #include - -static const struct grub_arg_option options[] = - { - {"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0}, - {0, 0, 0, 0, 0, 0} - }; +#include +#include static grub_err_t -grub_cmd_halt (grub_extcmd_t cmd, - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) - +test_blockarg (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; - int no_apm = 0; - if (state[0].set) - no_apm = 1; - grub_halt (no_apm); - return 0; + if (! ctxt->script) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no block parameter"); + + grub_printf ("%s\n", args[argc - 1]); + grub_script_execute (ctxt->script); + return GRUB_ERR_NONE; } static grub_extcmd_t cmd; - -GRUB_MOD_INIT(halt) + +GRUB_MOD_INIT(test_blockarg) { - cmd = grub_register_extcmd ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH, - "[-n]", - N_("Halt the system, if possible using APM."), - options); + cmd = grub_register_extcmd ("test_blockarg", test_blockarg, + GRUB_COMMAND_FLAG_BLOCKS, + N_("BLOCK"), + N_("Print and execute block argument."), 0); } -GRUB_MOD_FINI(halt) +GRUB_MOD_FINI(test_blockarg) { grub_unregister_extcmd (cmd); } diff --git a/video/bitmap.c b/grub-core/video/bitmap.c similarity index 100% rename from video/bitmap.c rename to grub-core/video/bitmap.c diff --git a/video/bitmap_scale.c b/grub-core/video/bitmap_scale.c similarity index 100% rename from video/bitmap_scale.c rename to grub-core/video/bitmap_scale.c diff --git a/video/bochs.c b/grub-core/video/bochs.c similarity index 100% rename from video/bochs.c rename to grub-core/video/bochs.c diff --git a/video/cirrus.c b/grub-core/video/cirrus.c similarity index 92% rename from video/cirrus.c rename to grub-core/video/cirrus.c index ccbab9d15..b8b0142ad 100644 --- a/video/cirrus.c +++ b/grub-core/video/cirrus.c @@ -334,43 +334,26 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, } { - int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; + struct grub_video_hw_config config = { + .pitch = pitch / GRUB_VGA_CR_PITCH_DIVISOR, + .line_compare = 0x3ff, + .vdisplay_end = height - 1, + .horizontal_end = width / GRUB_VGA_CR_WIDTH_DIVISOR + }; grub_uint8_t sr_ext = 0, hidden_dac = 0; - pitch_reg = pitch / GRUB_VGA_CR_PITCH_DIVISOR; - + grub_vga_set_geometry (&config, grub_vga_cr_write); + grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1, GRUB_VGA_GR_MODE); grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); - /* Disable CR0-7 write protection. */ - grub_vga_cr_write (0, GRUB_VGA_CR_VSYNC_END); - - grub_vga_cr_write (width / GRUB_VGA_CR_WIDTH_DIVISOR - 1, - GRUB_VGA_CR_WIDTH); - grub_vga_cr_write ((height - 1) & 0xff, GRUB_VGA_CR_HEIGHT); - overflow_reg |= (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & - GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) - | (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) & - GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK); - - grub_vga_cr_write (pitch_reg & 0xff, GRUB_VGA_CR_PITCH); - - grub_vga_cr_write (line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); - overflow_reg |= (line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) - & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK; - - grub_vga_cr_write (overflow_reg, GRUB_VGA_CR_OVERFLOW); - - grub_vga_cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) + grub_vga_cr_write ((config.pitch >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK, CIRRUS_CR_EXTENDED_DISPLAY); - grub_vga_cr_write ((line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) - & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK, GRUB_VGA_CR_CELL_HEIGHT); - grub_vga_cr_write (GRUB_VGA_CR_MODE_TIMING_ENABLE | GRUB_VGA_CR_MODE_BYTE_MODE | GRUB_VGA_CR_MODE_NO_HERCULES | GRUB_VGA_CR_MODE_NO_CGA, diff --git a/video/efi_gop.c b/grub-core/video/efi_gop.c similarity index 91% rename from video/efi_gop.c rename to grub-core/video/efi_gop.c index 4e79b8521..f02dc9cb6 100644 --- a/video/efi_gop.c +++ b/grub-core/video/efi_gop.c @@ -127,9 +127,11 @@ grub_video_gop_get_bitmask (grub_uint32_t mask, unsigned int *mask_size, } static grub_err_t -grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, +grub_video_gop_fill_mode_info (unsigned mode, + struct grub_efi_gop_mode_info *in, struct grub_video_mode_info *out) { + out->mode_number = mode; out->number_of_colors = 256; out->width = in->width; out->height = in->height; @@ -183,9 +185,43 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, return GRUB_ERR_NONE; } +static int +grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info)) +{ + unsigned mode; + + for (mode = 0; mode < gop->mode->max_mode; mode++) + { + grub_efi_uintn_t size; + grub_efi_status_t status; + struct grub_efi_gop_mode_info *info = NULL; + grub_err_t err; + struct grub_video_mode_info mode_info; + + status = efi_call_4 (gop->query_mode, gop, mode, &size, &info); + + if (status) + { + info = 0; + continue; + } + + err = grub_video_gop_fill_mode_info (mode, info, &mode_info); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (hook (&mode_info)) + return 1; + } + return 0; +} + static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; struct grub_efi_gop_mode_info *info = NULL; @@ -226,7 +262,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height, if (status) { info = 0; - break; + continue; } grub_dprintf ("video", "GOP: mode %d: %dx%d\n", mode, info->width, @@ -281,7 +317,8 @@ grub_video_gop_setup (unsigned int width, unsigned int height, info = gop->mode->info; - err = grub_video_gop_fill_mode_info (info, &framebuffer.mode_info); + err = grub_video_gop_fill_mode_info (gop->mode->mode, info, + &framebuffer.mode_info); if (err) { grub_dprintf ("video", "GOP: couldn't fill mode info\n"); @@ -379,6 +416,7 @@ static struct grub_video_adapter grub_video_gop_adapter = .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_gop_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, + .iterate = grub_video_gop_iterate, .next = 0 }; diff --git a/video/efi_uga.c b/grub-core/video/efi_uga.c similarity index 98% rename from video/efi_uga.c rename to grub-core/video/efi_uga.c index 6352d4342..a8f70edea 100644 --- a/video/efi_uga.c +++ b/grub-core/video/efi_uga.c @@ -198,7 +198,8 @@ grub_video_uga_fini (void) static grub_err_t grub_video_uga_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; int found = 0; diff --git a/video/emu/sdl.c b/grub-core/video/emu/sdl.c similarity index 100% rename from video/emu/sdl.c rename to grub-core/video/emu/sdl.c diff --git a/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c similarity index 100% rename from video/fb/fbblit.c rename to grub-core/video/fb/fbblit.c diff --git a/video/fb/fbfill.c b/grub-core/video/fb/fbfill.c similarity index 100% rename from video/fb/fbfill.c rename to grub-core/video/fb/fbfill.c diff --git a/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c similarity index 100% rename from video/fb/fbutil.c rename to grub-core/video/fb/fbutil.c diff --git a/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c similarity index 100% rename from video/fb/video_fb.c rename to grub-core/video/fb/video_fb.c diff --git a/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c similarity index 59% rename from video/i386/pc/vbe.c rename to grub-core/video/i386/pc/vbe.c index 7581c48b1..2ddb4ca80 100644 --- a/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -28,11 +28,11 @@ #include #include #include +#include static int vbe_detected = -1; static struct grub_vbe_info_block controller_info; -static struct grub_vbe_mode_info_block active_vbe_mode_info; /* Track last mode to support cards which fail on get_mode. */ static grub_uint32_t last_set_mode = 3; @@ -41,11 +41,7 @@ static struct { struct grub_video_mode_info mode_info; - unsigned int bytes_per_scan_line; - unsigned int bytes_per_pixel; - grub_uint32_t active_vbe_mode; grub_uint8_t *ptr; - int index_color_mode; } framebuffer; static grub_uint32_t initial_vbe_mode; @@ -58,6 +54,226 @@ real2pm (grub_vbe_farptr_t ptr) + ((unsigned long) ptr & 0x0000FFFF)); } +/* Call VESA BIOS 0x4f09 to set palette data, return status. */ +static grub_vbe_status_t +grub_vbe_bios_set_palette_data (grub_uint32_t color_count, + grub_uint32_t start_index, + struct grub_vbe_palette_data *palette_data) +{ + struct grub_bios_int_registers regs; + regs.eax = 0x4f09; + regs.ebx = 0; + regs.ecx = color_count; + regs.edx = start_index; + regs.es = (((grub_addr_t) palette_data) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) palette_data) & 0xffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_controller_info (struct grub_vbe_info_block *ci) +{ + struct grub_bios_int_registers regs; + /* Store *controller_info to %es:%di. */ + regs.es = (((grub_addr_t) ci) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) ci) & 0xffff; + regs.eax = 0x4f00; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_mode_info (grub_uint32_t mode, + struct grub_vbe_mode_info_block *mode_info) +{ + struct grub_bios_int_registers regs; + regs.eax = 0x4f01; + regs.ecx = mode; + /* Store *mode_info to %es:%di. */ + regs.es = ((grub_addr_t) mode_info & 0xffff0000) >> 4; + regs.edi = (grub_addr_t) mode_info & 0x0000ffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f02 to set video mode, return status. */ +static grub_vbe_status_t +grub_vbe_bios_set_mode (grub_uint32_t mode, + struct grub_vbe_crtc_info_block *crtc_info) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f02; + regs.ebx = mode; + /* Store *crtc_info to %es:%di. */ + regs.es = (((grub_addr_t) crtc_info) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) crtc_info) & 0xffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_mode (grub_uint32_t *mode) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f03; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + *mode = regs.ebx & 0xffff; + + return regs.eax & 0xffff; +} + +grub_vbe_status_t +grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f08; + regs.ebx = (*dac_mask_size & 0xff) >> 8; + regs.ebx = set ? 1 : 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + *dac_mask_size = (regs.ebx >> 8) & 0xff; + + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f05 to set memory window, return status. */ +grub_vbe_status_t +grub_vbe_bios_set_memory_window (grub_uint32_t window, + grub_uint32_t position) +{ + struct grub_bios_int_registers regs; + + /* BL = window, BH = 0, Set memory window. */ + regs.ebx = window & 0x00ff; + regs.edx = position; + regs.eax = 0x4f05; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f05 to return memory window, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_memory_window (grub_uint32_t window, + grub_uint32_t *position) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f05; + /* BH = 1, Get memory window. BL = window. */ + regs.ebx = (window & 0x00ff) | 0x100; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + *position = regs.edx & 0xffff; + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */ +grub_vbe_status_t +grub_vbe_bios_set_scanline_length (grub_uint32_t length) +{ + struct grub_bios_int_registers regs; + + regs.ecx = length; + regs.eax = 0x4f06; + /* BL = 2, Set Scan Line in Bytes. */ + regs.ebx = 0x0002; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */ +grub_vbe_status_t +grub_vbe_bios_get_scanline_length (grub_uint32_t *length) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f06; + regs.ebx = 0x0001; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + /* BL = 1, Get Scan Line Length (in bytes). */ + grub_bios_interrupt (0x10, ®s); + + *length = regs.ebx & 0xffff; + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f07 to set display start, return status. */ +static grub_vbe_status_t +grub_vbe_bios_set_display_start (grub_uint32_t x, grub_uint32_t y) +{ + struct grub_bios_int_registers regs; + + /* Store x in %ecx. */ + regs.ecx = x; + regs.edx = y; + regs.eax = 0x4f07; + /* BL = 80h, Set Display Start during Vertical Retrace. */ + regs.ebx = 0x0080; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f07 to get display start, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_display_start (grub_uint32_t *x, + grub_uint32_t *y) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f07; + /* BL = 1, Get Display Start. */ + regs.ebx = 0x0001; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + *x = regs.ecx & 0xffff; + *y = regs.edx & 0xffff; + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f0a. */ +grub_vbe_status_t +grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset, + grub_uint16_t *length) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f0a; + regs.ebx = 0x0000; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + if ((regs.eax & 0xffff) != GRUB_VBE_STATUS_OK) + { + *segment = 0; + *offset = 0; + *length = 0; + } + + *segment = regs.es & 0xffff; + *offset = regs.edi & 0xffff; + *length = regs.ecx & 0xffff; + return regs.eax & 0xffff; +} + + grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block) { @@ -137,21 +353,12 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, vbe_mode |= 1 << 14; /* Determine frame buffer pixel format. */ - switch (new_vbe_mode_info.memory_model) - { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - framebuffer.index_color_mode = 1; - break; - - case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - framebuffer.index_color_mode = 0; - break; - - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported pixel format 0x%x", - new_vbe_mode_info.memory_model); - } + if (new_vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL + && new_vbe_mode_info.memory_model + != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported pixel format 0x%x", + new_vbe_mode_info.memory_model); } /* Get current mode. */ @@ -165,24 +372,14 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", vbe_mode); last_set_mode = vbe_mode; - /* Save information for later usage. */ - framebuffer.active_vbe_mode = vbe_mode; - grub_memcpy (&active_vbe_mode_info, &new_vbe_mode_info, sizeof (active_vbe_mode_info)); - if (vbe_mode < 0x100) { /* If this is not a VESA mode, guess address. */ framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR; - framebuffer.index_color_mode = 1; } else { framebuffer.ptr = (grub_uint8_t *) new_vbe_mode_info.phys_base_addr; - - if (controller_info.version >= 0x300) - framebuffer.bytes_per_scan_line = new_vbe_mode_info.lin_bytes_per_scan_line; - else - framebuffer.bytes_per_scan_line = new_vbe_mode_info.bytes_per_scan_line; } /* Check whether mode is text mode or graphics mode. */ @@ -197,25 +394,9 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, { /* Graphics mode. */ - /* Calculate bytes_per_pixel value. */ - switch(new_vbe_mode_info.bits_per_pixel) - { - case 32: framebuffer.bytes_per_pixel = 4; break; - case 24: framebuffer.bytes_per_pixel = 3; break; - case 16: framebuffer.bytes_per_pixel = 2; break; - case 15: framebuffer.bytes_per_pixel = 2; break; - case 8: framebuffer.bytes_per_pixel = 1; break; - default: - grub_vbe_bios_set_mode (old_vbe_mode, 0); - last_set_mode = old_vbe_mode; - return grub_error (GRUB_ERR_BAD_DEVICE, - "cannot set VBE mode %x", - vbe_mode); - break; - } - /* If video mode is in indexed color, setup default VGA palette. */ - if (framebuffer.index_color_mode) + if (vbe_mode < 0x100 || new_vbe_mode_info.memory_model + == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL) { struct grub_vbe_palette_data *palette = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -353,10 +534,13 @@ grub_video_vbe_fini (void) grub_err_t err; /* Restore old video mode. */ - status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); - if (status != GRUB_VBE_STATUS_OK) - /* TODO: Decide, is this something we want to do. */ - return grub_errno; + if (last_set_mode != initial_vbe_mode) + { + status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); + if (status != GRUB_VBE_STATUS_OK) + /* TODO: Decide, is this something we want to do. */ + return grub_errno; + } last_set_mode = initial_vbe_mode; /* TODO: Free any resources allocated by driver. */ @@ -388,6 +572,120 @@ doublebuf_pageflipping_set_page (int page) return 0; } +static void +vbe2videoinfo (grub_uint32_t mode, + const struct grub_vbe_mode_info_block *vbeinfo, + struct grub_video_mode_info *mode_info) +{ + mode_info->mode_number = mode; + + mode_info->width = vbeinfo->x_resolution; + mode_info->height = vbeinfo->y_resolution; + mode_info->mode_type = 0; + switch (vbeinfo->memory_model) + { + case GRUB_VBE_MEMORY_MODEL_TEXT: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PURE_TEXT; + break; + + /* CGA is basically 4-bit packed pixel. */ + case GRUB_VBE_MEMORY_MODEL_CGA: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_CGA; + case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + + case GRUB_VBE_MEMORY_MODEL_HERCULES: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_HERCULES + | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP; + break; + + /* Non chain 4 is a special case of planar. */ + case GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_NONCHAIN4; + case GRUB_VBE_MEMORY_MODEL_PLANAR: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR + | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + + case GRUB_VBE_MEMORY_MODEL_YUV: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_YUV; + break; + + case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + break; + default: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UNKNOWN; + break; + } + + mode_info->bpp = vbeinfo->bits_per_pixel; + /* Calculate bytes_per_pixel value. */ + switch(vbeinfo->bits_per_pixel) + { + case 32: + mode_info->bytes_per_pixel = 4; + break; + case 24: + mode_info->bytes_per_pixel = 3; + break; + case 16: + mode_info->bytes_per_pixel = 2; + break; + case 15: + mode_info->bytes_per_pixel = 2; + break; + case 8: + mode_info->bytes_per_pixel = 1; + break; + case 4: + mode_info->bytes_per_pixel = 0; + break; + } + + if (controller_info.version >= 0x300) + mode_info->pitch = vbeinfo->lin_bytes_per_scan_line; + else + mode_info->pitch = vbeinfo->bytes_per_scan_line; + + mode_info->number_of_colors = 256; /* TODO: fix me. */ + mode_info->red_mask_size = vbeinfo->red_mask_size; + mode_info->red_field_pos = vbeinfo->red_field_position; + mode_info->green_mask_size = vbeinfo->green_mask_size; + mode_info->green_field_pos = vbeinfo->green_field_position; + mode_info->blue_mask_size = vbeinfo->blue_mask_size; + mode_info->blue_field_pos = vbeinfo->blue_field_position; + mode_info->reserved_mask_size = vbeinfo->rsvd_mask_size; + mode_info->reserved_field_pos = vbeinfo->rsvd_field_position; + + mode_info->blit_format = grub_video_get_blit_format (mode_info); +} + +static int +grub_video_vbe_iterate (int (*hook) (const struct grub_video_mode_info *info)) +{ + grub_uint16_t *p; + struct grub_vbe_mode_info_block vbe_mode_info; + struct grub_video_mode_info mode_info; + + for (p = vbe_mode_list; *p != 0xFFFF; p++) + { + grub_vbe_get_video_mode_info (*p, &vbe_mode_info); + if (grub_errno != GRUB_ERR_NONE) + { + /* Could not retrieve mode info, retreat. */ + grub_errno = GRUB_ERR_NONE; + break; + } + + vbe2videoinfo (*p, &vbe_mode_info, &mode_info); + if (hook (&mode_info)) + return 1; + } + return 0; +} + static grub_err_t grub_video_vbe_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask) @@ -436,6 +734,14 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Not compatible memory model. */ continue; + if (vbe_mode_info.bits_per_pixel != 8 + && vbe_mode_info.bits_per_pixel != 15 + && vbe_mode_info.bits_per_pixel != 16 + && vbe_mode_info.bits_per_pixel != 24 + && vbe_mode_info.bits_per_pixel != 32) + /* Unsupported bitdepth . */ + continue; + if (((vbe_mode_info.x_resolution != width) || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) /* Non matching resolution. */ @@ -481,36 +787,16 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, if (best_vbe_mode != 0) { grub_err_t err; + static struct grub_vbe_mode_info_block active_vbe_mode_info; /* If this fails, then we have mode selection heuristics problem, or adapter failure. */ - /* grub_vbe_set_video_mode already sets active_vbe_mode_info. */ - grub_vbe_set_video_mode (best_vbe_mode, NULL); + grub_vbe_set_video_mode (best_vbe_mode, &active_vbe_mode_info); if (grub_errno != GRUB_ERR_NONE) return grub_errno; /* Fill mode info details. */ - framebuffer.mode_info.width = active_vbe_mode_info.x_resolution; - framebuffer.mode_info.height = active_vbe_mode_info.y_resolution; - - if (framebuffer.index_color_mode) - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; - else - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; - - framebuffer.mode_info.bpp = active_vbe_mode_info.bits_per_pixel; - framebuffer.mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel; - framebuffer.mode_info.pitch = framebuffer.bytes_per_scan_line; - framebuffer.mode_info.number_of_colors = 256; /* TODO: fix me. */ - framebuffer.mode_info.red_mask_size = active_vbe_mode_info.red_mask_size; - framebuffer.mode_info.red_field_pos = active_vbe_mode_info.red_field_position; - framebuffer.mode_info.green_mask_size = active_vbe_mode_info.green_mask_size; - framebuffer.mode_info.green_field_pos = active_vbe_mode_info.green_field_position; - framebuffer.mode_info.blue_mask_size = active_vbe_mode_info.blue_mask_size; - framebuffer.mode_info.blue_field_pos = active_vbe_mode_info.blue_field_position; - framebuffer.mode_info.reserved_mask_size = active_vbe_mode_info.rsvd_mask_size; - framebuffer.mode_info.reserved_field_pos = active_vbe_mode_info.rsvd_field_position; - - framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + vbe2videoinfo (best_vbe_mode, &active_vbe_mode_info, + &framebuffer.mode_info); { /* Get video RAM size in bytes. */ @@ -545,7 +831,7 @@ static grub_err_t grub_video_vbe_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { - if (framebuffer.index_color_mode) + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) { /* TODO: Implement setting indexed color mode palette to hardware. */ //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) @@ -569,6 +855,20 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } +static void +grub_video_vbe_print_adapter_specific_info (void) +{ + grub_printf (" VBE info: version: %d.%d OEM software rev: %d.%d\n", + controller_info.version >> 8, + controller_info.version & 0xFF, + controller_info.oem_software_rev >> 8, + controller_info.oem_software_rev & 0xFF); + + /* The total_memory field is in 64 KiB units. */ + grub_printf (" total memory: %d KiB\n", + (controller_info.total_memory << 16) / 1024); +} + static struct grub_video_adapter grub_video_vbe_adapter = { .name = "VESA BIOS Extension Video Driver", @@ -598,6 +898,8 @@ static struct grub_video_adapter grub_video_vbe_adapter = .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, + .iterate = grub_video_vbe_iterate, + .print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info, .next = 0 }; diff --git a/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c similarity index 95% rename from video/i386/pc/vga.c rename to grub-core/video/i386/pc/vga.c index 3fbb18bb0..41b8d3eb1 100644 --- a/video/i386/pc/vga.c +++ b/grub-core/video/i386/pc/vga.c @@ -19,6 +19,7 @@ #define grub_video_render_target grub_video_fbrender_target #include +#include #include #include #include @@ -46,6 +47,25 @@ static struct int back_page; } framebuffer; +static unsigned char +grub_vga_set_mode (unsigned char mode) +{ + struct grub_bios_int_registers regs; + unsigned char ret; + /* get current mode */ + regs.eax = 0x0f00; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + ret = regs.eax & 0xff; + regs.eax = mode; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + return ret; +} + static inline void wait_vretrace (void) { diff --git a/video/ieee1275.c b/grub-core/video/ieee1275.c similarity index 91% rename from video/ieee1275.c rename to grub-core/video/ieee1275.c index 9c9477c2b..501ba7c2f 100644 --- a/video/ieee1275.c +++ b/grub-core/video/ieee1275.c @@ -32,6 +32,8 @@ static unsigned old_width, old_height; static int restore_needed; static char *display; +static grub_ieee1275_ihandle_t stdout_ihandle; +static int have_setcolors = 0; static struct { @@ -72,7 +74,17 @@ find_display (void) static grub_err_t grub_video_ieee1275_init (void) { + grub_ssize_t actual; + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS) + && !grub_ieee1275_get_integer_property (grub_ieee1275_chosen, + "stdout", &stdout_ihandle, + sizeof (stdout_ihandle), &actual) + && actual == sizeof (stdout_ihandle)) + have_setcolors = 1; + return grub_video_fb_init (); } @@ -169,9 +181,6 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height, /* For some reason sparc64 uses 32-bit pointer too. */ framebuffer.ptr = (void *) (grub_addr_t) address; - grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - grub_dprintf ("video", "IEEE1275: initialising FB @ %p %dx%dx%d\n", framebuffer.ptr, framebuffer.mode_info.width, framebuffer.mode_info.height, framebuffer.mode_info.bpp); @@ -192,15 +201,10 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height, grub_dprintf ("video", "IEEE1275: Couldn't set FB target\n"); return err; } - - err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - if (err) - grub_dprintf ("video", "IEEE1275: Couldn't set palette\n"); - else - grub_dprintf ("video", "IEEE1275: Success\n"); - + grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; } @@ -243,9 +247,17 @@ grub_video_ieee1275_set_palette (unsigned int start, unsigned int count, if (err) return err; - grub_video_fb_get_palette (0, 256, fb_palette_data); + grub_video_fb_get_palette (0, ARRAY_SIZE (fb_palette_data), fb_palette_data); - /* TODO. */ + /* Set colors. */ + if (have_setcolors) + { + unsigned col; + for (col = 0; col < ARRAY_SIZE (fb_palette_data); col++) + grub_ieee1275_set_color (stdout_ihandle, col, fb_palette_data[col].r, + fb_palette_data[col].g, + fb_palette_data[col].b); + } return GRUB_ERR_NONE; } diff --git a/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c similarity index 100% rename from video/readers/jpeg.c rename to grub-core/video/readers/jpeg.c diff --git a/video/readers/png.c b/grub-core/video/readers/png.c similarity index 100% rename from video/readers/png.c rename to grub-core/video/readers/png.c diff --git a/video/readers/tga.c b/grub-core/video/readers/tga.c similarity index 100% rename from video/readers/tga.c rename to grub-core/video/readers/tga.c diff --git a/grub-core/video/sm712.c b/grub-core/video/sm712.c new file mode 100644 index 000000000..60f2c9089 --- /dev/null +++ b/grub-core/video/sm712.c @@ -0,0 +1,787 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,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 . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm712_init.c" + +#define GRUB_SM712_TOTAL_MEMORY_SPACE 0x700400 +#define GRUB_SM712_REG_BASE 0x700000 +#define GRUB_SM712_PCIID 0x0712126f + +enum + { + GRUB_SM712_SR_TV_CONTROL = 0x65, + GRUB_SM712_SR_RAM_LUT = 0x66, + GRUB_SM712_SR_CLOCK_CONTROL1 = 0x68, + GRUB_SM712_SR_CLOCK_CONTROL2 = 0x69, + GRUB_SM712_SR_VCLK_NUM = 0x6c, + GRUB_SM712_SR_VCLK_DENOM = 0x6d, + GRUB_SM712_SR_VCLK2_NUM = 0x6e, + GRUB_SM712_SR_VCLK2_DENOM = 0x6f, + GRUB_SM712_SR_POPUP_ICON_LOW = 0x80, + GRUB_SM712_SR_POPUP_ICON_HIGH = 0x81, + GRUB_SM712_SR_POPUP_ICON_CTRL = 0x82, + GRUB_SM712_SR_POPUP_ICON_COLOR1 = 0x84, + GRUB_SM712_SR_POPUP_ICON_COLOR2 = 0x85, + GRUB_SM712_SR_POPUP_ICON_COLOR3 = 0x86, + + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_LOW = 0x88, + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_HIGH = 0x89, + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_LOW = 0x8a, + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_HIGH = 0x8b, + GRUB_SM712_SR_HW_CURSOR_FG_COLOR = 0x8c, + GRUB_SM712_SR_HW_CURSOR_BG_COLOR = 0x8d, + + GRUB_SM712_SR_POPUP_ICON_X_LOW = 0x90, + GRUB_SM712_SR_POPUP_ICON_X_HIGH = 0x91, + GRUB_SM712_SR_POPUP_ICON_Y_LOW = 0x92, + GRUB_SM712_SR_POPUP_ICON_Y_HIGH = 0x93, + GRUB_SM712_SR_PANEL_HW_VIDEO_CONTROL = 0xa0, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_LOW = 0xa1, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_HIGH = 0xa2, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_LOW = 0xa3, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_HIGH = 0xa4, + GRUB_SM712_SR_PANEL_HW_VIDEO_RED_CONSTANT = 0xa5, + GRUB_SM712_SR_PANEL_HW_VIDEO_GREEN_CONSTANT = 0xa6, + GRUB_SM712_SR_PANEL_HW_VIDEO_BLUE_CONSTANT = 0xa7, + GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_BOUNDARY = 0xa8, + GRUB_SM712_SR_PANEL_HW_VIDEO_LEFT_BOUNDARY = 0xa9, + GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_BOUNDARY = 0xaa, + GRUB_SM712_SR_PANEL_HW_VIDEO_RIGHT_BOUNDARY = 0xab, + GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_LEFT_OVERFLOW_BOUNDARY = 0xac, + GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_RIGHT_OVERFLOW_BOUNDARY = 0xad, + GRUB_SM712_SR_PANEL_HW_VIDEO_VERTICAL_STRETCH_FACTOR = 0xae, + GRUB_SM712_SR_PANEL_HW_VIDEO_HORIZONTAL_STRETCH_FACTOR = 0xaf, + }; +enum + { + GRUB_SM712_SR_TV_CRT_SRAM = 0x00, + GRUB_SM712_SR_TV_LCD_SRAM = 0x08 + }; +enum + { + GRUB_SM712_SR_TV_ALT_CLOCK = 0x00, + GRUB_SM712_SR_TV_FREE_RUN_CLOCK = 0x04 + }; +enum + { + GRUB_SM712_SR_TV_CLOCK_CKIN_NTSC = 0x00, + GRUB_SM712_SR_TV_CLOCK_REFCLK_PAL = 0x04 + }; +enum + { + GRUB_SM712_SR_TV_HSYNC = 0x00, + GRUB_SM712_SR_TV_COMPOSITE_HSYNC = 0x01 + }; +enum + { + GRUB_SM712_SR_RAM_LUT_NORMAL = 0, + GRUB_SM712_SR_RAM_LUT_LCD_RAM_OFF = 0x80, + GRUB_SM712_SR_RAM_LUT_CRT_RAM_OFF = 0x40, + GRUB_SM712_SR_RAM_LUT_LCD_RAM_NO_WRITE = 0x20, + GRUB_SM712_SR_RAM_LUT_CRT_RAM_NO_WRITE = 0x10, + GRUB_SM712_SR_RAM_LUT_CRT_8BIT = 0x08, + GRUB_SM712_SR_RAM_LUT_CRT_GAMMA = 0x04 + }; + +enum + { + GRUB_SM712_SR_CLOCK_CONTROL1_VCLK_FROM_CCR = 0x40, + GRUB_SM712_SR_CLOCK_CONTROL1_8DOT_CLOCK = 0x10, + }; + +enum + { + GRUB_SM712_SR_CLOCK_CONTROL2_PROGRAM_VCLOCK = 0x03 + }; + +#define GRUB_SM712_SR_POPUP_ICON_HIGH_MASK 0x7 +#define GRUB_SM712_SR_POPUP_ICON_HIGH_HW_CURSOR_EN 0x80 + enum + { + GRUB_SM712_SR_POPUP_ICON_CTRL_DISABLED = 0, + GRUB_SM712_SR_POPUP_ICON_CTRL_ZOOM_ENABLED = 0x40, + GRUB_SM712_SR_POPUP_ICON_CTRL_ENABLED = 0x80 + }; +#define RGB332_BLACK 0 +#define RGB332_WHITE 0xff + + enum + { + GRUB_SM712_CR_OVERFLOW_INTERLACE = 0x30, + GRUB_SM712_CR_INTERLACE_RETRACE = 0x31, + GRUB_SM712_CR_TV_VDISPLAY_START = 0x32, + GRUB_SM712_CR_TV_VDISPLAY_END_HIGH = 0x33, + GRUB_SM712_CR_TV_VDISPLAY_END_LOW = 0x34, + GRUB_SM712_CR_DDA_CONTROL_LOW = 0x35, + GRUB_SM712_CR_DDA_CONTROL_HIGH = 0x36, + GRUB_SM712_CR_TV_EQUALIZER = 0x38, + GRUB_SM712_CR_TV_SERRATION = 0x39, + GRUB_SM712_CR_HSYNC_CTRL = 0x3a, + GRUB_SM712_CR_DEBUG = 0x3c, + GRUB_SM712_CR_SHADOW_VGA_HTOTAL = 0x40, + GRUB_SM712_CR_SHADOW_VGA_HBLANK_START = 0x41, + GRUB_SM712_CR_SHADOW_VGA_HBLANK_END = 0x42, + GRUB_SM712_CR_SHADOW_VGA_HRETRACE_START = 0x43, + GRUB_SM712_CR_SHADOW_VGA_HRETRACE_END = 0x44, + GRUB_SM712_CR_SHADOW_VGA_VERTICAL_TOTAL = 0x45, + GRUB_SM712_CR_SHADOW_VGA_VBLANK_START = 0x46, + GRUB_SM712_CR_SHADOW_VGA_VBLANK_END = 0x47, + GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START = 0x48, + GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END = 0x49, + GRUB_SM712_CR_SHADOW_VGA_OVERFLOW = 0x4a, + GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT = 0x4b, + GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END = 0x4c, + GRUB_SM712_CR_SHADOW_VGA_VDISPLAY_END = 0x4d, + GRUB_SM712_CR_DDA_LOOKUP_REG3_START = 0x90, + GRUB_SM712_CR_DDA_LOOKUP_REG2_START = 0x91, + GRUB_SM712_CR_DDA_LOOKUP_REG1_START = 0xa0, + GRUB_SM712_CR_VCENTERING_OFFSET = 0xa6, + GRUB_SM712_CR_HCENTERING_OFFSET = 0xa7, + }; + +#define GRUB_SM712_CR_DEBUG_NONE 0 + +#define SM712_DDA_REG3_COMPARE_SHIFT 2 +#define SM712_DDA_REG3_COMPARE_MASK 0xfc +#define SM712_DDA_REG3_DDA_SHIFT 8 +#define SM712_DDA_REG3_DDA_MASK 0x3 +#define SM712_DDA_REG2_DDA_MASK 0xff +#define SM712_DDA_REG2_VCENTER_MASK 0x3f + +static struct +{ + grub_uint8_t compare; + grub_uint16_t dda; + grub_uint8_t vcentering; +} dda_lookups[] = { + { 21, 469, 2}, + { 23, 477, 2}, + { 33, 535, 2}, + { 35, 682, 21}, + { 34, 675, 2}, + { 55, 683, 6}, +}; + +static struct +{ + struct grub_video_mode_info mode_info; + struct grub_video_render_target *render_target; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +#ifndef TEST +static grub_err_t +grub_video_sm712_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_sm712_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + GRUB_SM712_TOTAL_MEMORY_SPACE); + + return grub_video_fb_fini (); +} +#endif + +static inline void +grub_sm712_write_reg (grub_uint8_t val, grub_uint16_t addr) +{ +#ifdef TEST + printf (" {1, 0x%x, 0x%x},\n", addr, val); +#else + *(volatile grub_uint8_t *) (framebuffer.ptr + GRUB_SM712_REG_BASE + + addr) = val; +#endif +} + +static inline grub_uint8_t +grub_sm712_read_reg (grub_uint16_t addr) +{ +#ifdef TEST + printf (" {-1, 0x%x, 0x5},\n", addr); +#else + return *(volatile grub_uint8_t *) (framebuffer.ptr + GRUB_SM712_REG_BASE + + addr); +#endif +} + +static inline grub_uint8_t +grub_sm712_sr_read (grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_SR_INDEX); + return grub_sm712_read_reg (GRUB_VGA_IO_SR_DATA); +} + +static inline void +grub_sm712_sr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_SR_INDEX); + grub_sm712_write_reg (val, GRUB_VGA_IO_SR_DATA); +} + +static inline void +grub_sm712_gr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_GR_INDEX); + grub_sm712_write_reg (val, GRUB_VGA_IO_GR_DATA); +} + +static inline void +grub_sm712_cr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_CR_INDEX); + grub_sm712_write_reg (val, GRUB_VGA_IO_CR_DATA); +} + +static inline void +grub_sm712_write_arx (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_read_reg (GRUB_VGA_IO_INPUT_STATUS1_REGISTER); + grub_sm712_write_reg (addr, GRUB_VGA_IO_ARX); + grub_sm712_read_reg (GRUB_VGA_IO_ARX_READ); + grub_sm712_write_reg (val, GRUB_VGA_IO_ARX); +} + +static inline void +grub_sm712_cr_shadow_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_uint8_t mapping[] = + { + [GRUB_VGA_CR_HTOTAL] = GRUB_SM712_CR_SHADOW_VGA_HTOTAL, + [GRUB_VGA_CR_HORIZ_END] = 0xff, + [GRUB_VGA_CR_HBLANK_START] = GRUB_SM712_CR_SHADOW_VGA_HBLANK_START, + [GRUB_VGA_CR_HBLANK_END] = GRUB_SM712_CR_SHADOW_VGA_HBLANK_END, + [GRUB_VGA_CR_HORIZ_SYNC_PULSE_START] = GRUB_SM712_CR_SHADOW_VGA_HRETRACE_START, + [GRUB_VGA_CR_HORIZ_SYNC_PULSE_END] = GRUB_SM712_CR_SHADOW_VGA_HRETRACE_END, + [GRUB_VGA_CR_VERT_TOTAL] = GRUB_SM712_CR_SHADOW_VGA_VERTICAL_TOTAL, + [GRUB_VGA_CR_OVERFLOW] = GRUB_SM712_CR_SHADOW_VGA_OVERFLOW, + [GRUB_VGA_CR_BYTE_PANNING] = 0xff, + [GRUB_VGA_CR_CELL_HEIGHT] = GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT, + [GRUB_VGA_CR_CURSOR_START] = 0xff, + [GRUB_VGA_CR_CURSOR_END] = 0xff, + [GRUB_VGA_CR_START_ADDR_HIGH_REGISTER] = 0xff, + [GRUB_VGA_CR_START_ADDR_LOW_REGISTER] = 0xff, + [GRUB_VGA_CR_CURSOR_ADDR_HIGH] = 0xff, + [GRUB_VGA_CR_CURSOR_ADDR_LOW] = 0xff, + [GRUB_VGA_CR_VSYNC_START] = GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START, + [GRUB_VGA_CR_VSYNC_END] = GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END, + [GRUB_VGA_CR_VDISPLAY_END] = GRUB_SM712_CR_SHADOW_VGA_VDISPLAY_END, + [GRUB_VGA_CR_PITCH] = GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END, + [GRUB_VGA_CR_UNDERLINE_LOCATION] = 0xff, + + [GRUB_VGA_CR_VERTICAL_BLANK_START] = GRUB_SM712_CR_SHADOW_VGA_VBLANK_START, + [GRUB_VGA_CR_VERTICAL_BLANK_END] = GRUB_SM712_CR_SHADOW_VGA_VBLANK_END, + [GRUB_VGA_CR_MODE] = 0xff, + [GRUB_VGA_CR_LINE_COMPARE] = 0xff + }; + if (addr >= ARRAY_SIZE (mapping) || mapping[addr] == 0xff) + return; + grub_sm712_cr_write (val, mapping[addr]); +} + +static inline void +grub_sm712_write_dda_lookup (int idx, grub_uint8_t compare, grub_uint16_t dda, + grub_uint8_t vcentering) +{ + grub_sm712_cr_write (((compare << SM712_DDA_REG3_COMPARE_SHIFT) + & SM712_DDA_REG3_COMPARE_MASK) + | ((dda >> SM712_DDA_REG3_DDA_SHIFT) + & SM712_DDA_REG3_DDA_MASK), + GRUB_SM712_CR_DDA_LOOKUP_REG3_START + 2 * idx); + grub_sm712_cr_write (dda & SM712_DDA_REG2_DDA_MASK, + GRUB_SM712_CR_DDA_LOOKUP_REG2_START + 2 * idx); + grub_sm712_cr_write (vcentering & SM712_DDA_REG2_VCENTER_MASK, + GRUB_SM712_CR_DDA_LOOKUP_REG1_START + idx); +} + +static grub_err_t +grub_video_sm712_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) +{ + int depth; + grub_err_t err; + int found = 0; + unsigned i; + +#ifndef TEST + auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); + 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 + || pciid != GRUB_SM712_PCIID) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr); + framebuffer.dev = dev; + + return 1; + } + + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if ((width != 1024 && width != 0) || (height != 600 && height != 0) + || (depth != 16 && depth != 0)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Only 1024x600x16 is supported"); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); +#endif + /* Fill mode info details. */ + framebuffer.mode_info.width = 1024; + framebuffer.mode_info.height = 600; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = 16; + framebuffer.mode_info.bytes_per_pixel = 2; + framebuffer.mode_info.pitch = 1024 * 2; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; +#ifndef TEST + framebuffer.mode_info.blit_format + = grub_video_get_blit_format (&framebuffer.mode_info); +#endif + +#ifndef TEST + if (found && framebuffer.base == 0) + { + grub_pci_address_t addr; + /* FIXME: choose address dynamically if needed. */ + framebuffer.base = 0x04000000; + + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, framebuffer.base); + + /* Set latency. */ + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_CACHELINE); + grub_pci_write (addr, 0x8); + + /* Enable address spaces. */ + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, 0x7); + } +#endif + + /* We can safely discard volatile attribute. */ +#ifndef TEST + framebuffer.ptr + = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + GRUB_SM712_TOTAL_MEMORY_SPACE); +#endif + framebuffer.mapped = 1; + + /* Initialise SM712. */ +#ifndef TEST + /* FIXME */ + grub_vga_sr_write (0x11, 0x18); +#endif + +#ifndef TEST + /* Prevent garbage from appearing on the screen. */ + grub_memset (framebuffer.ptr, 0, + framebuffer.mode_info.height * framebuffer.mode_info.pitch); +#endif + + /* FIXME */ + grub_sm712_sr_write (0, 0x21); + grub_sm712_sr_write (0x7a, 0x62); + grub_sm712_sr_write (0x16, 0x6a); + grub_sm712_sr_write (0x2, 0x6b); + grub_sm712_write_reg (0, GRUB_VGA_IO_PIXEL_MASK); + grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC, GRUB_VGA_SR_RESET); + grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY + | GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY + | GRUB_VGA_IO_MISC_UPPER_64K + | GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 + | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS + | GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); + grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC | GRUB_VGA_SR_RESET_SYNC, + GRUB_VGA_SR_RESET); + grub_sm712_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK, + GRUB_VGA_SR_CLOCKING_MODE); + grub_sm712_sr_write (GRUB_VGA_ALL_PLANES, GRUB_VGA_SR_MAP_MASK_REGISTER); + grub_sm712_sr_write (0, GRUB_VGA_SR_CHAR_MAP_SELECT); + grub_sm712_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4 + | GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING + | GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY, + GRUB_VGA_SR_MEMORY_MODE); + + for (i = 0; i < ARRAY_SIZE (sm712_sr_seq1); i++) + grub_sm712_sr_write (sm712_sr_seq1[i], 0x10 + i); + + for (i = 0; i < ARRAY_SIZE (sm712_sr_seq2); i++) + grub_sm712_sr_write (sm712_sr_seq2[i], 0x30 + i); + + /* Undocumented. */ + grub_sm712_sr_write (0x1a, 0x63); + /* Undocumented. */ + grub_sm712_sr_write (0x1a, 0x64); + + grub_sm712_sr_write (GRUB_SM712_SR_TV_CRT_SRAM | GRUB_SM712_SR_TV_ALT_CLOCK + | GRUB_SM712_SR_TV_CLOCK_CKIN_NTSC + | GRUB_SM712_SR_TV_HSYNC, + GRUB_SM712_SR_TV_CONTROL); + + grub_sm712_sr_write (GRUB_SM712_SR_RAM_LUT_NORMAL, GRUB_SM712_SR_RAM_LUT); + + /* Undocumented. */ + grub_sm712_sr_write (0x00, 0x67); + + grub_sm712_sr_write (GRUB_SM712_SR_CLOCK_CONTROL1_VCLK_FROM_CCR + | GRUB_SM712_SR_CLOCK_CONTROL1_8DOT_CLOCK, + GRUB_SM712_SR_CLOCK_CONTROL1); + grub_sm712_sr_write (GRUB_SM712_SR_CLOCK_CONTROL2_PROGRAM_VCLOCK, + GRUB_SM712_SR_CLOCK_CONTROL2); + + grub_sm712_sr_write (82, GRUB_SM712_SR_VCLK_NUM); + grub_sm712_sr_write (137, GRUB_SM712_SR_VCLK_DENOM); + + grub_sm712_sr_write (9, GRUB_SM712_SR_VCLK2_NUM); + grub_sm712_sr_write (2, GRUB_SM712_SR_VCLK2_DENOM); + /* FIXME */ + grub_sm712_sr_write (0x04, 0x70); + /* FIXME */ + grub_sm712_sr_write (0x45, 0x71); + /* Undocumented */ + grub_sm712_sr_write (0x30, 0x72); + /* Undocumented */ + grub_sm712_sr_write (0x30, 0x73); + /* Undocumented */ + grub_sm712_sr_write (0x40, 0x74); + /* Undocumented */ + grub_sm712_sr_write (0x20, 0x75); + + grub_sm712_sr_write (0xff, GRUB_SM712_SR_POPUP_ICON_LOW); + grub_sm712_sr_write (GRUB_SM712_SR_POPUP_ICON_HIGH_MASK, + GRUB_SM712_SR_POPUP_ICON_HIGH); + grub_sm712_sr_write (GRUB_SM712_SR_POPUP_ICON_CTRL_DISABLED, + GRUB_SM712_SR_POPUP_ICON_CTRL); + /* Undocumented */ + grub_sm712_sr_write (0x0, 0x83); + + grub_sm712_sr_write (8, GRUB_SM712_SR_POPUP_ICON_COLOR1); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_COLOR2); + grub_sm712_sr_write (0x42, GRUB_SM712_SR_POPUP_ICON_COLOR3); + + /* Undocumented */ + grub_sm712_sr_write (0x3a, 0x87); + + /* Why theese coordinates? */ + grub_sm712_sr_write (0x59, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_LOW); + grub_sm712_sr_write (0x02, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_HIGH); + grub_sm712_sr_write (0x44, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_LOW); + grub_sm712_sr_write (0x02, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_HIGH); + + grub_sm712_sr_write (RGB332_BLACK, GRUB_SM712_SR_HW_CURSOR_FG_COLOR); + grub_sm712_sr_write (RGB332_WHITE, GRUB_SM712_SR_HW_CURSOR_BG_COLOR); + + /* Undocumented */ + grub_sm712_sr_write (0x3a, 0x8e); + grub_sm712_sr_write (0x3a, 0x8f); + + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_X_LOW); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_X_HIGH); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_Y_LOW); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_Y_HIGH); + + grub_sm712_sr_write (0, GRUB_SM712_SR_PANEL_HW_VIDEO_CONTROL); + grub_sm712_sr_write (0x10, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_LOW); + grub_sm712_sr_write (0x08, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_HIGH); + grub_sm712_sr_write (0x00, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_LOW); + grub_sm712_sr_write (0x02, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_HIGH); + grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_RED_CONSTANT); + grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_GREEN_CONSTANT); + grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_BLUE_CONSTANT); + + grub_sm712_sr_write (0x7b, GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_BOUNDARY); + grub_sm712_sr_write (0xfb, GRUB_SM712_SR_PANEL_HW_VIDEO_LEFT_BOUNDARY); + grub_sm712_sr_write (0xff, GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_BOUNDARY); + grub_sm712_sr_write (0xff, GRUB_SM712_SR_PANEL_HW_VIDEO_RIGHT_BOUNDARY); + /* Doesn't match documentation? */ + grub_sm712_sr_write (0x97, GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_LEFT_OVERFLOW_BOUNDARY); + grub_sm712_sr_write (0xef, GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_RIGHT_OVERFLOW_BOUNDARY); + + grub_sm712_sr_write (0xbf, GRUB_SM712_SR_PANEL_HW_VIDEO_VERTICAL_STRETCH_FACTOR); + grub_sm712_sr_write (0xdf, GRUB_SM712_SR_PANEL_HW_VIDEO_HORIZONTAL_STRETCH_FACTOR); + + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_SET_RESET_PLANE); + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_SET_RESET_PLANE_ENABLE); + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_COLOR_COMPARE); + grub_sm712_gr_write (GRUB_VGA_GR_DATA_ROTATE_NOP, GRUB_VGA_GR_DATA_ROTATE); + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_READ_MAP_REGISTER); + grub_sm712_gr_write (GRUB_VGA_GR_MODE_256_COLOR, GRUB_VGA_GR_MODE); + grub_sm712_gr_write (GRUB_VGA_GR_GR6_MMAP_A0 + | GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); + grub_sm712_gr_write (GRUB_VGA_ALL_PLANES, GRUB_VGA_GR_COLOR_COMPARE_DISABLE); + grub_sm712_gr_write (0xff, GRUB_VGA_GR_BITMASK); + + /* Write palette mapping. */ + for (i = 0; i < 16; i++) + grub_sm712_write_arx (i, i); + + grub_sm712_write_arx (GRUB_VGA_ARX_MODE_ENABLE_256COLOR + | GRUB_VGA_ARX_MODE_GRAPHICS, GRUB_VGA_ARX_MODE); + grub_sm712_write_arx (0, GRUB_VGA_ARX_OVERSCAN); + grub_sm712_write_arx (GRUB_VGA_ALL_PLANES, GRUB_VGA_ARX_COLOR_PLANE_ENABLE); + grub_sm712_write_arx (0, GRUB_VGA_ARX_HORIZONTAL_PANNING); + grub_sm712_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT); + + /* FIXME: compute this generically. */ + { + struct grub_video_hw_config config = + { + .vertical_total = 806, + .vertical_blank_start = 0x300, + .vertical_blank_end = 0, + .vertical_sync_start = 0x303, + .vertical_sync_end = 0x9, + .line_compare = 0x3ff, + .vdisplay_end = 0x300, + .pitch = 0x80, + .horizontal_total = 164, + .horizontal_end = 128, + .horizontal_blank_start = 128, + .horizontal_blank_end = 0, + .horizontal_sync_pulse_start = 133, + .horizontal_sync_pulse_end = 22 + }; + grub_vga_set_geometry (&config, grub_sm712_cr_write); + config.horizontal_sync_pulse_start = 134; + config.horizontal_sync_pulse_end = 21; + config.vertical_sync_start = 0x301; + config.vertical_sync_end = 0x0; + config.line_compare = 0x0ff; + config.vdisplay_end = 0x258; + config.pitch = 0x7f; + grub_vga_set_geometry (&config, grub_sm712_cr_shadow_write); + } + + grub_sm712_cr_write (GRUB_VGA_CR_BYTE_PANNING_NORMAL, + GRUB_VGA_CR_BYTE_PANNING); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_START); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_END); + grub_sm712_cr_write (0, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); + grub_sm712_cr_write (0, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_ADDR_HIGH); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_ADDR_LOW); + grub_sm712_cr_write (GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE, + GRUB_VGA_CR_UNDERLINE_LOCATION); + grub_sm712_cr_write (GRUB_VGA_CR_MODE_ADDRESS_WRAP + | GRUB_VGA_CR_MODE_BYTE_MODE + | GRUB_VGA_CR_MODE_TIMING_ENABLE + | GRUB_VGA_CR_MODE_NO_CGA + | GRUB_VGA_CR_MODE_NO_HERCULES, + GRUB_VGA_CR_MODE); + + grub_sm712_cr_write (0, GRUB_SM712_CR_OVERFLOW_INTERLACE); + grub_sm712_cr_write (0, GRUB_SM712_CR_INTERLACE_RETRACE); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_START); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_END_HIGH); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_END_LOW); + grub_sm712_cr_write (0x80, GRUB_SM712_CR_DDA_CONTROL_LOW); + grub_sm712_cr_write (0x02, GRUB_SM712_CR_DDA_CONTROL_HIGH); + + /* Undocumented */ + grub_sm712_cr_write (0x20, 0x37); + + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_EQUALIZER); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_SERRATION); + grub_sm712_cr_write (0, GRUB_SM712_CR_HSYNC_CTRL); + + /* Undocumented */ + grub_sm712_cr_write (0x40, 0x3b); + + grub_sm712_cr_write (GRUB_SM712_CR_DEBUG_NONE, GRUB_SM712_CR_DEBUG); + + /* Undocumented */ + grub_sm712_cr_write (0xff, 0x3d); + grub_sm712_cr_write (0x46, 0x3e); + grub_sm712_cr_write (0x91, 0x3f); + + for (i = 0; i < ARRAY_SIZE (dda_lookups); i++) + grub_sm712_write_dda_lookup (i, dda_lookups[i].compare, dda_lookups[i].dda, + dda_lookups[i].vcentering); + + /* Undocumented */ + grub_sm712_cr_write (0, 0x9c); + grub_sm712_cr_write (0, 0x9d); + grub_sm712_cr_write (0, 0x9e); + grub_sm712_cr_write (0, 0x9f); + + grub_sm712_cr_write (0, GRUB_SM712_CR_VCENTERING_OFFSET); + grub_sm712_cr_write (0, GRUB_SM712_CR_HCENTERING_OFFSET); + + grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY + | GRUB_VGA_IO_MISC_UPPER_64K + | GRUB_VGA_IO_MISC_28MHZ + | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS + | GRUB_VGA_IO_MISC_COLOR, + GRUB_VGA_IO_MISC_WRITE); + +#ifndef TEST + /* Undocumented? */ + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c00c) = 0; + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c040) = 0; + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c000) = 0x20000; + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c010) = 0x1020100; +#endif + + (void) grub_sm712_sr_read (0x16); + +#ifndef TEST + err = grub_video_fb_create_render_target_from_pointer (&framebuffer + .render_target, + &framebuffer.mode_info, + framebuffer.ptr); + + if (err) + return err; + + err = grub_video_fb_set_active_render_target (framebuffer.render_target); + + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); +#endif + return err; +} + +#ifndef TEST + +static grub_err_t +grub_video_sm712_swap_buffers (void) +{ + /* TODO: Implement buffer swapping. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_sm712_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.render_target; + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t +grub_video_sm712_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); + *framebuf = (char *) framebuffer.ptr; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + +static struct grub_video_adapter grub_video_sm712_adapter = + { + .name = "SM712 Video Driver", + .id = GRUB_VIDEO_DRIVER_SM712, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + + .init = grub_video_sm712_video_init, + .fini = grub_video_sm712_video_fini, + .setup = grub_video_sm712_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_sm712_get_info_and_fini, + .set_palette = grub_video_fb_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_sm712_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_sm712_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_sm712) +{ + grub_video_register (&grub_video_sm712_adapter); +} + +GRUB_MOD_FINI(video_sm712) +{ + grub_video_unregister (&grub_video_sm712_adapter); +} +#else +int +main () +{ + grub_video_sm712_setup (1024, 600, 0, 0); +} +#endif diff --git a/grub-core/video/sm712_init.c b/grub-core/video/sm712_init.c new file mode 100644 index 000000000..cdb0b7383 --- /dev/null +++ b/grub-core/video/sm712_init.c @@ -0,0 +1,14 @@ +/* Following sequence is a capture of sm712 initialisation sequence. */ +static grub_uint8_t sm712_sr_seq1[] = + { 0xc8, 0x40, 0x14, 0x60, 0x0, 0xa, 0x92, 0x0, + 0x51, 0x00, 0x01, 0x00, 0x0, 0x0, 0x00, 0x0, + 0xc4, 0x30, 0x02, 0x00, 0x1 }; + +static grub_uint8_t sm712_sr_seq2[] = + { 0x28, 0x03, 0x24, 0x09, 0xc0, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x00, 0x00, 0x03, 0xff, + 0x00, 0xfc, 0x00, 0x00, 0x20, 0x18, 0x00, 0xfc, + 0x20, 0x0c, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3a, + 0x06, 0x68, 0xa7, 0x7f, 0x83, 0x24, 0xff, 0x03, + 0x00, 0x60, 0x59, 0x3a, 0x3a, 0x00, 0x00, 0x3a, + 0x01, 0x80 }; diff --git a/video/video.c b/grub-core/video/video.c similarity index 100% rename from video/video.c rename to grub-core/video/video.c diff --git a/include/grub/acpi.h b/include/grub/acpi.h index 7933db824..c843a0621 100644 --- a/include/grub/acpi.h +++ b/include/grub/acpi.h @@ -19,8 +19,10 @@ #ifndef GRUB_ACPI_HEADER #define GRUB_ACPI_HEADER 1 +#ifndef GRUB_DSDT_TEST #include #include +#endif struct grub_acpi_rsdp_v10 { @@ -53,17 +55,93 @@ struct grub_acpi_table_header grub_uint32_t creator_rev; } __attribute__ ((packed)); +#define GRUB_ACPI_FADT_SIGNATURE "FACP" + struct grub_acpi_fadt { struct grub_acpi_table_header hdr; grub_uint32_t facs_addr; grub_uint32_t dsdt_addr; - grub_uint8_t somefields1[88]; + grub_uint8_t somefields1[20]; + grub_uint32_t pm1a; + grub_uint8_t somefields2[64]; grub_uint64_t facs_xaddr; grub_uint64_t dsdt_xaddr; - grub_uint8_t somefields2[96]; + grub_uint8_t somefields3[96]; } __attribute__ ((packed)); +#define GRUB_ACPI_MADT_SIGNATURE "APIC" + +struct grub_acpi_madt_entry_header +{ + grub_uint8_t type; + grub_uint8_t len; +}; + +struct grub_acpi_madt +{ + struct grub_acpi_table_header hdr; + grub_uint32_t lapic_addr; + grub_uint32_t flags; + struct grub_acpi_madt_entry_header entries[0]; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE = 2, + GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC = 6, + GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC = 7, + GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE = 8 + }; + +struct grub_acpi_madt_entry_interrupt_override +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t bus; + grub_uint8_t source; + grub_uint32_t global_sys_interrupt; + grub_uint16_t flags; +}; + +struct grub_acpi_madt_entry_sapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t id; + grub_uint8_t pad; + grub_uint32_t global_sys_interrupt_base; + grub_uint64_t addr; +}; + +struct grub_acpi_madt_entry_lsapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t cpu_id; + grub_uint8_t id; + grub_uint8_t eid; + grub_uint8_t pad[3]; + grub_uint32_t flags; + grub_uint32_t cpu_uid; + grub_uint8_t cpu_uid_str[0]; +}; + +struct grub_acpi_madt_entry_platform_int_source +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint16_t flags; + grub_uint8_t inttype; + grub_uint8_t cpu_id; + grub_uint8_t cpu_eid; + grub_uint8_t sapic_vector; + grub_uint32_t global_sys_int; + grub_uint32_t src_flags; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED = 1 + }; + +#ifndef GRUB_DSDT_TEST struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void); struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void); struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void); @@ -72,4 +150,27 @@ grub_uint8_t grub_byte_checksum (void *base, grub_size_t size); grub_err_t grub_acpi_create_ebda (void); +void grub_acpi_halt (void); +#endif + +#define GRUB_ACPI_SLP_EN (1 << 13) +#define GRUB_ACPI_SLP_TYP_OFFSET 10 + +enum + { + GRUB_ACPI_OPCODE_ZERO = 0, GRUB_ACPI_OPCODE_ONE = 1, + GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a, + GRUB_ACPI_OPCODE_WORD_CONST = 0x0b, GRUB_ACPI_OPCODE_DWORD_CONST = 0x0c, + GRUB_ACPI_OPCODE_SCOPE = 0x10, GRUB_ACPI_OPCODE_PACKAGE = 0x12, + GRUB_ACPI_OPCODE_METHOD = 0x14, GRUB_ACPI_OPCODE_EXTOP = 0x5b, + GRUB_ACPI_OPCODE_IF = 0xa0, GRUB_ACPI_OPCODE_ONES = 0xff + }; +enum + { + GRUB_ACPI_EXTOPCODE_MUTEX = 0x01, + GRUB_ACPI_EXTOPCODE_OPERATION_REGION = 0x80, + GRUB_ACPI_EXTOPCODE_FIELD_OP = 0x81, + GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP = 0x86, + }; + #endif /* ! GRUB_ACPI_HEADER */ diff --git a/include/grub/aout.h b/include/grub/aout.h index f962a97b3..10d7dde61 100644 --- a/include/grub/aout.h +++ b/include/grub/aout.h @@ -120,8 +120,8 @@ union grub_aout_header int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header); grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset, - grub_addr_t load_addr, int load_size, - grub_addr_t bss_end_addr); + void *load_addr, int load_size, + grub_size_t bss_size); #endif diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 10421540a..65cf8a2a2 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -19,36 +19,20 @@ #ifndef GRUB_AT_KEYBOARD_HEADER #define GRUB_AT_KEYBOARD_HEADER 1 -#define SHIFT_L 0x2a -#define SHIFT_R 0x36 -#define CTRL 0x1d -#define ALT 0x38 -#define CAPS_LOCK 0x3a -#define NUM_LOCK 0x45 -#define SCROLL_LOCK 0x46 - /* Used for sending commands to the controller. */ #define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) #define KEYBOARD_COMMAND_READ 0x20 #define KEYBOARD_COMMAND_WRITE 0x60 #define KEYBOARD_COMMAND_REBOOT 0xfe -#define KEYBOARD_SCANCODE_SET1 0x40 +#define KEYBOARD_AT_TRANSLATE 0x40 + +#define GRUB_AT_ACK 0xfa +#define GRUB_AT_NACK 0xfe +#define GRUB_AT_TRIES 5 #define KEYBOARD_ISMAKE(x) !((x) & 0x80) #define KEYBOARD_ISREADY(x) ((x) & 0x01) #define KEYBOARD_SCANCODE(x) ((x) & 0x7f) -#ifdef GRUB_MACHINE_IEEE1275 -#define OLPC_UP GRUB_TERM_UP -#define OLPC_DOWN GRUB_TERM_DOWN -#define OLPC_LEFT GRUB_TERM_LEFT -#define OLPC_RIGHT GRUB_TERM_RIGHT -#else -#define OLPC_UP '\0' -#define OLPC_DOWN '\0' -#define OLPC_LEFT '\0' -#define OLPC_RIGHT '\0' -#endif - #endif diff --git a/include/grub/autoefi.h b/include/grub/autoefi.h index 5ae4b3a21..b75591176 100644 --- a/include/grub/autoefi.h +++ b/include/grub/autoefi.h @@ -34,22 +34,12 @@ static inline grub_err_t grub_autoefi_prepare (void) { return GRUB_ERR_NONE; }; -# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_MACHINE_MEMORY_AVAILABLE -# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_MACHINE_MEMORY_RESERVED -# ifdef GRUB_MACHINE_MEMORY_ACPI -# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_MACHINE_MEMORY_ACPI -# endif -# ifdef GRUB_MACHINE_MEMORY_NVS -# define GRUB_AUTOEFI_MEMORY_NVS GRUB_MACHINE_MEMORY_NVS -# endif -# ifdef GRUB_MACHINE_MEMORY_CODE -# define GRUB_AUTOEFI_MEMORY_CODE GRUB_MACHINE_MEMORY_CODE -# endif # define SYSTEM_TABLE_SIZEOF(x) (sizeof(grub_efi_system_table->x)) # define SYSTEM_TABLE_VAR(x) ((void *)&(grub_efi_system_table->x)) # define SYSTEM_TABLE_PTR(x) ((void *)(grub_efi_system_table->x)) # define SIZEOF_OF_UINTN sizeof (grub_efi_uintn_t) # define SYSTEM_TABLE(x) (grub_efi_system_table->x) +# define grub_autoefi_finish_boot_services grub_efi_finish_boot_services # define EFI_PRESENT 1 #else # include @@ -60,11 +50,6 @@ static inline grub_err_t grub_autoefi_prepare (void) # define grub_autoefi_mmap_iterate grub_efiemu_mmap_iterate # define grub_autoefi_prepare grub_efiemu_prepare # define grub_autoefi_set_virtual_address_map grub_efiemu_set_virtual_address_map -# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_EFIEMU_MEMORY_AVAILABLE -# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_EFIEMU_MEMORY_RESERVED -# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_EFIEMU_MEMORY_ACPI -# define GRUB_AUTOEFI_MEMORY_NVS GRUB_EFIEMU_MEMORY_NVS -# define GRUB_AUTOEFI_MEMORY_CODE GRUB_EFIEMU_MEMORY_CODE # define SYSTEM_TABLE_SIZEOF GRUB_EFIEMU_SYSTEM_TABLE_SIZEOF # define SYSTEM_TABLE_VAR GRUB_EFIEMU_SYSTEM_TABLE_VAR # define SYSTEM_TABLE_PTR GRUB_EFIEMU_SYSTEM_TABLE_PTR @@ -72,6 +57,7 @@ static inline grub_err_t grub_autoefi_prepare (void) # define SYSTEM_TABLE GRUB_EFIEMU_SYSTEM_TABLE # define grub_efi_allocate_pages(x,y) (x) # define grub_efi_free_pages(x,y) GRUB_EFI_SUCCESS +# define grub_autoefi_finish_boot_services grub_efiemu_finish_boot_services # define EFI_PRESENT 1 #endif diff --git a/include/grub/cache.h b/include/grub/cache.h index 27e44f0a2..4f913f5c8 100644 --- a/include/grub/cache.h +++ b/include/grub/cache.h @@ -23,6 +23,10 @@ #include #include +#ifdef _mips +#include +#endif + #if defined (__i386__) || defined (__x86_64__) static inline void grub_arch_sync_caches (void *address __attribute__ ((unused)), diff --git a/include/grub/command.h b/include/grub/command.h index 6bd3d07c9..19622752e 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -23,20 +23,21 @@ #include #include -/* Can be run in the command-line. */ -#define GRUB_COMMAND_FLAG_CMDLINE 0x1 -/* Can be run in the menu. */ -#define GRUB_COMMAND_FLAG_MENU 0x2 -/* Can be run in both interfaces. */ -#define GRUB_COMMAND_FLAG_BOTH 0x3 -/* Only for the command title. */ -#define GRUB_COMMAND_FLAG_TITLE 0x4 -/* Don't print the command on booting. */ -#define GRUB_COMMAND_FLAG_NO_ECHO 0x8 -/* This is an extended command. */ -#define GRUB_COMMAND_FLAG_EXTCMD 0x10 -/* This is an dynamic command. */ -#define GRUB_COMMAND_FLAG_DYNCMD 0x20 +typedef enum grub_command_flags + { + /* This is an extended command. */ + GRUB_COMMAND_FLAG_EXTCMD = 0x10, + /* This is an dynamic command. */ + GRUB_COMMAND_FLAG_DYNCMD = 0x20, + /* This command accepts block arguments. */ + GRUB_COMMAND_FLAG_BLOCKS = 0x40, + /* This command accepts unknown arguments as direct parameters. */ + GRUB_COMMAND_ACCEPT_DASH = 0x80, + /* This command accepts only options preceding direct arguments. */ + GRUB_COMMAND_OPTIONS_AT_START = 0x100, + /* Can be executed in an entries extractor. */ + GRUB_COMMAND_FLAG_EXTRACTOR = 0x200 + } grub_command_flags_t; struct grub_command; @@ -59,7 +60,7 @@ struct grub_command grub_command_func_t func; /* The flags. */ - unsigned flags; + grub_command_flags_t flags; /* The summary of the command usage. */ const char *summary; diff --git a/include/grub/crypto.h b/include/grub/crypto.h index 48b52ee65..ebe78e7a1 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -243,10 +243,12 @@ extern gcry_md_spec_t _gcry_digest_spec_md5; extern gcry_md_spec_t _gcry_digest_spec_sha1; extern gcry_md_spec_t _gcry_digest_spec_sha256; extern gcry_md_spec_t _gcry_digest_spec_sha512; +extern gcry_md_spec_t _gcry_digest_spec_crc32; #define GRUB_MD_MD5 ((const gcry_md_spec_t *) &_gcry_digest_spec_md5) #define GRUB_MD_SHA1 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha1) #define GRUB_MD_SHA256 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha256) #define GRUB_MD_SHA512 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha512) +#define GRUB_MD_CRC32 ((const gcry_md_spec_t *) &_gcry_digest_spec_crc32) /* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant of digest supplied by MD. Inputs are the password P of length PLEN, diff --git a/include/grub/i386/coreboot/init.h b/include/grub/decompressor.h similarity index 62% rename from include/grub/i386/coreboot/init.h rename to include/grub/decompressor.h index e67007414..a6eefb01b 100644 --- a/include/grub/i386/coreboot/init.h +++ b/include/grub/decompressor.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007 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 @@ -16,13 +16,19 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_INIT_I386_LINUXBIOS_HEADER -#define GRUB_INIT_I386_LINUXBIOS_HEADER 1 +#ifndef GRUB_DECOMPRESSOR_HEADER +#define GRUB_DECOMPRESSOR_HEADER 1 -#include -#include +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize); -void EXPORT_FUNC(grub_stop) (void) __attribute__ ((noreturn)); -void EXPORT_FUNC(grub_stop_floppy) (void); +void +find_scratch (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize); + +#define GRUB_DECOMPRESSOR_DICT_SIZE (1 << 16) + +extern void *grub_decompressor_scratch; #endif diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..66db1149a 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -78,6 +78,7 @@ struct grub_disk_dev #ifdef GRUB_UTIL struct grub_disk_memberlist *(*memberlist) (struct grub_disk *disk); + const char * (*raidname) (struct grub_disk *disk); #endif /* The next disk device. */ @@ -99,9 +100,6 @@ struct grub_disk /* The total number of sectors. */ grub_uint64_t total_sectors; - /* If partitions can be stored. */ - int has_partitions; - /* The id used by the disk cache manager. */ unsigned long id; @@ -177,4 +175,15 @@ struct grub_disk_ata_pass_through_parms extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t, struct grub_disk_ata_pass_through_parms *); +#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU) +void grub_lvm_init (void); +void grub_mdraid09_init (void); +void grub_mdraid1x_init (void); +void grub_raid_init (void); +void grub_lvm_fini (void); +void grub_mdraid09_fini (void); +void grub_mdraid1x_fini (void); +void grub_raid_fini (void); +#endif + #endif /* ! GRUB_DISK_HEADER */ diff --git a/include/grub/dl.h b/include/grub/dl.h index 351cca64d..afc4af41a 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -25,6 +25,13 @@ #include #include +/* + * Macros GRUB_MOD_INIT and GRUB_MOD_FINI are also used by build rules + * to collect module names, so we define them only when they are not + * defined already. + */ + +#ifndef GRUB_MOD_INIT #define GRUB_MOD_INIT(name) \ static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ void grub_##name##_init (void); \ @@ -32,7 +39,9 @@ void \ grub_##name##_init (void) { grub_mod_init (0); } \ static void \ grub_mod_init (grub_dl_t mod __attribute__ ((unused))) +#endif +#ifndef GRUB_MOD_FINI #define GRUB_MOD_FINI(name) \ static void grub_mod_fini (void) __attribute__ ((used)); \ void grub_##name##_fini (void); \ @@ -40,6 +49,7 @@ void \ grub_##name##_fini (void) { grub_mod_fini (); } \ static void \ grub_mod_fini (void) +#endif #ifdef APPLE_CC #define GRUB_MOD_NAME(name) \ @@ -91,12 +101,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name); grub_dl_t grub_dl_load_core (void *addr, grub_size_t size); int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod); void grub_dl_unload_unneeded (void); -void grub_dl_unload_all (void); -#if defined (GRUB_UTIL) || defined (GRUB_TARGET_NO_MODULES) -#define GRUB_NO_MODULES 1 -#else -#define GRUB_NO_MODULES 0 -#endif int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); extern grub_dl_t EXPORT_VAR(grub_dl_head); @@ -110,7 +114,7 @@ grub_err_t grub_dl_register_symbol (const char *name, void *addr, grub_err_t grub_arch_dl_check_header (void *ehdr); grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr); -#if defined (_mips) && ! GRUB_NO_MODULES +#if defined (_mips) #define GRUB_LINKER_HAVE_INIT 1 void grub_arch_dl_init_linker (void); #endif diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 36363ae1e..cb6b1113b 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -109,6 +109,109 @@ { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ } +#define GRUB_EFI_SAL_TABLE_GUID \ + { 0xeb9d2d32, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define GRUB_EFI_HCDP_TABLE_GUID \ + { 0xf951938d, 0x620b, 0x42ef, \ + { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \ + } + +struct grub_efi_sal_system_table +{ + grub_uint32_t signature; + grub_uint32_t total_table_len; + grub_uint16_t sal_rev; + grub_uint16_t entry_count; + grub_uint8_t checksum; + grub_uint8_t reserved1[7]; + grub_uint16_t sal_a_version; + grub_uint16_t sal_b_version; + grub_uint8_t oem_id[32]; + grub_uint8_t product_id[32]; + grub_uint8_t reserved2[8]; + grub_uint8_t entries[0]; +}; + +enum + { + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR = 0, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR = 1, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES = 2, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR = 3, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE = 4, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP = 5 + }; + +struct grub_efi_sal_system_table_entrypoint_descriptor +{ + grub_uint8_t type; + grub_uint8_t pad[7]; + grub_uint64_t pal_proc_addr; + grub_uint64_t sal_proc_addr; + grub_uint64_t global_data_ptr; + grub_uint64_t reserved[2]; +}; + +struct grub_efi_sal_system_table_memory_descriptor +{ + grub_uint8_t type; + grub_uint8_t sal_used; + grub_uint8_t attr; + grub_uint8_t ar; + grub_uint8_t attr_mask; + grub_uint8_t mem_type; + grub_uint8_t usage; + grub_uint8_t unknown; + grub_uint64_t addr; + grub_uint64_t len; + grub_uint64_t unknown2; +}; + +struct grub_efi_sal_system_table_platform_features +{ + grub_uint8_t type; + grub_uint8_t flags; + grub_uint8_t reserved[14]; +}; + +struct grub_efi_sal_system_table_translation_register_descriptor +{ + grub_uint8_t type; + grub_uint8_t register_type; + grub_uint8_t register_number; + grub_uint8_t reserved[5]; + grub_uint64_t addr; + grub_uint64_t page_size; + grub_uint64_t reserver; +}; + +struct grub_efi_sal_system_table_purge_translation_coherence +{ + grub_uint8_t type; + grub_uint8_t reserved[3]; + grub_uint32_t ndomains; + grub_uint64_t coherence; +}; + +struct grub_efi_sal_system_table_ap_wakeup +{ + grub_uint8_t type; + grub_uint8_t mechanism; + grub_uint8_t reserved[6]; + grub_uint64_t vector; +}; + +enum + { + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK = 1, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT = 2, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT = 4, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT = 8, + }; + /* Enumerations. */ enum grub_efi_timer_delay { @@ -184,6 +287,8 @@ typedef grub_uint64_t grub_efi_uint64_t; typedef grub_uint8_t grub_efi_char8_t; typedef grub_uint16_t grub_efi_char16_t; +#define PRIxGRUB_EFI_UINTN_T "lx" + typedef grub_efi_intn_t grub_efi_status_t; #define GRUB_EFI_ERROR_CODE(value) \ diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index 5852a476f..e9c57dd11 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -53,8 +53,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp); char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp); grub_efi_device_path_t * EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle); -int EXPORT_FUNC(grub_efi_exit_boot_services) (grub_efi_uintn_t map_key); -int EXPORT_FUNC (grub_efi_finish_boot_services) (void); +grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *efi_desc_size, + grub_efi_uint32_t *efi_desc_version); grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memory_map_size, grub_efi_uintn_t descriptor_size, grub_efi_uint32_t descriptor_version, @@ -70,4 +72,6 @@ void grub_efi_set_prefix (void); extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle); +extern int EXPORT_VAR(grub_efi_is_finished); + #endif /* ! GRUB_EFI_EFI_HEADER */ diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h index 285be8359..133f9504c 100644 --- a/include/grub/efi/memory.h +++ b/include/grub/efi/memory.h @@ -24,16 +24,6 @@ #define GRUB_MMAP_REGISTER_BY_FIRMWARE 1 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_RESERVED 2 -#define GRUB_MACHINE_MEMORY_ACPI 3 -#define GRUB_MACHINE_MEMORY_NVS 4 -#define GRUB_MACHINE_MEMORY_CODE 5 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 5 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 6 - grub_err_t grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 3980d32cd..8eee98b61 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -217,20 +217,22 @@ int grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size, grub_efi_uintn_t *map_key, grub_efi_uintn_t *descriptor_size, grub_efi_uint32_t *descriptor_version); + + +grub_err_t +grub_efiemu_finish_boot_services (grub_efi_uintn_t *memory_map_size, + grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version); + grub_err_t grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); int grub_efiemu_sizeof_uintn_t (void); -int grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key); -int grub_efiemu_finish_boot_services (void); grub_err_t grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper); -#define GRUB_EFIEMU_MEMORY_AVAILABLE 1 -#define GRUB_EFIEMU_MEMORY_RESERVED 2 -#define GRUB_EFIEMU_MEMORY_ACPI 3 -#define GRUB_EFIEMU_MEMORY_NVS 4 -#define GRUB_EFIEMU_MEMORY_CODE 5 /* efiemu main control definitions and functions*/ typedef enum {GRUB_EFIEMU_NOTLOADED, @@ -283,4 +285,6 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size, __attribute__ ((unused)), grub_efi_memory_descriptor_t *virtual_map); +grub_err_t grub_machine_efiemu_init_tables (void); + #endif /* ! GRUB_EFI_EMU_HEADER */ diff --git a/include/grub/elfload.h b/include/grub/elfload.h index 77ee41675..579656f23 100644 --- a/include/grub/elfload.h +++ b/include/grub/elfload.h @@ -46,13 +46,21 @@ grub_elf_t grub_elf_file (grub_file_t); grub_err_t grub_elf_close (grub_elf_t); int grub_elf_is_elf32 (grub_elf_t); -grub_size_t grub_elf32_size (grub_elf_t, Elf32_Addr *); +grub_size_t grub_elf32_size (grub_elf_t, Elf32_Addr *, grub_uint32_t *); grub_err_t grub_elf32_load (grub_elf_t, grub_elf32_load_hook_t, grub_addr_t *, grub_size_t *); int grub_elf_is_elf64 (grub_elf_t); -grub_size_t grub_elf64_size (grub_elf_t, Elf64_Addr *); +grub_size_t grub_elf64_size (grub_elf_t, Elf64_Addr *, grub_uint64_t *); grub_err_t grub_elf64_load (grub_elf_t, grub_elf64_load_hook_t, grub_addr_t *, grub_size_t *); +grub_err_t +grub_elf32_phdr_iterate (grub_elf_t elf, + int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *), + void *hook_arg); +grub_err_t +grub_elf64_phdr_iterate (grub_elf_t elf, + int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *), + void *hook_arg); #endif /* ! GRUB_ELFLOAD_HEADER */ diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index dff7b4df7..581ea8056 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -19,15 +19,19 @@ #ifndef GRUB_UTIL_GETROOT_HEADER #define GRUB_UTIL_GETROOT_HEADER 1 +#include + enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_NONE, GRUB_DEV_ABSTRACTION_LVM, GRUB_DEV_ABSTRACTION_RAID, }; +char *grub_find_device (const char *dir, dev_t dev); char *grub_guess_root_device (const char *dir); int grub_util_get_dev_abstraction (const char *os_dev); char *grub_util_get_grub_dev (const char *os_dev); +char *grub_make_system_path_relative_to_its_root (const char *path); const char *grub_util_check_block_device (const char *blk_dev); const char *grub_util_check_char_device (const char *blk_dev); diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 246046ee0..d8cc02e14 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -26,5 +26,7 @@ void grub_util_biosdisk_init (const char *dev_map); void grub_util_biosdisk_fini (void); char *grub_util_biosdisk_get_grub_dev (const char *os_dev); const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); +int grub_util_biosdisk_is_present (const char *name); +int grub_util_biosdisk_is_floppy (grub_disk_t disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index 70cf05e0d..ef0d18300 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -19,9 +19,11 @@ #ifndef GRUB_EMU_MISC_H #define GRUB_EMU_MISC_H 1 +#include +#include + #include #include -#include #ifdef __CYGWIN__ # include @@ -32,9 +34,9 @@ #ifdef __NetBSD__ /* NetBSD uses /boot for its boot block. */ -# define DEFAULT_DIRECTORY "/grub" +# define DEFAULT_DIRECTORY "/"GRUB_DIR_NAME #else -# define DEFAULT_DIRECTORY "/boot/grub" +# define DEFAULT_DIRECTORY "/"GRUB_BOOT_DIR_NAME"/"GRUB_DIR_NAME #endif #define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map" @@ -42,13 +44,13 @@ extern int verbosity; extern const char *program_name; +void grub_emu_init (void); void grub_init_all (void); void grub_fini_all (void); +void grub_emu_post_init (void); -char *grub_find_mount_point_from_dir (const char *dir) - __attribute__ ((warn_unused_result)); -void grub_find_zpool_from_mount_point (const char *mnt_point, - char **poolname, char **poolfs); +void grub_find_zpool_from_dir (const char *dir, + char **poolname, char **poolfs); char *grub_make_system_path_relative_to_its_root (const char *path) __attribute__ ((warn_unused_result)); @@ -76,6 +78,4 @@ extern char * canonicalize_file_name (const char *path); int grub_device_mapper_supported (void); #endif -libzfs_handle_t *grub_get_libzfs_handle (void); - #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/env.h b/include/grub/env.h index ae4fd8745..6d1f0de6e 100644 --- a/include/grub/env.h +++ b/include/grub/env.h @@ -51,7 +51,7 @@ grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name, grub_env_read_hook_t read_hook, grub_env_write_hook_t write_hook); -grub_err_t grub_env_context_open (int export); +grub_err_t grub_env_context_open (void); grub_err_t grub_env_context_close (void); grub_err_t grub_env_export (const char *name); @@ -59,4 +59,11 @@ void grub_env_unset_menu (void); grub_menu_t grub_env_get_menu (void); void grub_env_set_menu (grub_menu_t nmenu); +grub_err_t +grub_env_extractor_open (int source); + +grub_err_t +grub_env_extractor_close (int source); + + #endif /* ! GRUB_ENV_HEADER */ diff --git a/include/grub/err.h b/include/grub/err.h index e44705389..22334038d 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -50,11 +50,12 @@ typedef enum GRUB_ERR_BAD_FONT, GRUB_ERR_NOT_IMPLEMENTED_YET, GRUB_ERR_SYMLINK_LOOP, - GRUB_ERR_BAD_GZIP_DATA, + GRUB_ERR_BAD_COMPRESSED_DATA, GRUB_ERR_MENU, GRUB_ERR_TIMEOUT, GRUB_ERR_IO, - GRUB_ERR_ACCESS_DENIED + GRUB_ERR_ACCESS_DENIED, + GRUB_ERR_EXTRACTOR } grub_err_t; @@ -66,6 +67,7 @@ void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_error_push) (void); int EXPORT_FUNC(grub_error_pop) (void); void EXPORT_FUNC(grub_print_error) (void); +extern int EXPORT_VAR(grub_err_printed_errors); int grub_err_printf (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h index 03eaba8f8..19fe59266 100644 --- a/include/grub/extcmd.h +++ b/include/grub/extcmd.h @@ -21,10 +21,12 @@ #include #include +#include struct grub_extcmd; +struct grub_extcmd_context; -typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd *cmd, +typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd_context *ctxt, int argc, char **args); /* The argcmd description. */ @@ -38,18 +40,40 @@ struct grub_extcmd const struct grub_arg_option *options; void *data; - - struct grub_arg_list *state; }; typedef struct grub_extcmd *grub_extcmd_t; -grub_extcmd_t grub_register_extcmd (const char *name, - grub_extcmd_func_t func, - unsigned flags, - const char *summary, - const char *description, - const struct grub_arg_option *parser); +/* Command context for each instance of execution. */ +struct grub_extcmd_context +{ + struct grub_extcmd *extcmd; -void grub_unregister_extcmd (grub_extcmd_t cmd); + struct grub_arg_list *state; + + /* Script parameter, if any. */ + struct grub_script *script; +}; +typedef struct grub_extcmd_context *grub_extcmd_context_t; + +grub_extcmd_t EXPORT_FUNC(grub_register_extcmd) (const char *name, + grub_extcmd_func_t func, + grub_command_flags_t flags, + const char *summary, + const char *description, + const struct grub_arg_option *parser); + +grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_prio) (const char *name, + grub_extcmd_func_t func, + grub_command_flags_t flags, + const char *summary, + const char *description, + const struct grub_arg_option *parser, + int prio); + +void EXPORT_FUNC(grub_unregister_extcmd) (grub_extcmd_t cmd); + +grub_err_t EXPORT_FUNC(grub_extcmd_dispatcher) (struct grub_command *cmd, + int argc, char **args, + struct grub_script *script); #endif /* ! GRUB_EXTCMD_HEADER */ diff --git a/include/grub/file.h b/include/grub/file.h index 2aacf936f..72cd45468 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -39,6 +39,9 @@ struct grub_file /* The file size. */ grub_off_t size; + /* If file is not easly seekable. Should be set by underlying layer. */ + int not_easly_seekable; + /* Filesystem-specific data. */ void *data; @@ -48,6 +51,51 @@ struct grub_file }; typedef struct grub_file *grub_file_t; +/* Filters with lower ID are executed first. */ +typedef enum grub_file_filter_id + { + GRUB_FILE_FILTER_GZIO, + GRUB_FILE_FILTER_XZIO, + GRUB_FILE_FILTER_MAX, + GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO, + GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_XZIO, + } grub_file_filter_id_t; + +typedef grub_file_t (*grub_file_filter_t) (grub_file_t in); + +extern grub_file_filter_t EXPORT_VAR(grub_file_filters_all)[GRUB_FILE_FILTER_MAX]; +extern grub_file_filter_t EXPORT_VAR(grub_file_filters_enabled)[GRUB_FILE_FILTER_MAX]; + +static inline void +grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter) +{ + grub_file_filters_all[id] = filter; + grub_file_filters_enabled[id] = filter; +}; + +static inline void +grub_file_filter_unregister (grub_file_filter_id_t id) +{ + grub_file_filters_all[id] = 0; + grub_file_filters_enabled[id] = 0; +}; + +static inline void +grub_file_filter_disable (grub_file_filter_id_t id) +{ + grub_file_filters_enabled[id] = 0; +}; + +static inline void +grub_file_filter_disable_compression (void) +{ + grub_file_filter_id_t id; + + for (id = GRUB_FILE_FILTER_COMPRESSION_FIRST; + id <= GRUB_FILE_FILTER_COMPRESSION_LAST; id++) + grub_file_filters_enabled[id] = 0; +}; + /* Get a device name from NAME. */ char *EXPORT_FUNC(grub_file_get_device_name) (const char *name); @@ -57,6 +105,9 @@ grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf, grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset); grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file); +/* Return value of grub_file_size() in case file size is unknown. */ +#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL + static inline grub_off_t grub_file_size (const grub_file_t file) { @@ -69,4 +120,10 @@ grub_file_tell (const grub_file_t file) return file->offset; } +static inline int +grub_file_seekable (const grub_file_t file) +{ + return !file->not_easly_seekable; +} + #endif /* ! GRUB_FILE_HEADER */ diff --git a/include/grub/gzio.h b/include/grub/gzio.h deleted file mode 100644 index cd7f39793..000000000 --- a/include/grub/gzio.h +++ /dev/null @@ -1,28 +0,0 @@ -/* gzio.h - prototypes for gzio */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,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 . - */ - -#ifndef GRUB_GZIO_H -#define GRUB_GZIO_H 1 - -#include - -grub_file_t grub_gzio_open (grub_file_t io, int transparent); -grub_file_t grub_gzfile_open (const char *name, int transparent); - -#endif /* ! GRUB_GZIO_H */ diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h index 4d55f04fb..53008cdaf 100644 --- a/include/grub/i386/bsd.h +++ b/include/grub/i386/bsd.h @@ -20,6 +20,8 @@ #define GRUB_BSD_CPU_HEADER 1 #include +#include + #include #include #include @@ -27,7 +29,6 @@ #include #include - enum bsd_kernel_types { KERNEL_TYPE_NONE, @@ -65,35 +66,55 @@ struct grub_freebsd_bootinfo grub_uint32_t tags; } __attribute__ ((packed)); -struct grub_openbsd_bios_mmap +struct freebsd_tag_header { - grub_uint64_t addr; - grub_uint64_t len; -#define OPENBSD_MMAP_AVAILABLE 1 -#define OPENBSD_MMAP_RESERVED 2 -#define OPENBSD_MMAP_ACPI 3 -#define OPENBSD_MMAP_NVS 4 grub_uint32_t type; + grub_uint32_t len; }; -void grub_unix_real_boot (grub_addr_t entry, ...) - __attribute__ ((cdecl,noreturn)); -grub_err_t grub_freebsd_load_elfmodule32 (grub_file_t file, int argc, +grub_err_t grub_freebsd_load_elfmodule32 (struct grub_relocator *relocator, + grub_file_t file, int argc, char *argv[], grub_addr_t *kern_end); -grub_err_t grub_freebsd_load_elfmodule_obj64 (grub_file_t file, int argc, +grub_err_t grub_freebsd_load_elfmodule_obj64 (struct grub_relocator *relocator, + grub_file_t file, int argc, char *argv[], grub_addr_t *kern_end); -grub_err_t grub_freebsd_load_elf_meta32 (grub_file_t file, +grub_err_t grub_freebsd_load_elf_meta32 (struct grub_relocator *relocator, + grub_file_t file, grub_addr_t *kern_end); -grub_err_t grub_freebsd_load_elf_meta64 (grub_file_t file, +grub_err_t grub_freebsd_load_elf_meta64 (struct grub_relocator *relocator, + grub_file_t file, grub_addr_t *kern_end); -grub_err_t grub_freebsd_add_meta (grub_uint32_t type, void *data, - grub_uint32_t len); +grub_err_t grub_netbsd_load_elf_meta32 (struct grub_relocator *relocator, + grub_file_t file, + grub_addr_t *kern_end); +grub_err_t grub_netbsd_load_elf_meta64 (struct grub_relocator *relocator, + grub_file_t file, + grub_addr_t *kern_end); + +grub_err_t grub_bsd_add_meta (grub_uint32_t type, + void *data, grub_uint32_t len); grub_err_t grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv, grub_addr_t addr, grub_uint32_t size); +struct grub_openbsd_ramdisk_descriptor +{ + grub_size_t max_size; + grub_uint8_t *target; + grub_uint32_t *size; +}; + +grub_err_t grub_openbsd_find_ramdisk32 (grub_file_t file, + grub_addr_t kern_start, + void *kern_chunk_src, + struct grub_openbsd_ramdisk_descriptor *desc); +grub_err_t grub_openbsd_find_ramdisk64 (grub_file_t file, + grub_addr_t kern_start, + void *kern_chunk_src, + struct grub_openbsd_ramdisk_descriptor *desc); + extern grub_uint8_t grub_bsd64_trampoline_start, grub_bsd64_trampoline_end; extern grub_uint32_t grub_bsd64_trampoline_selfjump; extern grub_uint32_t grub_bsd64_trampoline_gdt; diff --git a/include/grub/i386/coreboot/lbio.h b/include/grub/i386/coreboot/lbio.h new file mode 100644 index 000000000..aa1853933 --- /dev/null +++ b/include/grub/i386/coreboot/lbio.h @@ -0,0 +1,49 @@ +/* memory.h - describe the memory map */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2007,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 . + */ + +#ifndef _GRUB_MACHINE_LBIO_HEADER +#define _GRUB_MACHINE_LBIO_HEADER 1 + +struct grub_linuxbios_table_header +{ + char signature[4]; + grub_uint32_t size; +}; +typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t; + +struct grub_linuxbios_table_item +{ +#define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00 +#define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01 +#define GRUB_LINUXBIOS_MEMBER_LINK 0x11 + grub_uint32_t tag; + grub_uint32_t size; +}; +typedef struct grub_linuxbios_table_item *grub_linuxbios_table_item_t; + +struct grub_linuxbios_mem_region +{ + grub_uint64_t addr; + grub_uint64_t size; +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 + grub_uint32_t type; +}; +typedef struct grub_linuxbios_mem_region *mem_region_t; + +#endif diff --git a/include/grub/i386/coreboot/loader.h b/include/grub/i386/coreboot/loader.h deleted file mode 100644 index d3f36bba5..000000000 --- a/include/grub/i386/coreboot/loader.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h index 664086a81..0642280b9 100644 --- a/include/grub/i386/coreboot/memory.h +++ b/include/grub/i386/coreboot/memory.h @@ -21,11 +21,11 @@ #define _GRUB_MEMORY_MACHINE_LB_HEADER 1 #include -#include #ifndef ASM_FILE #include #include +#include #endif #define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ @@ -35,36 +35,21 @@ #ifndef ASM_FILE -struct grub_linuxbios_table_header -{ - char signature[4]; - grub_uint32_t size; -}; -typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t; - -struct grub_linuxbios_table_item -{ -#define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00 -#define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01 -#define GRUB_LINUXBIOS_MEMBER_LINK 0x11 - grub_uint32_t tag; - grub_uint32_t size; -}; -typedef struct grub_linuxbios_table_item *grub_linuxbios_table_item_t; - -struct grub_linuxbios_mem_region -{ - grub_uint64_t addr; - grub_uint64_t size; -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - grub_uint32_t type; -}; -typedef struct grub_linuxbios_mem_region *mem_region_t; - void grub_machine_mmap_init (void); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); +static inline grub_err_t +grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + int type __attribute__ ((unused)), + int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +static inline grub_err_t +grub_machine_mmap_unregister (int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} #endif diff --git a/include/grub/i386/floppy.h b/include/grub/i386/floppy.h new file mode 100644 index 000000000..0e3690549 --- /dev/null +++ b/include/grub/i386/floppy.h @@ -0,0 +1,36 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,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 . + */ + +#ifndef GRUB_FLOPPY_CPU_HEADER +#define GRUB_FLOPPY_CPU_HEADER 1 + +#define GRUB_FLOPPY_REG_DIGITAL_OUTPUT 0x3f2 + +#ifndef ASM_FILE +#include + +/* Stop the floppy drive from spinning, so that other software is + jumped to with a known state. */ +static inline void +grub_stop_floppy (void) +{ + grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT); +} +#endif + +#endif diff --git a/include/grub/i386/ieee1275/memory.h b/include/grub/i386/ieee1275/memory.h index 386ee4a05..8dd6f7c8c 100644 --- a/include/grub/i386/ieee1275/memory.h +++ b/include/grub/i386/ieee1275/memory.h @@ -1 +1 @@ -#include +#include diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h index f02a722d6..63f99db62 100644 --- a/include/grub/i386/linux.h +++ b/include/grub/i386/linux.h @@ -124,7 +124,7 @@ struct linux_kernel_header grub_uint32_t bootsect_kludge; /* obsolete */ grub_uint16_t heap_end_ptr; /* Free memory after setup end */ grub_uint16_t pad1; /* Unused */ - char *cmd_line_ptr; /* Points to the kernel command line */ + grub_uint32_t cmd_line_ptr; /* Points to the kernel command line */ grub_uint32_t initrd_addr_max; /* Highest address for initrd */ } __attribute__ ((packed)); diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h index 466947cc6..582226eed 100644 --- a/include/grub/i386/memory.h +++ b/include/grub/i386/memory.h @@ -22,9 +22,42 @@ /* The flag for protected mode. */ #define GRUB_MEMORY_CPU_CR0_PE_ON 0x1 -#define GRUB_MEMORY_CPU_CR4_PAE_ON 0x00000040 +#define GRUB_MEMORY_CPU_CR4_PAE_ON 0x00000020 +#define GRUB_MEMORY_CPU_CR4_PSE_ON 0x00000010 #define GRUB_MEMORY_CPU_CR0_PAGING_ON 0x80000000 #define GRUB_MEMORY_CPU_AMD64_MSR 0xc0000080 #define GRUB_MEMORY_CPU_AMD64_MSR_ON 0x00000100 +#ifndef ASM_FILE + +#define GRUB_MMAP_MALLOC_LOW 1 + +#include + +grub_uint64_t grub_mmap_get_upper (void); +grub_uint64_t grub_mmap_get_lower (void); +grub_uint64_t grub_mmap_get_post64 (void); + +typedef grub_addr_t grub_phys_addr_t; + +static inline grub_phys_addr_t +grub_vtop (void *a) +{ + return (grub_phys_addr_t) a; +} + +static inline void * +grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) +{ + return (void *) a; +} + +static inline void +grub_unmap_memory (void *a __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} + +#endif + #endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h index 1c711fad4..a1b94883d 100644 --- a/include/grub/i386/multiboot.h +++ b/include/grub/i386/multiboot.h @@ -19,11 +19,6 @@ #ifndef GRUB_MULTIBOOT_CPU_HEADER #define GRUB_MULTIBOOT_CPU_HEADER 1 -extern grub_uint32_t grub_multiboot_payload_eip; -extern char *grub_multiboot_payload_orig; -extern grub_addr_t grub_multiboot_payload_dest; -extern grub_size_t grub_multiboot_payload_size; - #define MULTIBOOT_INITIAL_STATE { .eax = MULTIBOOT_BOOTLOADER_MAGIC, \ .ecx = 0, \ .edx = 0, \ diff --git a/include/grub/i386/multiboot/init.h b/include/grub/i386/multiboot/init.h deleted file mode 100644 index fd935c3a2..000000000 --- a/include/grub/i386/multiboot/init.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/grub/i386/multiboot/loader.h b/include/grub/i386/multiboot/loader.h deleted file mode 100644 index 1c725be19..000000000 --- a/include/grub/i386/multiboot/loader.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/grub/i386/netbsd_bootinfo.h b/include/grub/i386/netbsd_bootinfo.h index 776ecf3b0..fd429a251 100644 --- a/include/grub/i386/netbsd_bootinfo.h +++ b/include/grub/i386/netbsd_bootinfo.h @@ -49,64 +49,90 @@ #include - #define NETBSD_BTINFO_BOOTPATH 0 #define NETBSD_BTINFO_ROOTDEVICE 1 -#define NETBSD_BTINFO_BOOTDISK 3 +#define NETBSD_BTINFO_CONSOLE 6 +#define NETBSD_BTINFO_SYMTAB 8 #define NETBSD_BTINFO_MEMMAP 9 +#define NETBSD_BTINFO_MODULES 11 +#define NETBSD_BTINFO_FRAMEBUF 12 + +struct grub_netbsd_bootinfo +{ + grub_uint32_t bi_count; + grub_uint32_t bi_data[0]; +}; struct grub_netbsd_btinfo_common { - int len; - int type; -}; - -struct grub_netbsd_btinfo_mmap_header -{ - struct grub_netbsd_btinfo_common common; - grub_uint32_t count; -}; - -struct grub_netbsd_btinfo_mmap_entry -{ - grub_uint64_t addr; - grub_uint64_t len; -#define NETBSD_MMAP_AVAILABLE 1 -#define NETBSD_MMAP_RESERVED 2 -#define NETBSD_MMAP_ACPI 3 -#define NETBSD_MMAP_NVS 4 + grub_uint32_t len; grub_uint32_t type; }; -struct grub_netbsd_btinfo_bootpath -{ - struct grub_netbsd_btinfo_common common; - char bootpath[80]; -}; - -struct grub_netbsd_btinfo_rootdevice -{ - struct grub_netbsd_btinfo_common common; - char devname[16]; -}; +#define GRUB_NETBSD_MAX_BOOTPATH_LEN 80 struct grub_netbsd_btinfo_bootdisk { - struct grub_netbsd_btinfo_common common; - int labelsector; /* label valid if != -1 */ + grub_uint32_t labelsector; /* label valid if != 0xffffffff */ struct { grub_uint16_t type, checksum; char packname[16]; } label; - int biosdev; - int partition; + grub_uint32_t biosdev; + grub_uint32_t partition; }; -struct grub_netbsd_bootinfo +struct grub_netbsd_btinfo_symtab { - grub_uint32_t bi_count; - void *bi_data[1]; + grub_uint32_t nsyms; + grub_uint32_t ssyms; + grub_uint32_t esyms; }; + +struct grub_netbsd_btinfo_serial +{ + char devname[16]; + grub_uint32_t addr; + grub_uint32_t speed; +}; + +struct grub_netbsd_btinfo_modules +{ + grub_uint32_t num; + grub_uint32_t last_addr; + struct grub_netbsd_btinfo_module + { + char name[80]; +#define GRUB_NETBSD_MODULE_RAW 0 +#define GRUB_NETBSD_MODULE_ELF 1 + grub_uint32_t type; + grub_uint32_t size; + grub_uint32_t addr; + } mods[0]; +}; + +struct grub_netbsd_btinfo_framebuf +{ + grub_uint64_t fbaddr; + grub_uint32_t flags; + grub_uint32_t width; + grub_uint32_t height; + grub_uint16_t pitch; + grub_uint8_t bpp; + + grub_uint8_t red_mask_size; + grub_uint8_t green_mask_size; + grub_uint8_t blue_mask_size; + + grub_uint8_t red_field_pos; + grub_uint8_t green_field_pos; + grub_uint8_t blue_field_pos; + + grub_uint8_t reserved[16]; +}; + +#define GRUB_NETBSD_MAX_ROOTDEVICE_LEN 16 + #endif diff --git a/include/grub/i386/openbsd_bootarg.h b/include/grub/i386/openbsd_bootarg.h index ccbe1ca12..935dfc0c8 100644 --- a/include/grub/i386/openbsd_bootarg.h +++ b/include/grub/i386/openbsd_bootarg.h @@ -61,12 +61,22 @@ #define OPENBSD_BOOTARG_END -1 #define OPENBSD_BOOTARG_MMAP 0 +#define OPENBSD_BOOTARG_CONSOLE 5 struct grub_openbsd_bootargs { - int ba_type; - int ba_size; - struct grub_openbsd_bootargs *ba_next; + grub_uint32_t ba_type; + grub_uint32_t ba_size; + grub_uint32_t ba_next; } __attribute__ ((packed)); +struct grub_openbsd_bootarg_console +{ + grub_uint32_t device; + grub_uint32_t speed; +}; + +#define GRUB_OPENBSD_COM_MAJOR 8 +#define GRUB_OPENBSD_VGA_MAJOR 12 + #endif diff --git a/include/grub/i386/loader.h b/include/grub/i386/pc/apm.h similarity index 52% rename from include/grub/i386/loader.h rename to include/grub/i386/pc/apm.h index 05954b6db..6d9e8c61d 100644 --- a/include/grub/i386/loader.h +++ b/include/grub/i386/pc/apm.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2007,2008,2009,2010 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 @@ -16,22 +16,33 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_LOADER_CPU_HEADER -#define GRUB_LOADER_CPU_HEADER 1 +#ifndef GRUB_APM_MACHINE_HEADER +#define GRUB_APM_MACHINE_HEADER 1 #include -#include -#include -extern grub_addr_t EXPORT_VAR(grub_os_area_addr); -extern grub_size_t EXPORT_VAR(grub_os_area_size); +struct grub_apm_info +{ + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; + grub_uint16_t version; +}; + +enum + { + GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED = 1, + GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED = 2, + GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN = 4, + GRUB_APM_FLAGS_DISABLED = 8, + GRUB_APM_FLAGS_DISENGAGED = 16, + }; + +int grub_apm_get_info (struct grub_apm_info *info); -#ifdef GRUB_MACHINE_PCBIOS -extern grub_uint32_t EXPORT_VAR(grub_linux_prot_size); -extern char *EXPORT_VAR(grub_linux_tmp_addr); -extern char *EXPORT_VAR(grub_linux_real_addr); -extern grub_int32_t EXPORT_VAR(grub_linux_is_bzimage); -grub_err_t EXPORT_FUNC(grub_linux16_real_boot) (void); #endif - -#endif /* ! GRUB_LOADER_CPU_HEADER */ diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h index b87e0e433..f8a9b463f 100644 --- a/include/grub/i386/pc/biosdisk.h +++ b/include/grub/i386/pc/biosdisk.h @@ -106,21 +106,4 @@ struct grub_biosdisk_dap grub_uint64_t block; } __attribute__ ((packed)); -int EXPORT_FUNC(grub_biosdisk_rw_int13_extensions) (int ah, int drive, void *dap); -int EXPORT_FUNC(grub_biosdisk_rw_standard) (int ah, int drive, int coff, int hoff, - int soff, int nsec, int segment); -int EXPORT_FUNC(grub_biosdisk_check_int13_extensions) (int drive); -int EXPORT_FUNC(grub_biosdisk_get_diskinfo_int13_extensions) (int drive, - void *drp); -int EXPORT_FUNC(grub_biosdisk_get_cdinfo_int13_extensions) (int drive, - void *cdrp); -int EXPORT_FUNC(grub_biosdisk_get_diskinfo_standard) (int drive, - unsigned long *cylinders, - unsigned long *heads, - unsigned long *sectors); -int EXPORT_FUNC(grub_biosdisk_get_num_floppies) (void); - -void grub_biosdisk_init (void); -void grub_biosdisk_fini (void); - #endif /* ! GRUB_BIOSDISK_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h index 7f58344ec..1631a40ad 100644 --- a/include/grub/i386/pc/console.h +++ b/include/grub/i386/pc/console.h @@ -19,19 +19,6 @@ #ifndef GRUB_CONSOLE_MACHINE_HEADER #define GRUB_CONSOLE_MACHINE_HEADER 1 -/* Define scan codes. */ -#define GRUB_CONSOLE_KEY_LEFT 0x4B00 -#define GRUB_CONSOLE_KEY_RIGHT 0x4D00 -#define GRUB_CONSOLE_KEY_UP 0x4800 -#define GRUB_CONSOLE_KEY_DOWN 0x5000 -#define GRUB_CONSOLE_KEY_IC 0x5200 -#define GRUB_CONSOLE_KEY_DC 0x5300 -#define GRUB_CONSOLE_KEY_BACKSPACE 0x0008 -#define GRUB_CONSOLE_KEY_HOME 0x4700 -#define GRUB_CONSOLE_KEY_END 0x4F00 -#define GRUB_CONSOLE_KEY_NPAGE 0x5100 -#define GRUB_CONSOLE_KEY_PPAGE 0x4900 - #ifndef ASM_FILE #include @@ -40,7 +27,6 @@ #include /* These are global to share code between C and asm. */ -int grub_console_checkkey (struct grub_term_input *term); int grub_console_getkey (struct grub_term_input *term); grub_uint16_t grub_console_getxy (struct grub_term_output *term); void grub_console_gotoxy (struct grub_term_output *term, diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h deleted file mode 100644 index 30130d189..000000000 --- a/include/grub/i386/pc/init.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2005,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 . - */ - -#ifndef GRUB_INIT_MACHINE_HEADER -#define GRUB_INIT_MACHINE_HEADER 1 - -#include -#include -#include - -/* Get the memory size in KB. If EXTENDED is zero, return conventional - memory, otherwise return extended memory. */ -grub_uint16_t grub_get_memsize (int extended); - -/* Get a packed EISA memory map. Lower 16 bits are between 1MB and 16MB - in 1KB parts, and upper 16 bits are above 16MB in 64KB parts. */ -grub_uint32_t grub_get_eisa_mmap (void); - -/* Get a memory map entry. Return next continuation value. Zero means - the end. */ -grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, - grub_uint32_t cont); - -/* Turn on/off Gate A20. */ -void grub_gate_a20 (int on); - -void EXPORT_FUNC(grub_stop_floppy) (void); - -#endif /* ! GRUB_INIT_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h new file mode 100644 index 000000000..de23775d0 --- /dev/null +++ b/include/grub/i386/pc/int.h @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +#ifndef GRUB_INTERRUPT_MACHINE_HEADER +#define GRUB_INTERRUPT_MACHINE_HEADER 1 + +#include +#include + +struct grub_bios_int_registers +{ + grub_uint32_t eax; + grub_uint16_t es; + grub_uint16_t ds; + grub_uint16_t flags; + grub_uint16_t dummy; + grub_uint32_t ebx; + grub_uint32_t ecx; + grub_uint32_t edi; + grub_uint32_t esi; + grub_uint32_t edx; +}; + +#define GRUB_CPU_INT_FLAGS_CARRY 0x1 +#define GRUB_CPU_INT_FLAGS_PARITY 0x4 +#define GRUB_CPU_INT_FLAGS_ADJUST 0x10 +#define GRUB_CPU_INT_FLAGS_ZERO 0x40 +#define GRUB_CPU_INT_FLAGS_SIGN 0x80 +#define GRUB_CPU_INT_FLAGS_TRAP 0x100 +#define GRUB_CPU_INT_FLAGS_INTERRUPT 0x200 +#define GRUB_CPU_INT_FLAGS_DIRECTION 0x400 +#define GRUB_CPU_INT_FLAGS_OVERFLOW 0x800 +#define GRUB_CPU_INT_FLAGS_DEFAULT GRUB_CPU_INT_FLAGS_INTERRUPT + +void EXPORT_FUNC (grub_bios_interrupt) (grub_uint8_t intno, + struct grub_bios_int_registers *regs); + +#endif diff --git a/include/grub/i386/pc/loader.h b/include/grub/i386/pc/loader.h index 3e031413b..bfbcaac5a 100644 --- a/include/grub/i386/pc/loader.h +++ b/include/grub/i386/pc/loader.h @@ -20,7 +20,6 @@ #define GRUB_LOADER_MACHINE_HEADER 1 #include -#include /* This is an asm part of the chainloader. */ void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn)); diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h index 68f5e8bc9..401c837fa 100644 --- a/include/grub/i386/pc/memory.h +++ b/include/grub/i386/pc/memory.h @@ -88,51 +88,9 @@ struct grub_machine_bios_data_area grub_uint8_t unused2[0xf0 - 0x18]; }; -struct grub_machine_mmap_entry -{ - grub_uint32_t size; - grub_uint64_t addr; - grub_uint64_t len; -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_RESERVED 2 -#define GRUB_MACHINE_MEMORY_ACPI 3 -#define GRUB_MACHINE_MEMORY_NVS 4 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 4 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 5 - - grub_uint32_t type; -} __attribute__((packed)); - -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - -grub_uint64_t grub_mmap_get_post64 (void); -grub_uint64_t grub_mmap_get_upper (void); -grub_uint64_t grub_mmap_get_lower (void); - -#define GRUB_MMAP_MALLOC_LOW 1 - -#ifdef GRUB_MACHINE_PCBIOS grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, int type, int handle); grub_err_t grub_machine_mmap_unregister (int handle); -#else -static inline grub_err_t -grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - int type __attribute__ ((unused)), - int handle __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} -static inline grub_err_t -grub_machine_mmap_unregister (int handle __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} -#endif #endif diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 39f356c83..62ece21b0 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -168,6 +168,8 @@ #ifndef ASM_FILE +#define GRUB_PXE_SIGNATURE "PXENV+" + struct grub_pxenv { grub_uint8_t signature[6]; /* 'PXENV+'. */ @@ -190,6 +192,19 @@ struct grub_pxenv grub_uint32_t pxe_ptr; /* SEG:OFF to !PXE struct. */ } __attribute__ ((packed)); +struct grub_pxe_bangpxe +{ + grub_uint8_t signature[4]; +#define GRUB_PXE_BANGPXE_SIGNATURE "!PXE" + grub_uint8_t length; + grub_uint8_t chksum; + grub_uint8_t rev; + grub_uint8_t reserved; + grub_uint32_t undiromid; + grub_uint32_t baseromid; + grub_uint32_t rm_entry; +} __attribute__ ((packed)); + struct grub_pxenv_get_cached_info { grub_uint16_t status; @@ -302,10 +317,9 @@ struct grub_pxenv_unload_stack grub_uint8_t reserved[10]; } __attribute__ ((packed)); -struct grub_pxenv * EXPORT_FUNC(grub_pxe_scan) (void); -int EXPORT_FUNC(grub_pxe_call) (int func, void * data); +int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entry); -extern struct grub_pxenv *grub_pxe_pxenv; +extern struct grub_pxe_bangpxe *grub_pxe_pxenv; void grub_pxe_unload (void); diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index abf246fa1..fba3ee642 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -169,62 +169,49 @@ struct grub_vbe_palette_data grub_uint8_t alignment; } __attribute__ ((packed)); -/* Prototypes for kernel real mode thunks. */ - +/* Prototypes for helper functions. */ /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct grub_vbe_info_block *controller_info); - +grub_vbe_status_t +grub_vbe_bios_get_controller_info (struct grub_vbe_info_block *controller_info); /* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode, - struct grub_vbe_mode_info_block *mode_info); +grub_vbe_status_t +grub_vbe_bios_get_mode_info (grub_uint32_t mode, + struct grub_vbe_mode_info_block *mode_info); +/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_mode (grub_uint32_t *mode); +/* Call VESA BIOS 0x4f05 to set memory window, return status. */ +grub_vbe_status_t +grub_vbe_bios_set_memory_window (grub_uint32_t window, grub_uint32_t position); +/* Call VESA BIOS 0x4f05 to return memory window, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_memory_window (grub_uint32_t window, + grub_uint32_t *position); +/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */ +grub_vbe_status_t +grub_vbe_bios_set_scanline_length (grub_uint32_t length); +/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */ +grub_vbe_status_t +grub_vbe_bios_get_scanline_length (grub_uint32_t *length); +/* Call VESA BIOS 0x4f07 to get display start, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_display_start (grub_uint32_t *x, + grub_uint32_t *y); -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_getset_dac_palette_width) (int set, int *width); +grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); #define grub_vbe_bios_get_dac_palette_width(width) grub_vbe_bios_getset_dac_palette_width(0, (width)) #define grub_vbe_bios_set_dac_palette_width(width) grub_vbe_bios_getset_dac_palette_width(1, (width)) -/* Call VESA BIOS 0x4f02 to set video mode, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode, - struct grub_vbe_crtc_info_block *crtc_info); - -/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode); - -/* Call VESA BIOS 0x4f05 to set memory window, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t window, - grub_uint32_t position); - -/* Call VESA BIOS 0x4f05 to return memory window, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t window, - grub_uint32_t *position); - -/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) (grub_uint32_t length); - -/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) (grub_uint32_t *length); - -/* Call VESA BIOS 0x4f07 to set display start, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t x, - grub_uint32_t y); - -/* Call VESA BIOS 0x4f07 to get display start, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t *x, - grub_uint32_t *y); - -/* Call VESA BIOS 0x4f09 to set palette data, return status. */ -grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t color_count, - grub_uint32_t start_index, - struct grub_vbe_palette_data *palette_data); - -/* Prototypes for helper functions. */ - grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block); grub_err_t grub_vbe_set_video_mode (grub_uint32_t mode, struct grub_vbe_mode_info_block *mode_info); grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode); grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode, struct grub_vbe_mode_info_block *mode_info); +grub_vbe_status_t +grub_vbe_bios_get_pm_interface (grub_uint16_t *seg, grub_uint16_t *offset, + grub_uint16_t *length); #endif /* ! GRUB_VBE_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/vesa_modes_table.h b/include/grub/i386/pc/vesa_modes_table.h new file mode 100644 index 000000000..376ca376b --- /dev/null +++ b/include/grub/i386/pc/vesa_modes_table.h @@ -0,0 +1,19 @@ +#ifndef GRUB_VESA_MODE_TABLE_HEADER +#define GRUB_VESA_MODE_TABLE_HEADER 1 + +#include + +#define GRUB_VESA_MODE_TABLE_START 0x300 +#define GRUB_VESA_MODE_TABLE_END 0x373 + +struct grub_vesa_mode_table_entry { + grub_uint16_t width; + grub_uint16_t height; + grub_uint8_t depth; +}; + +extern struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1]; + +#endif diff --git a/include/grub/i386/pc/vga.h b/include/grub/i386/pc/vga.h index 2724f6401..ecc169022 100644 --- a/include/grub/i386/pc/vga.h +++ b/include/grub/i386/pc/vga.h @@ -25,7 +25,4 @@ /* The VGA (at the beginning of upper memory). */ #define GRUB_MEMORY_MACHINE_VGA_ADDR GRUB_MEMORY_MACHINE_UPPER -/* Set the video mode to MODE and return the previous mode. */ -unsigned char EXPORT_FUNC(grub_vga_set_mode) (unsigned char mode); - #endif /* ! GRUB_VGA_MACHINE_HEADER */ diff --git a/include/grub/i386/qemu/init.h b/include/grub/i386/qemu/init.h deleted file mode 100644 index fd935c3a2..000000000 --- a/include/grub/i386/qemu/init.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/grub/i386/qemu/loader.h b/include/grub/i386/qemu/loader.h deleted file mode 100644 index d3f36bba5..000000000 --- a/include/grub/i386/qemu/loader.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/grub/i386/qemu/memory.h b/include/grub/i386/qemu/memory.h index de559443d..2003e4934 100644 --- a/include/grub/i386/qemu/memory.h +++ b/include/grub/i386/qemu/memory.h @@ -21,7 +21,7 @@ #define _GRUB_MEMORY_MACHINE_HEADER 1 #include -#include +#include #ifndef ASM_FILE #include @@ -37,9 +37,6 @@ void grub_machine_mmap_init (void); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - #endif #endif /* ! _GRUB_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/i386/relocator.h b/include/grub/i386/relocator.h index ef7fe23aa..6ff5c6631 100644 --- a/include/grub/i386/relocator.h +++ b/include/grub/i386/relocator.h @@ -21,21 +21,54 @@ #include #include +#include struct grub_relocator32_state { grub_uint32_t esp; + grub_uint32_t ebp; grub_uint32_t eax; grub_uint32_t ebx; grub_uint32_t ecx; grub_uint32_t edx; grub_uint32_t eip; + grub_uint32_t esi; + grub_uint32_t edi; }; -void *grub_relocator32_alloc (grub_size_t size); -grub_err_t grub_relocator32_boot (void *relocator, grub_uint32_t dest, +struct grub_relocator16_state +{ + grub_uint16_t cs; + grub_uint16_t ds; + grub_uint16_t es; + grub_uint16_t fs; + grub_uint16_t gs; + grub_uint16_t ss; + grub_uint16_t sp; + grub_uint16_t ip; + grub_uint32_t edx; +}; + +struct grub_relocator64_state +{ + grub_uint64_t rsp; + grub_uint64_t rax; + grub_uint64_t rbx; + grub_uint64_t rcx; + grub_uint64_t rdx; + grub_uint64_t rip; + grub_uint64_t rsi; + grub_addr_t cr3; +}; + +grub_err_t grub_relocator16_boot (struct grub_relocator *rel, + struct grub_relocator16_state state); + +grub_err_t grub_relocator32_boot (struct grub_relocator *rel, struct grub_relocator32_state state); -void *grub_relocator32_realloc (void *relocator, grub_size_t size); -void grub_relocator32_free (void *relocator); + +grub_err_t grub_relocator64_boot (struct grub_relocator *rel, + struct grub_relocator64_state state, + grub_addr_t min_addr, grub_addr_t max_addr); #endif /* ! GRUB_RELOCATOR_CPU_HEADER */ diff --git a/include/grub/i386/xnu.h b/include/grub/i386/xnu.h index 2fa2639c1..386c8b9e0 100644 --- a/include/grub/i386/xnu.h +++ b/include/grub/i386/xnu.h @@ -115,5 +115,4 @@ extern grub_uint32_t grub_xnu_arg1; extern char grub_xnu_cmdline[1024]; grub_err_t grub_xnu_boot (void); grub_err_t grub_cpu_xnu_fill_devicetree (void); -extern grub_uint32_t grub_xnu_heap_will_be_at; #endif diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index b30909c68..2592dd348 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -103,6 +103,9 @@ enum grub_ieee1275_flag /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM, + + /* OLPC / XO firmware has the cursor ON/OFF routines. */ + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF, }; extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); @@ -187,4 +190,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); +char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); + #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/kernel.h b/include/grub/kernel.h index fed875db1..2ecc73df4 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -26,8 +26,7 @@ enum { OBJ_TYPE_ELF, OBJ_TYPE_MEMDISK, - OBJ_TYPE_CONFIG, - OBJ_TYPE_FONT + OBJ_TYPE_CONFIG }; /* The module header. */ diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h new file mode 100644 index 000000000..24d4880af --- /dev/null +++ b/include/grub/keyboard_layouts.h @@ -0,0 +1,142 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#ifndef GRUB_KEYBOARD_LAYOUTS_H +#define GRUB_KEYBOARD_LAYOUTS_H 1 + +#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" +#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) +#define GRUB_KEYBOARD_LAYOUTS_VERSION 8 + +#define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 + +struct grub_keyboard_layout +{ + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; +}; + +typedef enum grub_keyboard_key + { + GRUB_KEYBOARD_KEY_A = 0x04, + GRUB_KEYBOARD_KEY_B = 0x05, + GRUB_KEYBOARD_KEY_C = 0x06, + GRUB_KEYBOARD_KEY_D = 0x07, + GRUB_KEYBOARD_KEY_E = 0x08, + GRUB_KEYBOARD_KEY_F = 0x09, + GRUB_KEYBOARD_KEY_G = 0x0a, + GRUB_KEYBOARD_KEY_H = 0x0b, + GRUB_KEYBOARD_KEY_I = 0x0c, + GRUB_KEYBOARD_KEY_J = 0x0d, + GRUB_KEYBOARD_KEY_K = 0x0e, + GRUB_KEYBOARD_KEY_L = 0x0f, + GRUB_KEYBOARD_KEY_M = 0x10, + GRUB_KEYBOARD_KEY_N = 0x11, + GRUB_KEYBOARD_KEY_O = 0x12, + GRUB_KEYBOARD_KEY_P = 0x13, + GRUB_KEYBOARD_KEY_Q = 0x14, + GRUB_KEYBOARD_KEY_R = 0x15, + GRUB_KEYBOARD_KEY_S = 0x16, + GRUB_KEYBOARD_KEY_T = 0x17, + GRUB_KEYBOARD_KEY_U = 0x18, + GRUB_KEYBOARD_KEY_V = 0x19, + GRUB_KEYBOARD_KEY_W = 0x1a, + GRUB_KEYBOARD_KEY_X = 0x1b, + GRUB_KEYBOARD_KEY_Y = 0x1c, + GRUB_KEYBOARD_KEY_Z = 0x1d, + GRUB_KEYBOARD_KEY_1 = 0x1e, + GRUB_KEYBOARD_KEY_2 = 0x1f, + GRUB_KEYBOARD_KEY_3 = 0x20, + GRUB_KEYBOARD_KEY_4 = 0x21, + GRUB_KEYBOARD_KEY_5 = 0x22, + GRUB_KEYBOARD_KEY_6 = 0x23, + GRUB_KEYBOARD_KEY_7 = 0x24, + GRUB_KEYBOARD_KEY_8 = 0x25, + GRUB_KEYBOARD_KEY_9 = 0x26, + GRUB_KEYBOARD_KEY_0 = 0x27, + GRUB_KEYBOARD_KEY_ENTER = 0x28, + GRUB_KEYBOARD_KEY_ESCAPE = 0x29, + GRUB_KEYBOARD_KEY_BACKSPACE = 0x2a, + GRUB_KEYBOARD_KEY_TAB = 0x2b, + GRUB_KEYBOARD_KEY_SPACE = 0x2c, + GRUB_KEYBOARD_KEY_DASH = 0x2d, + GRUB_KEYBOARD_KEY_EQUAL = 0x2e, + GRUB_KEYBOARD_KEY_LBRACKET = 0x2f, + GRUB_KEYBOARD_KEY_RBRACKET = 0x30, + GRUB_KEYBOARD_KEY_BACKSLASH = 0x32, + GRUB_KEYBOARD_KEY_SEMICOLON = 0x33, + GRUB_KEYBOARD_KEY_DQUOTE = 0x34, + GRUB_KEYBOARD_KEY_RQUOTE = 0x35, + GRUB_KEYBOARD_KEY_COMMA = 0x36, + GRUB_KEYBOARD_KEY_DOT = 0x37, + GRUB_KEYBOARD_KEY_SLASH = 0x38, + GRUB_KEYBOARD_KEY_CAPS_LOCK = 0x39, + GRUB_KEYBOARD_KEY_F1 = 0x3a, + GRUB_KEYBOARD_KEY_F2 = 0x3b, + GRUB_KEYBOARD_KEY_F3 = 0x3c, + GRUB_KEYBOARD_KEY_F4 = 0x3d, + GRUB_KEYBOARD_KEY_F5 = 0x3e, + GRUB_KEYBOARD_KEY_F6 = 0x3f, + GRUB_KEYBOARD_KEY_F7 = 0x40, + GRUB_KEYBOARD_KEY_F8 = 0x41, + GRUB_KEYBOARD_KEY_F9 = 0x42, + GRUB_KEYBOARD_KEY_F10 = 0x43, + GRUB_KEYBOARD_KEY_F11 = 0x44, + GRUB_KEYBOARD_KEY_F12 = 0x45, + GRUB_KEYBOARD_KEY_SCROLL_LOCK = 0x47, + GRUB_KEYBOARD_KEY_INSERT = 0x49, + GRUB_KEYBOARD_KEY_HOME = 0x4a, + GRUB_KEYBOARD_KEY_PPAGE = 0x4b, + GRUB_KEYBOARD_KEY_DELETE = 0x4c, + GRUB_KEYBOARD_KEY_END = 0x4d, + GRUB_KEYBOARD_KEY_NPAGE = 0x4e, + GRUB_KEYBOARD_KEY_RIGHT = 0x4f, + GRUB_KEYBOARD_KEY_LEFT = 0x50, + GRUB_KEYBOARD_KEY_DOWN = 0x51, + GRUB_KEYBOARD_KEY_UP = 0x52, + GRUB_KEYBOARD_KEY_NUM_LOCK = 0x53, + GRUB_KEYBOARD_KEY_NUMSLASH = 0x54, + GRUB_KEYBOARD_KEY_NUMMUL = 0x55, + GRUB_KEYBOARD_KEY_NUMMINUS = 0x56, + GRUB_KEYBOARD_KEY_NUMPLUS = 0x57, + GRUB_KEYBOARD_KEY_NUMENTER = 0x58, + GRUB_KEYBOARD_KEY_NUM1 = 0x59, + GRUB_KEYBOARD_KEY_NUM2 = 0x5a, + GRUB_KEYBOARD_KEY_NUM3 = 0x5b, + GRUB_KEYBOARD_KEY_NUM4 = 0x5c, + GRUB_KEYBOARD_KEY_NUM5 = 0x5d, + GRUB_KEYBOARD_KEY_NUM6 = 0x5e, + GRUB_KEYBOARD_KEY_NUM7 = 0x5f, + GRUB_KEYBOARD_KEY_NUM8 = 0x60, + GRUB_KEYBOARD_KEY_NUM9 = 0x61, + GRUB_KEYBOARD_KEY_NUM0 = 0x62, + GRUB_KEYBOARD_KEY_NUMDOT = 0x63, + GRUB_KEYBOARD_KEY_102ND = 0x64, + GRUB_KEYBOARD_KEY_LEFT_CTRL = 0xe0, + GRUB_KEYBOARD_KEY_LEFT_SHIFT = 0xe1, + GRUB_KEYBOARD_KEY_LEFT_ALT = 0xe2, + GRUB_KEYBOARD_KEY_RIGHT_CTRL = 0xe4, + GRUB_KEYBOARD_KEY_RIGHT_SHIFT = 0xe5, + GRUB_KEYBOARD_KEY_RIGHT_ALT = 0xe6, + } grub_keyboard_key_t; + +unsigned EXPORT_FUNC(grub_term_map_key) (grub_keyboard_key_t code, int status); + +#endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/include/grub/lib/crc.h b/include/grub/legacy_parse.h similarity index 75% rename from include/grub/lib/crc.h rename to include/grub/legacy_parse.h index ff7284dc8..a5e67a071 100644 --- a/include/grub/lib/crc.h +++ b/include/grub/legacy_parse.h @@ -1,4 +1,3 @@ -/* crc.h - prototypes for crc */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. @@ -17,9 +16,12 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_CRC_H -#define GRUB_CRC_H 1 +#ifndef GRUB_LEGACY_PARSE_HEADER +#define GRUB_LEGACY_PARSE_HEADER 1 -grub_uint32_t grub_getcrc32 (grub_uint32_t crc, void *buf, int size); +#include -#endif /* ! GRUB_CRC_H */ +char *grub_legacy_parse (const char *buf, char **entryname, char **suffix); +char *grub_legacy_escape (const char *in, grub_size_t len); + +#endif diff --git a/include/grub/lib/arg.h b/include/grub/lib/arg.h index e6af60cf9..b61f6f30e 100644 --- a/include/grub/lib/arg.h +++ b/include/grub/lib/arg.h @@ -38,6 +38,8 @@ typedef enum grub_arg_type grub_arg_type_t; /* Flags for the option field op grub_arg_option. */ #define GRUB_ARG_OPTION_OPTIONAL (1 << 1) +/* Flags for an option that can appear multiple times. */ +#define GRUB_ARG_OPTION_REPEATABLE (1 << 2) enum grub_key_type { @@ -59,7 +61,10 @@ struct grub_arg_option struct grub_arg_list { int set; - char *arg; + union { + char *arg; + char **args; + }; }; struct grub_extcmd; @@ -67,6 +72,8 @@ struct grub_extcmd; int grub_arg_parse (struct grub_extcmd *cmd, int argc, char **argv, struct grub_arg_list *usr, char ***args, int *argnum); -void grub_arg_show_help (struct grub_extcmd *cmd); +void EXPORT_FUNC(grub_arg_show_help) (struct grub_extcmd *cmd); +struct grub_arg_list* grub_arg_list_alloc (struct grub_extcmd *cmd, + int argc, char *argv[]); #endif /* ! GRUB_ARG_HEADER */ diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index d0adae8c1..8c4c19d8c 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -16,7 +16,8 @@ * along with GRUB. If not, see . */ -#include +/* We need to include config-util.h.in for HAVE_*. */ +#include /* On x86 these functions aren't really needed. Save some space. */ #if !defined (__i386__) && !defined (__x86_64__) diff --git a/include/grub/loader.h b/include/grub/loader.h index 319f3c551..c71e8dd10 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -26,16 +26,16 @@ #include /* Check if a loader is loaded. */ -int grub_loader_is_loaded (void); +int EXPORT_FUNC (grub_loader_is_loaded) (void); /* Set loader functions. NORETURN must be set to true, if BOOT won't return to the original state. */ -void grub_loader_set (grub_err_t (*boot) (void), - grub_err_t (*unload) (void), - int noreturn); +void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), + grub_err_t (*unload) (void), + int noreturn); /* Unset current loader, if any. */ -void grub_loader_unset (void); +void EXPORT_FUNC (grub_loader_unset) (void); /* Call the boot hook in current loader. This may or may not return, depending on the setting by grub_loader_set. */ @@ -56,7 +56,7 @@ typedef enum { } grub_loader_preboot_hook_prio_t; /* Register a preboot hook. */ -void *grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noret), +void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), grub_err_t (*preboot_rest_func) (void), grub_loader_preboot_hook_prio_t prio); diff --git a/include/grub/memory.h b/include/grub/memory.h index 43f90e1dd..d98386565 100644 --- a/include/grub/memory.h +++ b/include/grub/memory.h @@ -22,11 +22,32 @@ #include #include -#include -grub_err_t grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)); +typedef enum grub_memory_type + { + GRUB_MEMORY_AVAILABLE = 1, + GRUB_MEMORY_RESERVED = 2, + GRUB_MEMORY_ACPI = 3, + GRUB_MEMORY_NVS = 4, + GRUB_MEMORY_BADRAM = 5, + GRUB_MEMORY_CODE = 20, + /* This one is special: it's used internally but is never reported + by firmware. */ + GRUB_MEMORY_HOLE = 21 + } grub_memory_type_t; + +typedef int NESTED_FUNC_ATTR (*grub_memory_hook_t) (grub_uint64_t, + grub_uint64_t, + grub_memory_type_t); + +grub_err_t grub_mmap_iterate (grub_memory_hook_t hook); + +#if !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_EFI) +grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) (grub_memory_hook_t hook); +#else +grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook); +#endif + int grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type); grub_err_t grub_mmap_unregister (int handle); @@ -42,7 +63,7 @@ struct grub_mmap_region struct grub_mmap_region *next; grub_uint64_t start; grub_uint64_t end; - int type; + grub_memory_type_t type; int handle; }; diff --git a/include/grub/menu.h b/include/grub/menu.h index e5e5fb110..5ff356beb 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -47,8 +47,14 @@ struct grub_menu_entry /* The sourcecode of the menu entry, used by the editor. */ const char *sourcecode; + /* Parameters to be passed to menu definition. */ + int argc; + char **args; + int hotkey; + int submenu; + /* The next element. */ struct grub_menu_entry *next; }; @@ -96,4 +102,7 @@ void grub_menu_execute_with_fallback (grub_menu_t menu, void grub_menu_entry_run (grub_menu_entry_t entry); int grub_menu_get_default_entry_index (grub_menu_t menu); +void grub_menu_init (void); +void grub_menu_fini (void); + #endif /* GRUB_MENU_HEADER */ diff --git a/include/grub/mips/memory.h b/include/grub/mips/memory.h new file mode 100644 index 000000000..e51bcc1f2 --- /dev/null +++ b/include/grub/mips/memory.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/mips/multiboot.h b/include/grub/mips/multiboot.h index a27229efe..4aebf29e7 100644 --- a/include/grub/mips/multiboot.h +++ b/include/grub/mips/multiboot.h @@ -19,11 +19,6 @@ #ifndef GRUB_MULTIBOOT_CPU_HEADER #define GRUB_MULTIBOOT_CPU_HEADER 1 -extern grub_uint32_t grub_multiboot_payload_eip; -extern char *grub_multiboot_payload_orig; -extern grub_addr_t grub_multiboot_payload_dest; -extern grub_size_t grub_multiboot_payload_size; - #define MULTIBOOT_INITIAL_STATE { .gpr[4] = MULTIBOOT_BOOTLOADER_MAGIC, \ .jumpreg = 1 } #define MULTIBOOT_ENTRY_REGISTER gpr[1] diff --git a/include/grub/mips/qemu-mips/memory.h b/include/grub/mips/qemu-mips/memory.h index 87e68674e..99d9ef2be 100644 --- a/include/grub/mips/qemu-mips/memory.h +++ b/include/grub/mips/qemu-mips/memory.h @@ -28,8 +28,6 @@ #define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000 #define GRUB_MACHINE_MEMORY_USABLE 0x81000000 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - #ifndef ASM_FILE grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/mips/relocator.h b/include/grub/mips/relocator.h index 838ef832f..67b0a4c43 100644 --- a/include/grub/mips/relocator.h +++ b/include/grub/mips/relocator.h @@ -21,6 +21,7 @@ #include #include +#include struct grub_relocator32_state { @@ -30,10 +31,8 @@ struct grub_relocator32_state int jumpreg; }; -void *grub_relocator32_alloc (grub_size_t size); -grub_err_t grub_relocator32_boot (void *relocator, grub_uint32_t dest, - struct grub_relocator32_state state); -void *grub_relocator32_realloc (void *relocator, grub_size_t size); -void grub_relocator32_free (void *relocator); +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state); #endif /* ! GRUB_RELOCATOR_CPU_HEADER */ diff --git a/include/grub/mips/time.h b/include/grub/mips/time.h index e69de29bb..b143a48e0 100644 --- a/include/grub/mips/time.h +++ b/include/grub/mips/time.h @@ -0,0 +1,6 @@ +#ifdef GRUB_MACHINE_EMU +static inline void +grub_cpu_idle(void) +{ +} +#endif diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/yeeloong/kernel.h index c08405e83..15cf9f9fd 100644 --- a/include/grub/mips/yeeloong/kernel.h +++ b/include/grub/mips/yeeloong/kernel.h @@ -23,8 +23,8 @@ #ifndef ASM_FILE -void EXPORT_FUNC (grub_reboot) (void); -void EXPORT_FUNC (grub_halt) (void); +void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn)); +void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); #endif diff --git a/include/grub/mips/yeeloong/loader.h b/include/grub/mips/yeeloong/loader.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h index 922db2404..9d53b5e0e 100644 --- a/include/grub/mips/yeeloong/memory.h +++ b/include/grub/mips/yeeloong/memory.h @@ -31,15 +31,28 @@ #define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 #define GRUB_ARCH_HIGHMEMPSTART 0x10000000 - -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 1 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 2 -#define GRUB_MACHINE_MEMORY_RESERVED GRUB_MACHINE_MEMORY_HOLE - #ifndef ASM_FILE + +typedef grub_addr_t grub_phys_addr_t; + +static inline grub_phys_addr_t +grub_vtop (void *a) +{ + return ((grub_phys_addr_t) a) & 0x1fffffff; +} + +static inline void * +grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) +{ + return (void *) (a | 0x80000000); +} + +static inline void +grub_unmap_memory (void *a __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} + grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/misc.h b/include/grub/misc.h index eab01b0fb..27f15e44a 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -43,6 +43,8 @@ #define ALIGN_UP(addr, align) \ ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1)) +#define ALIGN_DOWN(addr, align) \ + ((addr) & ~((typeof (addr)) align - 1)) #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } @@ -268,11 +270,11 @@ void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r); -#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL) +#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) void EXPORT_FUNC(__enable_execute_stack) (void *addr); #endif -#if defined (NEED_REGISTER_FRAME_INFO) && !defined(GRUB_UTIL) +#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL) void EXPORT_FUNC (__register_frame_info) (void); void EXPORT_FUNC (__deregister_frame_info) (void); #endif @@ -288,6 +290,15 @@ grub_abs (int x) return (unsigned int) x; } +static inline long +grub_min (long x, long y) +{ + if (x < y) + return x; + else + return y; +} + static inline long grub_max (long x, long y) { @@ -310,9 +321,16 @@ void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn)); #ifdef GRUB_MACHINE_PCBIOS /* Halt the system, using APM if possible. If NO_APM is true, don't * use APM even if it is available. */ -void EXPORT_FUNC (grub_halt) (int no_apm) __attribute__ ((noreturn)); +void grub_halt (int no_apm) __attribute__ ((noreturn)); #else -void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); +void grub_halt (void) __attribute__ ((noreturn)); +#endif + +#ifdef GRUB_MACHINE_EMU +/* Flag to control module autoloading in normal mode. */ +extern int EXPORT_VAR(grub_no_autoload); +#else +#define grub_no_autoload 0 #endif #endif /* ! GRUB_MISC_HEADER */ diff --git a/include/grub/mm.h b/include/grub/mm.h index 38dd39646..cc115907a 100644 --- a/include/grub/mm.h +++ b/include/grub/mm.h @@ -35,6 +35,9 @@ void EXPORT_FUNC(grub_free) (void *ptr); void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); +void grub_mm_check_real (char *file, int line); +#define GRUB_MM_CHECK grub_mm_check_real (__FILE__, __LINE__); + /* For debugging. */ #if defined(MM_DEBUG) && !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) /* Set this variable to 1 when you want to trace all memory function calls. */ diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h new file mode 100644 index 000000000..c2c4cb151 --- /dev/null +++ b/include/grub/mm_private.h @@ -0,0 +1,64 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#ifndef GRUB_MM_PRIVATE_H +#define GRUB_MM_PRIVATE_H 1 + +#include + +/* Magic words. */ +#define GRUB_MM_FREE_MAGIC 0x2d3c2808 +#define GRUB_MM_ALLOC_MAGIC 0x6db08fa4 + +typedef struct grub_mm_header +{ + struct grub_mm_header *next; + grub_size_t size; + grub_size_t magic; +#if GRUB_CPU_SIZEOF_VOID_P == 4 + char padding[4]; +#elif GRUB_CPU_SIZEOF_VOID_P == 8 + char padding[8]; +#else +# error "unknown word size" +#endif +} +*grub_mm_header_t; + +#if GRUB_CPU_SIZEOF_VOID_P == 4 +# define GRUB_MM_ALIGN_LOG2 4 +#elif GRUB_CPU_SIZEOF_VOID_P == 8 +# define GRUB_MM_ALIGN_LOG2 5 +#endif + +#define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2) + +typedef struct grub_mm_region +{ + struct grub_mm_header *first; + struct grub_mm_region *next; + grub_size_t pre_size; + grub_size_t size; +} +*grub_mm_region_t; + +#ifndef GRUB_MACHINE_EMU +extern grub_mm_region_t EXPORT_VAR (grub_mm_base); +#endif + +#endif diff --git a/include/grub/msdos_partition.h b/include/grub/msdos_partition.h index 650d78493..a6e3fda49 100644 --- a/include/grub/msdos_partition.h +++ b/include/grub/msdos_partition.h @@ -22,6 +22,8 @@ #include #include #include +#include +#include /* The signature. */ #define GRUB_PC_PARTITION_SIGNATURE 0xaa55 @@ -114,4 +116,9 @@ grub_msdos_partition_is_extended (int type) || type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED); } +grub_err_t +grub_partition_msdos_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)); + #endif /* ! GRUB_PC_PARTITION_HEADER */ diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index 63947d1bc..9a0b57359 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -34,28 +34,44 @@ #include #include +extern struct grub_relocator *grub_multiboot_relocator; + void grub_multiboot (int argc, char *argv[]); void grub_module (int argc, char *argv[]); -grub_size_t grub_multiboot_get_mbi_size (void); -grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, - grub_off_t buf_off, grub_size_t bufsize); +void grub_multiboot_set_accepts_video (int val); +grub_err_t grub_multiboot_make_mbi (grub_uint32_t *target); void grub_multiboot_free_mbi (void); grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]); grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, int argc, char *argv[]); void grub_multiboot_set_bootdev (void); +void +grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, + unsigned shndx, void *data); grub_uint32_t grub_get_multiboot_mmap_count (void); grub_err_t grub_multiboot_set_video_mode (void); +/* FIXME: support coreboot as well. */ +#if defined (GRUB_MACHINE_PCBIOS) +#define GRUB_MACHINE_HAS_VBE 1 +#else +#define GRUB_MACHINE_HAS_VBE 0 +#endif + #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU) -#include #define GRUB_MACHINE_HAS_VGA_TEXT 1 #else #define GRUB_MACHINE_HAS_VGA_TEXT 0 #endif +#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) +#define GRUB_MACHINE_HAS_ACPI 1 +#else +#define GRUB_MACHINE_HAS_ACPI 0 +#endif + #define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT 1 #define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER 2 @@ -70,5 +86,7 @@ grub_err_t grub_multiboot_load_elf (grub_file_t file, void *buffer); extern grub_size_t grub_multiboot_pure_size; extern grub_size_t grub_multiboot_alloc_mbi; +extern grub_uint32_t grub_multiboot_payload_eip; + #endif /* ! GRUB_MULTIBOOT_HEADER */ diff --git a/include/grub/normal.h b/include/grub/normal.h index a33e42e61..187567797 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -54,8 +54,6 @@ void grub_normal_execute (const char *config, int nested, int batch); void grub_menu_init_page (int nested, int edit, struct grub_term_output *term); void grub_normal_init_page (struct grub_term_output *term); -grub_err_t grub_normal_add_menu_entry (int argc, const char **args, - const char *sourcecode); char *grub_file_getline (grub_file_t file); void grub_cmdline_run (int nested); @@ -73,7 +71,7 @@ grub_err_t grub_normal_print_device_info (const char *name); /* Defined in `color.c'. */ char *grub_env_write_color_normal (struct grub_env_var *var, const char *val); char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val); -void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); +int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); /* Defined in `menu_text.c'. */ void grub_wait_after_message (void); @@ -112,9 +110,24 @@ void read_terminal_list (const char *prefix); void grub_set_more (int onoff); -int grub_normal_get_char_counter (void); void grub_normal_reset_more (void); void grub_xputs_normal (const char *str); +extern int grub_extractor_level; + +grub_err_t +grub_normal_add_menu_entry (int argc, const char **args, char **classes, + const char *users, const char *hotkey, + const char *prefix, const char *sourcecode, + int submenu); + +grub_err_t +grub_normal_set_password (const char *user, const char *password); + +void grub_normal_free_menu (grub_menu_t menu); + +void grub_normal_auth_init (void); +void grub_normal_auth_fini (void); + #endif /* ! GRUB_NORMAL_HEADER */ diff --git a/include/grub/ns8250.h b/include/grub/ns8250.h new file mode 100644 index 000000000..7947ba9c9 --- /dev/null +++ b/include/grub/ns8250.h @@ -0,0 +1,80 @@ +/* serial.h - serial device interface */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2005,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 . + */ + +#ifndef GRUB_NS8250_HEADER +#define GRUB_NS8250_HEADER 1 + +/* Macros. */ + +/* The offsets of UART registers. */ +#define UART_TX 0 +#define UART_RX 0 +#define UART_DLL 0 +#define UART_IER 1 +#define UART_DLH 1 +#define UART_IIR 2 +#define UART_FCR 2 +#define UART_LCR 3 +#define UART_MCR 4 +#define UART_LSR 5 +#define UART_MSR 6 +#define UART_SR 7 + +/* For LSR bits. */ +#define UART_DATA_READY 0x01 +#define UART_EMPTY_TRANSMITTER 0x20 + +/* The type of parity. */ +#define UART_NO_PARITY 0x00 +#define UART_ODD_PARITY 0x08 +#define UART_EVEN_PARITY 0x18 + +/* The type of word length. */ +#define UART_5BITS_WORD 0x00 +#define UART_6BITS_WORD 0x01 +#define UART_7BITS_WORD 0x02 +#define UART_8BITS_WORD 0x03 + +/* The type of the length of stop bit. */ +#define UART_1_STOP_BIT 0x00 +#define UART_2_STOP_BITS 0x04 + +/* the switch of DLAB. */ +#define UART_DLAB 0x80 + +/* Enable the FIFO. */ +#define UART_ENABLE_FIFO_TRIGGER14 0xC7 + +/* Enable the FIFO. */ +#define UART_ENABLE_FIFO_TRIGGER1 0x07 + +/* Turn on DTR, RTS, and OUT2. */ +#define UART_ENABLE_DTRRTS 0x03 + +/* Turn on DTR, RTS, and OUT2. */ +#define UART_ENABLE_OUT2 0x08 + +#ifndef ASM_FILE +#include + +grub_port_t +grub_ns8250_hw_get_port (const unsigned int unit); +#endif + +#endif /* ! GRUB_SERIAL_MACHINE_HEADER */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index ae0b2557e..b096abf37 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -34,14 +34,19 @@ /* The offset of GRUB_INSTALL_BSD_PART. */ #define GRUB_KERNEL_I386_PC_INSTALL_BSD_PART 0x18 -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_I386_PC_PREFIX 0x1c - -/* End of the data section. */ -#define GRUB_KERNEL_I386_PC_DATA_END 0x5c +/* Offset of reed_solomon_redundancy. */ +#define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x1c /* The size of the first region which won't be compressed. */ -#define GRUB_KERNEL_I386_PC_RAW_SIZE (GRUB_KERNEL_I386_PC_DATA_END + 0x5F0) +#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xc90 + +#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6f8 + +/* The offset of GRUB_PREFIX. */ +#define GRUB_KERNEL_I386_PC_PREFIX GRUB_KERNEL_I386_PC_RAW_SIZE + +/* End of the data section. */ +#define GRUB_KERNEL_I386_PC_PREFIX_END (GRUB_KERNEL_I386_PC_PREFIX + 0x40) /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 @@ -65,7 +70,7 @@ #define GRUB_KERNEL_I386_QEMU_PREFIX 0x10 /* End of the data section. */ -#define GRUB_KERNEL_I386_QEMU_DATA_END 0x50 +#define GRUB_KERNEL_I386_QEMU_PREFIX_END 0x50 #define GRUB_KERNEL_I386_QEMU_LINK_ADDR 0x8200 @@ -82,7 +87,7 @@ #define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX 0x14 /* End of the data section. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_DATA_END 0x114 +#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END 0x114 #define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12 @@ -91,7 +96,7 @@ #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 #define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX 0x4 -#define GRUB_KERNEL_POWERPC_IEEE1275_DATA_END 0x44 +#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END 0x44 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 @@ -99,36 +104,39 @@ #define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE 0x200 -#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0xc -#define GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE 0x10 +#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8 +#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE -#define GRUB_KERNEL_MIPS_YEELOONG_DATA_END GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE + 0x48 +#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08 +#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c +#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54 /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_I386_EFI_PREFIX 0x8 /* End of the data section. */ -#define GRUB_KERNEL_I386_EFI_DATA_END 0x50 +#define GRUB_KERNEL_I386_EFI_PREFIX_END 0x50 /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_X86_64_EFI_PREFIX 0x8 /* End of the data section. */ -#define GRUB_KERNEL_X86_64_EFI_DATA_END 0x50 +#define GRUB_KERNEL_X86_64_EFI_PREFIX_END 0x50 #define GRUB_KERNEL_I386_COREBOOT_PREFIX 0x2 -#define GRUB_KERNEL_I386_COREBOOT_DATA_END 0x42 +#define GRUB_KERNEL_I386_COREBOOT_PREFIX_END 0x42 #define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR 0x8200 +#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX GRUB_KERNEL_I386_COREBOOT_PREFIX +#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END GRUB_KERNEL_I386_COREBOOT_PREFIX_END + #define GRUB_KERNEL_I386_IEEE1275_PREFIX 0x2 -#define GRUB_KERNEL_I386_IEEE1275_DATA_END 0x42 +#define GRUB_KERNEL_I386_IEEE1275_PREFIX_END 0x42 #define GRUB_KERNEL_I386_IEEE1275_LINK_ADDR 0x10000 #define GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN 0x1000 #define GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN 0x1 +#define GRUB_KERNEL_I386_MULTIBOOT_MOD_ALIGN GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN /* Non-zero value is only needed for PowerMacs. */ #define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0 @@ -143,22 +151,23 @@ rewrite grub-mkimage to generate valid ELF files. */ #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000 -#ifdef MACHINE +#ifdef GRUB_MACHINE #define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c #define GRUB_OFFSETS_CONCAT(a,b,c) GRUB_OFFSETS_CONCAT_(a,b,c) -#define GRUB_KERNEL_MACHINE_MOD_ALIGN GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _MOD_ALIGN) -#define GRUB_KERNEL_MACHINE_MOD_GAP GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _MOD_GAP) -#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _TOTAL_MODULE_SIZE) -#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _KERNEL_IMAGE_SIZE) -#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _COMPRESSED_SIZE) +#define GRUB_KERNEL_MACHINE_MOD_ALIGN GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _MOD_ALIGN) +#define GRUB_KERNEL_MACHINE_MOD_GAP GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _MOD_GAP) +#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _TOTAL_MODULE_SIZE) +#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _KERNEL_IMAGE_SIZE) +#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _COMPRESSED_SIZE) +#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) -#define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _PREFIX) -#define GRUB_KERNEL_MACHINE_DATA_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _DATA_END) -#define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, MACHINE, _KERNEL_SEG) -#define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, MACHINE, _UPPER) -#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _RAW_SIZE) -#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _INSTALL_BSD_PART) -#define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _INSTALL_DOS_PART) +#define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX) +#define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX_END) +#define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG) +#define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER) +#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _RAW_SIZE) +#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_BSD_PART) +#define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_DOS_PART) #endif #ifndef ASM_FILE diff --git a/include/grub/partition.h b/include/grub/partition.h index 20705c527..e7e00ef7f 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -26,6 +26,13 @@ struct grub_disk; typedef struct grub_partition *grub_partition_t; +#ifdef GRUB_UTIL +typedef enum +{ + GRUB_EMBED_PCBIOS +} grub_embed_type_t; +#endif + /* Partition map type. */ struct grub_partition_map { @@ -39,6 +46,12 @@ struct grub_partition_map grub_err_t (*iterate) (struct grub_disk *disk, int (*hook) (struct grub_disk *disk, const grub_partition_t partition)); +#ifdef GRUB_UTIL + /* Determine sectors available for embedding. */ + grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors); +#endif }; typedef struct grub_partition_map *grub_partition_map_t; @@ -65,6 +78,10 @@ struct grub_partition /* The type partition map. */ grub_partition_map_t partmap; + + /* The type of partition whne it's on MSDOS. + Used for embedding detection. */ + grub_uint8_t msdostype; }; grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk, diff --git a/include/grub/pci.h b/include/grub/pci.h index e6d6488f0..f34e3d907 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -80,6 +80,7 @@ #define GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9 #define GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600 +#define GRUB_PCI_CLASS_SUBCLASS_VGA 0x0300 #ifndef ASM_FILE typedef grub_uint32_t grub_pci_id_t; diff --git a/include/grub/powerpc/ieee1275/loader.h b/include/grub/powerpc/ieee1275/loader.h deleted file mode 100644 index 606bfcd0b..000000000 --- a/include/grub/powerpc/ieee1275/loader.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004,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 . - */ - -#ifndef GRUB_LOADER_MACHINE_HEADER -#define GRUB_LOADER_MACHINE_HEADER 1 - -/* The symbol shared between the normal mode and rescue mode - loader. */ -void grub_rescue_cmd_linux (int argc, char *argv[]); -void grub_rescue_cmd_initrd (int argc, char *argv[]); - -void grub_linux_init (void); -void grub_linux_fini (void); -void grub_linux_normal_init (void); -void grub_linux_normal_fini (void); - -#endif /* ! GRUB_LOADER_MACHINE_HEADER */ diff --git a/include/grub/powerpc/memory.h b/include/grub/powerpc/memory.h new file mode 100644 index 000000000..b748f33c5 --- /dev/null +++ b/include/grub/powerpc/memory.h @@ -0,0 +1,47 @@ +/* memory.h - describe the memory map */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,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 + * 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_MEMORY_CPU_HEADER +#define GRUB_MEMORY_CPU_HEADER 1 + +#ifndef ASM_FILE + +typedef grub_addr_t grub_phys_addr_t; + +static inline grub_phys_addr_t +grub_vtop (void *a) +{ + return (grub_phys_addr_t) a; +} + +static inline void * +grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) +{ + return (void *) a; +} + +static inline void +grub_unmap_memory (void *a __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} + +#endif + +#endif /* ! GRUB_MEMORY_CPU_HEADER */ diff --git a/include/grub/i386/ieee1275/loader.h b/include/grub/powerpc/relocator.h similarity index 62% rename from include/grub/i386/ieee1275/loader.h rename to include/grub/powerpc/relocator.h index 20df2e1d6..c2780bbca 100644 --- a/include/grub/i386/ieee1275/loader.h +++ b/include/grub/powerpc/relocator.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -16,14 +16,22 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_LOADER_MACHINE_HEADER -#define GRUB_LOADER_MACHINE_HEADER 1 +#ifndef GRUB_RELOCATOR_CPU_HEADER +#define GRUB_RELOCATOR_CPU_HEADER 1 #include -#include -#include +#include +#include -void grub_rescue_cmd_linux (int argc, char *argv[]); -void grub_rescue_cmd_initrd (int argc, char *argv[]); +#define GRUB_PPC_JUMP_REGISTER 31 -#endif /* ! GRUB_LOADER_MACHINE_HEADER */ +struct grub_relocator32_state +{ + grub_uint32_t gpr[32]; +}; + +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state); + +#endif /* ! GRUB_RELOCATOR_CPU_HEADER */ diff --git a/include/grub/raid.h b/include/grub/raid.h index 711a7f79c..d5853639d 100644 --- a/include/grub/raid.h +++ b/include/grub/raid.h @@ -22,8 +22,6 @@ #include -#define GRUB_RAID_MAX_DEVICES 32 - #define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC 0 #define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC 1 #define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC 2 @@ -32,6 +30,13 @@ #define GRUB_RAID_LAYOUT_RIGHT_MASK 1 #define GRUB_RAID_LAYOUT_SYMMETRIC_MASK 2 +struct grub_raid_member +{ + grub_disk_t device; /* Array of total_devs devices. */ + grub_disk_addr_t start_sector; + /* Start of each device, in 512 byte sectors. */ +}; + struct grub_raid_array { int number; /* The device number, taken from md_minor so we @@ -43,17 +48,20 @@ struct grub_raid_array grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */ grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte sectors. */ - int index; /* Index of current device. */ + unsigned int index; /* Index of current device. */ int uuid_len; /* The length of uuid. */ char *uuid; /* The UUID of the device. */ /* The following field is setup by the caller. */ char *name; /* That will be "md". */ unsigned int nr_devs; /* The number of devices we've found so far. */ - grub_disk_t device[GRUB_RAID_MAX_DEVICES]; /* Array of total_devs devices. */ - grub_disk_addr_t start_sector[GRUB_RAID_MAX_DEVICES]; - /* Start of each device, in 512 byte sectors. */ + unsigned int allocated_devs; + struct grub_raid_member *members; struct grub_raid_array *next; + +#ifdef GRUB_UTIL + struct grub_raid *driver; +#endif }; struct grub_raid diff --git a/include/grub/sparc64/ieee1275/memory.h b/include/grub/reed_solomon.h similarity index 67% rename from include/grub/sparc64/ieee1275/memory.h rename to include/grub/reed_solomon.h index 25e31002e..596dff246 100644 --- a/include/grub/sparc64/ieee1275/memory.h +++ b/include/grub/reed_solomon.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 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 @@ -16,11 +16,15 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MEMORY_MACHINE_HEADER -#define GRUB_MEMORY_MACHINE_HEADER 1 +#ifndef GRUB_REED_SOLOMON_HEADER +#define GRUB_REED_SOLOMON_HEADER 1 -#include +void +grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, + grub_size_t redundancy); -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +void +grub_reed_solomon_recover (void *buffer, grub_size_t data_size, + grub_size_t redundancy); #endif diff --git a/include/grub/relocator.h b/include/grub/relocator.h new file mode 100644 index 000000000..653a00eba --- /dev/null +++ b/include/grub/relocator.h @@ -0,0 +1,58 @@ +/* + * 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 . + */ + +#ifndef GRUB_RELOCATOR_HEADER +#define GRUB_RELOCATOR_HEADER 1 + +#include +#include +#include +#include + +struct grub_relocator; +struct grub_relocator_chunk; +typedef const struct grub_relocator_chunk *grub_relocator_chunk_t; + +struct grub_relocator *grub_relocator_new (void); + +grub_err_t +grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t target, grub_size_t size); + +void * +get_virtual_current_address (grub_relocator_chunk_t in); +grub_phys_addr_t +get_physical_target_address (grub_relocator_chunk_t in); + +grub_err_t +grub_relocator_alloc_chunk_align (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t min_addr, + grub_phys_addr_t max_addr, + grub_size_t size, grub_size_t align, + int preference); + +#define GRUB_RELOCATOR_PREFERENCE_NONE 0 +#define GRUB_RELOCATOR_PREFERENCE_LOW 1 +#define GRUB_RELOCATOR_PREFERENCE_HIGH 2 + +void +grub_relocator_unload (struct grub_relocator *rel); + +#endif diff --git a/include/grub/relocator_private.h b/include/grub/relocator_private.h new file mode 100644 index 000000000..1c563cb64 --- /dev/null +++ b/include/grub/relocator_private.h @@ -0,0 +1,113 @@ +/* + * 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 . + */ + +#ifndef GRUB_RELOCATOR_PRIVATE_HEADER +#define GRUB_RELOCATOR_PRIVATE_HEADER 1 + +#include +#include +#include + +extern grub_size_t grub_relocator_align; +extern grub_size_t grub_relocator_forward_size; +extern grub_size_t grub_relocator_backward_size; +extern grub_size_t grub_relocator_jumper_size; + +void +grub_cpu_relocator_init (void); +grub_err_t +grub_relocator_prepare_relocs (struct grub_relocator *rel, + grub_addr_t addr, + void **relstart, grub_size_t *relsize); +void grub_cpu_relocator_forward (void *rels, void *src, void *tgt, + grub_size_t size); +void grub_cpu_relocator_backward (void *rels, void *src, void *tgt, + grub_size_t size); +void grub_cpu_relocator_jumper (void *rels, grub_addr_t addr); + +/* Remark: GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG = 1 or 2 + aren't supported. */ +#ifdef GRUB_MACHINE_IEEE1275 +#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 1 +#define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG 0 +#elif defined (GRUB_MACHINE_EFI) +#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 1 +#define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG 12 +#else +#define GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS 0 +#endif + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS && GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG != 0 +#define GRUB_RELOCATOR_HAVE_LEFTOVERS 1 +#else +#define GRUB_RELOCATOR_HAVE_LEFTOVERS 0 +#endif + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS +#define GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT (1 << GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT_LOG) +#endif + +struct grub_relocator_mmap_event +{ + enum { + IN_REG_START = 0, + IN_REG_END = 1, + REG_BEG_START = 2, + REG_BEG_END = REG_BEG_START | 1, +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + REG_FIRMWARE_START = 4, + REG_FIRMWARE_END = REG_FIRMWARE_START | 1, + /* To track the regions already in heap. */ + FIRMWARE_BLOCK_START = 6, + FIRMWARE_BLOCK_END = FIRMWARE_BLOCK_START | 1, +#endif +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + REG_LEFTOVER_START = 8, + REG_LEFTOVER_END = REG_LEFTOVER_START | 1, +#endif + COLLISION_START = 10, + COLLISION_END = COLLISION_START | 1 + } type; + grub_phys_addr_t pos; + union + { + struct + { + grub_mm_region_t reg; + grub_mm_header_t hancestor; + grub_mm_region_t *regancestor; + grub_mm_header_t head; + }; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + struct grub_relocator_fw_leftover *leftover; +#endif + }; +}; + +/* Return 0 on failure, 1 on success. The failure here + can be very time-expensive, so please make sure fill events is accurate. */ +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS +int grub_relocator_firmware_alloc_region (grub_phys_addr_t start, + grub_size_t size); +unsigned grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events); +unsigned grub_relocator_firmware_get_max_events (void); +void grub_relocator_firmware_free_region (grub_phys_addr_t start, + grub_size_t size); +#endif + +#endif diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 7d6129243..6d31fca5a 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -23,6 +23,7 @@ #include #include #include +#include struct grub_script_mem; @@ -39,8 +40,13 @@ struct grub_script_cmd struct grub_script { + unsigned refcnt; struct grub_script_mem *mem; struct grub_script_cmd *cmd; + + /* grub_scripts from block arguments. */ + struct grub_script *next_siblings; + struct grub_script *children; }; typedef enum @@ -49,7 +55,8 @@ typedef enum GRUB_SCRIPT_ARG_TYPE_TEXT, GRUB_SCRIPT_ARG_TYPE_DQVAR, GRUB_SCRIPT_ARG_TYPE_DQSTR, - GRUB_SCRIPT_ARG_TYPE_SQSTR + GRUB_SCRIPT_ARG_TYPE_SQSTR, + GRUB_SCRIPT_ARG_TYPE_BLOCK } grub_script_arg_type_t; /* A part of an argument. */ @@ -59,10 +66,31 @@ struct grub_script_arg char *str; + /* Parsed block argument. */ + struct grub_script *script; + /* Next argument part. */ struct grub_script_arg *next; }; +/* An argument vector. */ +struct grub_script_argv +{ + unsigned argc; + char **args; + struct grub_script *script; +}; + +/* Pluggable wildcard translator. */ +struct grub_script_wildcard_translator +{ + char *(*escape) (const char *str); + char *(*unescape) (const char *str); + grub_err_t (*expand) (const char *str, char ***expansions); +}; +extern struct grub_script_wildcard_translator *grub_wildcard_translator; +extern struct grub_script_wildcard_translator grub_filename_translator; + /* A complete argument. It consists of a list of one or more `struct grub_script_arg's. */ struct grub_script_arglist @@ -82,15 +110,6 @@ struct grub_script_cmdline struct grub_script_arglist *arglist; }; -/* A block of commands, this can be used to group commands. */ -struct grub_script_cmdblock -{ - struct grub_script_cmd cmd; - - /* A chain of commands. */ - struct grub_script_cmd *cmdlist; -}; - /* An if statement. */ struct grub_script_cmdif { @@ -136,21 +155,6 @@ struct grub_script_cmdwhile int until; }; -/* A menu entry generate statement. */ -struct grub_script_cmd_menuentry -{ - struct grub_script_cmd cmd; - - /* The arguments for this menu entry. */ - struct grub_script_arglist *arglist; - - /* The sourcecode the entry will be generated from. */ - const char *sourcecode; - - /* Options. XXX: Not used yet. */ - int options; -}; - /* State of the lexer as passed to the lexer. */ struct grub_lexer_param { @@ -195,6 +199,12 @@ struct grub_lexer_param /* Type of text. */ grub_script_arg_type_t type; + /* Flag to indicate resplit in progres. */ + unsigned resplit; + + /* Text that is unput. */ + char *prefix; + /* Flex scanner. */ void *yyscanner; @@ -218,12 +228,26 @@ struct grub_parser_param /* The memory that was used while parsing and scanning. */ struct grub_script_mem *memused; + /* The block argument scripts. */ + struct grub_script *scripts; + /* The result of the parser. */ struct grub_script_cmd *parsed; struct grub_lexer_param *lexerstate; }; +void grub_script_init (void); +void grub_script_fini (void); + +void grub_script_mem_free (struct grub_script_mem *mem); + +void grub_script_argv_free (struct grub_script_argv *argv); +int grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args); +int grub_script_argv_next (struct grub_script_argv *argv); +int grub_script_argv_append (struct grub_script_argv *argv, const char *s); +int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); + struct grub_script_arglist * grub_script_create_arglist (struct grub_parser_param *state); @@ -234,8 +258,6 @@ grub_script_add_arglist (struct grub_parser_param *state, struct grub_script_cmd * grub_script_create_cmdline (struct grub_parser_param *state, struct grub_script_arglist *arglist); -struct grub_script_cmd * -grub_script_create_cmdblock (struct grub_parser_param *state); struct grub_script_cmd * grub_script_create_cmdif (struct grub_parser_param *state, @@ -256,15 +278,9 @@ grub_script_create_cmdwhile (struct grub_parser_param *state, int is_an_until_loop); struct grub_script_cmd * -grub_script_create_cmdmenu (struct grub_parser_param *state, - struct grub_script_arglist *arglist, - char *sourcecode, - int options); - -struct grub_script_cmd * -grub_script_add_cmd (struct grub_parser_param *state, - struct grub_script_cmdblock *cmdblock, - struct grub_script_cmd *cmd); +grub_script_append_cmd (struct grub_parser_param *state, + struct grub_script_cmd *list, + struct grub_script_cmd *last); struct grub_script_arg * grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *arg, @@ -282,9 +298,9 @@ struct grub_lexer_param *grub_script_lexer_init (struct grub_parser_param *parse void grub_script_lexer_fini (struct grub_lexer_param *); void grub_script_lexer_ref (struct grub_lexer_param *); void grub_script_lexer_deref (struct grub_lexer_param *); -void grub_script_lexer_record_start (struct grub_parser_param *); -char *grub_script_lexer_record_stop (struct grub_parser_param *); -int grub_script_lexer_yywrap (struct grub_parser_param *); +unsigned grub_script_lexer_record_start (struct grub_parser_param *); +char *grub_script_lexer_record_stop (struct grub_parser_param *, unsigned); +int grub_script_lexer_yywrap (struct grub_parser_param *, const char *input); void grub_script_lexer_record (struct grub_parser_param *, char *); /* Functions to track allocated memory. */ @@ -301,14 +317,26 @@ void grub_script_yyerror (struct grub_parser_param *, char const *); /* Commands to execute, don't use these directly. */ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd); -grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd); +grub_err_t grub_script_execute_cmdlist (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdwhile (struct grub_script_cmd *cmd); -grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd); /* Execute any GRUB pre-parsed command or script. */ grub_err_t grub_script_execute (struct grub_script *script); +grub_err_t grub_script_execute_sourcecode (const char *source, int argc, char **args); + +/* Break command for loops. */ +grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]); + +/* SHIFT command for GRUB script. */ +grub_err_t grub_script_shift (grub_command_t cmd, int argc, char *argv[]); + +/* SETPARAMS command for GRUB script functions. */ +grub_err_t grub_script_setparams (grub_command_t cmd, int argc, char *argv[]); + +/* RETURN command for functions. */ +grub_err_t grub_script_return (grub_command_t cmd, int argc, char *argv[]); /* This variable points to the parsed command. This is used to communicate with the bison code. */ @@ -344,8 +372,9 @@ grub_script_function_t grub_script_function_create (struct grub_script_arg *func struct grub_script *cmd); void grub_script_function_remove (const char *name); grub_script_function_t grub_script_function_find (char *functionname); -int grub_script_function_call (grub_script_function_t func, - int argc, char **args); + +grub_err_t grub_script_function_call (grub_script_function_t func, + int argc, char **args); char ** grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count); @@ -353,4 +382,24 @@ grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *c grub_err_t grub_normal_parse_line (char *line, grub_reader_getline_t getline); +static inline struct grub_script * +grub_script_ref (struct grub_script *script) +{ + if (script) + script->refcnt++; + return script; +} + +static inline void +grub_script_unref (struct grub_script *script) +{ + if (! script) + return; + + if (script->refcnt == 0) + grub_script_free (script); + else + script->refcnt--; +} + #endif /* ! GRUB_NORMAL_PARSER_HEADER */ diff --git a/include/grub/scsi.h b/include/grub/scsi.h index b3c60f3e8..b30d317c7 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -40,7 +40,7 @@ static inline grub_uint32_t grub_make_scsi_id (int subsystem, int bus, int lun) { return (subsystem << GRUB_SCSI_ID_SUBSYSTEM_SHIFT) - | (bus << GRUB_SCSI_ID_BUS_SHIFT) | (lun << GRUB_SCSI_ID_BUS_SHIFT); + | (bus << GRUB_SCSI_ID_BUS_SHIFT) | (lun << GRUB_SCSI_ID_LUN_SHIFT); } struct grub_scsi_dev diff --git a/include/grub/search.h b/include/grub/search.h index e8f9db285..d80347df3 100644 --- a/include/grub/search.h +++ b/include/grub/search.h @@ -19,8 +19,11 @@ #ifndef GRUB_SEARCH_HEADER #define GRUB_SEARCH_HEADER 1 -void grub_search_fs_file (const char *key, const char *var, int no_floppy); -void grub_search_fs_uuid (const char *key, const char *var, int no_floppy); -void grub_search_label (const char *key, const char *var, int no_floppy); +void grub_search_fs_file (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); +void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); +void grub_search_label (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); #endif diff --git a/include/grub/serial.h b/include/grub/serial.h index 758b6fb3e..9540bee64 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -1,7 +1,7 @@ /* serial.h - serial device interface */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2001,2002,2005,2007 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 @@ -20,54 +20,104 @@ #ifndef GRUB_SERIAL_HEADER #define GRUB_SERIAL_HEADER 1 -/* Macros. */ +#include +#include +#include +#include +#include -/* The offsets of UART registers. */ -#define UART_TX 0 -#define UART_RX 0 -#define UART_DLL 0 -#define UART_IER 1 -#define UART_DLH 1 -#define UART_IIR 2 -#define UART_FCR 2 -#define UART_LCR 3 -#define UART_MCR 4 -#define UART_LSR 5 -#define UART_MSR 6 -#define UART_SR 7 +struct grub_serial_port; +struct grub_serial_config; -/* For LSR bits. */ -#define UART_DATA_READY 0x01 -#define UART_EMPTY_TRANSMITTER 0x20 +struct grub_serial_driver +{ + grub_err_t (*configure) (struct grub_serial_port *port, + struct grub_serial_config *config); + int (*fetch) (struct grub_serial_port *port); + void (*put) (struct grub_serial_port *port, const int c); + void (*fini) (struct grub_serial_port *port); +}; /* The type of parity. */ -#define UART_NO_PARITY 0x00 -#define UART_ODD_PARITY 0x08 -#define UART_EVEN_PARITY 0x18 +typedef enum + { + GRUB_SERIAL_PARITY_NONE, + GRUB_SERIAL_PARITY_ODD, + GRUB_SERIAL_PARITY_EVEN, + } grub_serial_parity_t; -/* The type of word length. */ -#define UART_5BITS_WORD 0x00 -#define UART_6BITS_WORD 0x01 -#define UART_7BITS_WORD 0x02 -#define UART_8BITS_WORD 0x03 +typedef enum + { + GRUB_SERIAL_STOP_BITS_1, + GRUB_SERIAL_STOP_BITS_2, + } grub_serial_stop_bits_t; -/* The type of the length of stop bit. */ -#define UART_1_STOP_BIT 0x00 -#define UART_2_STOP_BITS 0x04 +struct grub_serial_config +{ + unsigned speed; + int word_len; + grub_serial_parity_t parity; + grub_serial_stop_bits_t stop_bits; +}; -/* the switch of DLAB. */ -#define UART_DLAB 0x80 +struct grub_serial_port +{ + struct grub_serial_port *next; + char *name; + struct grub_serial_driver *driver; + struct grub_serial_config config; + int configured; + /* This should be void *data but since serial is useful as an early console + when malloc isn't available it's a union. + */ + union + { + struct + { + grub_port_t port; + int broken; + }; + struct + { + grub_usb_device_t usbdev; + int configno; + int interfno; + char buf[64]; + int bufstart, bufend; + struct grub_usb_desc_endp *in_endp; + struct grub_usb_desc_endp *out_endp; + }; + }; + grub_term_output_t term_out; + grub_term_input_t term_in; +}; -/* Enable the FIFO. */ -#define UART_ENABLE_FIFO_TRIGGER14 0xC7 +grub_err_t EXPORT_FUNC(grub_serial_register) (struct grub_serial_port *port); -/* Enable the FIFO. */ -#define UART_ENABLE_FIFO_TRIGGER1 0x07 +void EXPORT_FUNC(grub_serial_unregister) (struct grub_serial_port *port); -/* Turn on DTR, RTS, and OUT2. */ -#define UART_ENABLE_DTRRTS 0x03 + /* Set default settings. */ +static inline grub_err_t +grub_serial_config_defaults (struct grub_serial_port *port) +{ + struct grub_serial_config config = + { +#ifdef GRUB_MACHINE_MIPS_YEELOONG + .speed = 115200, +#else + .speed = 9600, +#endif + .word_len = 8, + .parity = GRUB_SERIAL_PARITY_NONE, + .stop_bits = GRUB_SERIAL_STOP_BITS_1 + }; -/* Turn on DTR, RTS, and OUT2. */ -#define UART_ENABLE_OUT2 0x08 + return port->driver->configure (port, &config); +} -#endif /* ! GRUB_SERIAL_MACHINE_HEADER */ +void grub_ns8250_init (void); +char *grub_serial_ns8250_add_port (grub_port_t port); +extern struct grub_serial_driver grub_ns8250_driver; +void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver); + +#endif diff --git a/include/grub/sparc64/ieee1275/boot.h b/include/grub/sparc64/ieee1275/boot.h index bd0a7bf3c..112d19bc7 100644 --- a/include/grub/sparc64/ieee1275/boot.h +++ b/include/grub/sparc64/ieee1275/boot.h @@ -52,4 +52,13 @@ #define GRUB_BOOT_MACHINE_KERNEL_ADDR 0x4200 +#ifndef ASM_FILE +/* This is the blocklist used in the diskboot image. */ +struct grub_boot_blocklist +{ + grub_uint64_t start; + grub_uint32_t len; +} __attribute__ ((packed)); +#endif + #endif /* ! BOOT_MACHINE_HEADER */ diff --git a/include/grub/symbol.h b/include/grub/symbol.h index 63ed19436..c6adb7ee3 100644 --- a/include/grub/symbol.h +++ b/include/grub/symbol.h @@ -25,7 +25,7 @@ #define LOCAL(sym) L_ ## sym /* Add an underscore to a C symbol in assembler code if needed. */ -#ifdef HAVE_ASM_USCORE +#if HAVE_ASM_USCORE # define EXT_C(sym) _ ## sym #else # define EXT_C(sym) sym diff --git a/include/grub/term.h b/include/grub/term.h index f40d935e4..dbcb2f52c 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -19,19 +19,45 @@ #ifndef GRUB_TERM_HEADER #define GRUB_TERM_HEADER 1 +#define GRUB_TERM_NO_KEY 0 + /* Internal codes used by GRUB to represent terminal input. */ -#define GRUB_TERM_LEFT 2 -#define GRUB_TERM_RIGHT 6 -#define GRUB_TERM_UP 16 -#define GRUB_TERM_DOWN 14 -#define GRUB_TERM_HOME 1 -#define GRUB_TERM_END 5 -#define GRUB_TERM_DC 4 -#define GRUB_TERM_PPAGE 7 -#define GRUB_TERM_NPAGE 3 +/* Only for keys otherwise not having shifted modification. */ +#define GRUB_TERM_SHIFT 0x01000000 +#define GRUB_TERM_CTRL 0x02000000 +#define GRUB_TERM_ALT 0x04000000 + +/* Keys without associated character. */ +#define GRUB_TERM_EXTENDED 0x00800000 +#define GRUB_TERM_KEY_MASK 0x00ffffff + +#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 0x4b) +#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 0x4d) +#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 0x48) +#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 0x50) +#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 0x47) +#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 0x4f) +#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 0x53) +#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 0x49) +#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 0x51) +#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 0x3b) +#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 0x3c) +#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 0x3d) +#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 0x3e) +#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 0x3f) +#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 0x40) +#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 0x41) +#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 0x42) +#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 0x43) +#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 0x44) +#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 0x57) +#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 0x58) +#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 0x52) +#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 0x4c) + #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' -#define GRUB_TERM_BACKSPACE 8 +#define GRUB_TERM_BACKSPACE '\b' #ifndef ASM_FILE @@ -86,9 +112,15 @@ grub_term_color_state; /* Bitmasks for modifier keys returned by grub_getkeystatus. */ -#define GRUB_TERM_STATUS_SHIFT (1 << 0) -#define GRUB_TERM_STATUS_CTRL (1 << 1) -#define GRUB_TERM_STATUS_ALT (1 << 2) +#define GRUB_TERM_STATUS_RSHIFT (1 << 0) +#define GRUB_TERM_STATUS_LSHIFT (1 << 1) +#define GRUB_TERM_STATUS_RCTRL (1 << 2) +#define GRUB_TERM_STATUS_RALT (1 << 3) +#define GRUB_TERM_STATUS_SCROLL (1 << 4) +#define GRUB_TERM_STATUS_NUM (1 << 5) +#define GRUB_TERM_STATUS_CAPS (1 << 6) +#define GRUB_TERM_STATUS_LCTRL (1 << 8) +#define GRUB_TERM_STATUS_LALT (1 << 9) /* Menu-related geometrical constants. */ @@ -128,10 +160,7 @@ struct grub_term_input /* Clean up the terminal. */ grub_err_t (*fini) (struct grub_term_input *term); - /* Check if any input character is available. */ - int (*checkkey) (struct grub_term_input *term); - - /* Get a character. */ + /* Get a character if any input character is available. Otherwise return -1 */ int (*getkey) (struct grub_term_input *term); /* Get keyboard modifier status. */ @@ -279,7 +308,6 @@ grub_term_unregister_output (grub_term_output_t term) void grub_putcode (grub_uint32_t code, struct grub_term_output *term); int EXPORT_FUNC(grub_getkey) (void); int EXPORT_FUNC(grub_checkkey) (void); -int EXPORT_FUNC(grub_getkeystatus) (void); void grub_cls (void); void EXPORT_FUNC(grub_refresh) (void); void grub_puts_terminal (const char *str, struct grub_term_output *term); @@ -459,9 +487,10 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) grub_putcode (' ', term); } +extern void (*EXPORT_VAR (grub_term_poll_usb)) (void); -/* For convenience. */ -#define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff) +#define GRUB_TERM_REPEAT_PRE_INTERVAL 400 +#define GRUB_TERM_REPEAT_INTERVAL 50 #endif /* ! ASM_FILE */ diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h index d6907d7f0..8317995d8 100644 --- a/include/grub/terminfo.h +++ b/include/grub/terminfo.h @@ -32,7 +32,7 @@ struct grub_terminfo_input_state { int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN]; int npending; - int (*readkey) (void); + int (*readkey) (struct grub_term_input *term); }; struct grub_terminfo_output_state @@ -49,9 +49,11 @@ struct grub_terminfo_output_state char *cursor_off; char *setcolor; + unsigned int width, height; + unsigned int xpos, ypos; - void (*put) (const int c); + void (*put) (struct grub_term_output *term, const int c); }; void EXPORT_FUNC(grub_terminfo_gotoxy) (grub_term_output_t term, @@ -64,11 +66,12 @@ void EXPORT_FUNC (grub_terminfo_setcolorstate) (struct grub_term_output *term, const grub_term_color_state state); -int EXPORT_FUNC (grub_terminfo_checkkey) (struct grub_term_input *term); grub_err_t EXPORT_FUNC (grub_terminfo_input_init) (struct grub_term_input *term); int EXPORT_FUNC (grub_terminfo_getkey) (struct grub_term_input *term); void EXPORT_FUNC (grub_terminfo_putchar) (struct grub_term_output *term, const struct grub_unicode_glyph *c); +grub_uint16_t EXPORT_FUNC (grub_terminfo_getwh) (struct grub_term_output *term); + grub_err_t EXPORT_FUNC (grub_terminfo_output_register) (struct grub_term_output *term, const char *type); diff --git a/include/grub/test.h b/include/grub/test.h index 27591cca2..336d3b672 100644 --- a/include/grub/test.h +++ b/include/grub/test.h @@ -72,14 +72,14 @@ void grub_test_nonzero (int cond, const char *file, /* Macro to define a functional test. */ #define GRUB_FUNCTIONAL_TEST(name, funp) \ - GRUB_MOD_INIT(functional_test_##funp) \ + GRUB_MOD_INIT(name) \ { \ - grub_test_register (name, funp); \ + grub_test_register (#name, funp); \ } \ \ - GRUB_MOD_FINI(functional_test_##funp) \ + GRUB_MOD_FINI(name) \ { \ - grub_test_unregister (name); \ + grub_test_unregister (#name); \ } #endif /* ! GRUB_TEST_HEADER */ diff --git a/include/grub/types.h b/include/grub/types.h index 4499e4538..e57666a10 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -69,21 +69,25 @@ typedef long long grub_int64_t; typedef unsigned char grub_uint8_t; typedef unsigned short grub_uint16_t; typedef unsigned grub_uint32_t; +# define PRIxGRUB_UINT32_T "x" +# define PRIuGRUB_UINT32_T "u" #if GRUB_CPU_SIZEOF_LONG == 8 typedef unsigned long grub_uint64_t; +# define PRIxGRUB_UINT64_T "lx" +# define PRIuGRUB_UINT64_T "lu" #else typedef unsigned long long grub_uint64_t; +# define PRIxGRUB_UINT64_T "llx" +# define PRIuGRUB_UINT64_T "llu" #endif /* Misc types. */ #if GRUB_TARGET_SIZEOF_VOID_P == 8 typedef grub_uint64_t grub_target_addr_t; -typedef grub_uint64_t grub_target_off_t; typedef grub_uint64_t grub_target_size_t; typedef grub_int64_t grub_target_ssize_t; #else typedef grub_uint32_t grub_target_addr_t; -typedef grub_uint32_t grub_target_off_t; typedef grub_uint32_t grub_target_size_t; typedef grub_int32_t grub_target_ssize_t; #endif @@ -95,8 +99,10 @@ typedef grub_int64_t grub_ssize_t; # if GRUB_CPU_SIZEOF_LONG == 8 # define PRIxGRUB_SIZE "lx" +# define PRIuGRUB_SIZE "lu" # else # define PRIxGRUB_SIZE "llx" +# define PRIuGRUB_SIZE "llu" # endif #else typedef grub_uint32_t grub_addr_t; @@ -104,6 +110,7 @@ typedef grub_uint32_t grub_size_t; typedef grub_int32_t grub_ssize_t; # define PRIxGRUB_SIZE "x" +# define PRIuGRUB_SIZE "u" #endif #if GRUB_CPU_SIZEOF_LONG == 8 diff --git a/include/grub/usb.h b/include/grub/usb.h index 3c17318fc..6f838e4f9 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -19,6 +19,7 @@ #ifndef GRUB_USB_H #define GRUB_USB_H 1 +#include #include #include @@ -29,6 +30,7 @@ typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t; typedef enum { GRUB_USB_ERR_NONE, + GRUB_USB_ERR_WAIT, GRUB_USB_ERR_INTERNAL, GRUB_USB_ERR_STALL, GRUB_USB_ERR_DATA, @@ -88,6 +90,7 @@ grub_usb_err_t grub_usb_root_hub (grub_usb_controller_t controller); + /* XXX: All handled by libusb for now. */ struct grub_usb_controller_dev { @@ -96,8 +99,15 @@ struct grub_usb_controller_dev int (*iterate) (int (*hook) (grub_usb_controller_t dev)); - grub_usb_err_t (*transfer) (grub_usb_controller_t dev, - grub_usb_transfer_t transfer); + grub_usb_err_t (*setup_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer); + + grub_usb_err_t (*check_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual); + + grub_usb_err_t (*cancel_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer); int (*hubports) (grub_usb_controller_t dev); @@ -106,6 +116,9 @@ struct grub_usb_controller_dev grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed); + /* Per controller flag - port reset pending, don't do another reset */ + grub_uint64_t pending_reset; + /* The next host controller. */ struct grub_usb_controller_dev *next; }; @@ -132,6 +145,8 @@ struct grub_usb_interface int attached; void (*detach_hook) (struct grub_usb_device *dev, int config, int interface); + + void *detach_data; }; struct grub_usb_configuration @@ -166,12 +181,40 @@ struct grub_usb_device /* Data toggle values (used for bulk transfers only). */ int toggle[256]; - /* Device-specific data. */ + /* Used by libusb wrapper. Schedulded for removal. */ void *data; + + /* Hub information. */ + + /* Array of children for a hub. */ + grub_usb_device_t *children; + + /* Number of hub ports. */ + unsigned nports; + + grub_usb_transfer_t hub_transfer; + + grub_uint32_t statuschange; + + struct grub_usb_desc_endp *hub_endpoint; }; +typedef enum grub_usb_ep_type + { + GRUB_USB_EP_CONTROL, + GRUB_USB_EP_ISOCHRONOUS, + GRUB_USB_EP_BULK, + GRUB_USB_EP_INTERRUPT + } grub_usb_ep_type_t; + +static inline enum grub_usb_ep_type +grub_usb_get_ep_type (struct grub_usb_desc_endp *ep) +{ + return ep->attrib & 3; +} + typedef enum { GRUB_USB_CLASS_NOTHERE, @@ -230,5 +273,16 @@ void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc); void grub_usb_poll_devices (void); void grub_usb_device_attach (grub_usb_device_t dev); +grub_usb_err_t +grub_usb_bulk_read_extended (grub_usb_device_t dev, + int endpoint, grub_size_t size, char *data, + int timeout, grub_size_t *actual); +grub_usb_transfer_t +grub_usb_bulk_read_background (grub_usb_device_t dev, + int endpoint, grub_size_t size, void *data); +grub_usb_err_t +grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); +void +grub_usb_cancel_transfer (grub_usb_transfer_t trans); #endif /* GRUB_USB_H */ diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h index 2f711d755..84b723a62 100644 --- a/include/grub/usbdesc.h +++ b/include/grub/usbdesc.h @@ -31,6 +31,12 @@ typedef enum { GRUB_USB_DESCRIPTOR_HUB = 0x29 } grub_usb_descriptor_t; +struct grub_usb_desc +{ + grub_uint8_t length; + grub_uint8_t type; +} __attribute__ ((packed)); + struct grub_usb_desc_device { grub_uint8_t length; diff --git a/include/grub/usbserial.h b/include/grub/usbserial.h new file mode 100644 index 000000000..74201256e --- /dev/null +++ b/include/grub/usbserial.h @@ -0,0 +1,34 @@ +/* serial.h - serial device interface */ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#ifndef GRUB_USBSERIAL_HEADER +#define GRUB_USBSERIAL_HEADER 1 + +void grub_usbserial_fini (struct grub_serial_port *port); + +void grub_usbserial_detach (grub_usb_device_t usbdev, int configno, + int interfno); + +int +grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, + struct grub_serial_driver *driver); +int +grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size); + +#endif diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index e68698c1d..5ee276d26 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -38,6 +38,7 @@ struct grub_usb_transaction int toggle; grub_transfer_type_t pid; grub_uint32_t data; + grub_size_t preceding; }; typedef struct grub_usb_transaction *grub_usb_transaction_t; @@ -55,51 +56,89 @@ struct grub_usb_transfer grub_transaction_type_t type; + grub_transfer_type_t dir; + struct grub_usb_device *dev; struct grub_usb_transaction *transactions; int last_trans; /* Index of last processed transaction in OHCI/UHCI driver. */ + + void *controller_data; + + /* Used when finishing transfer to copy data back. */ + struct grub_pci_dma_chunk *data_chunk; + void *data; }; typedef struct grub_usb_transfer *grub_usb_transfer_t; -#define GRUB_USB_REQTYPE_IN (1 << 7) -#define GRUB_USB_REQTYPE_OUT (0 << 7) -#define GRUB_USB_REQTYPE_STANDARD (0 << 5) -#define GRUB_USB_REQTYPE_CLASS (1 << 5) -#define GRUB_USB_REQTYPE_VENDOR (2 << 5) -#define GRUB_USB_REQTYPE_TARGET_DEV (0 << 0) -#define GRUB_USB_REQTYPE_TARGET_INTERF (1 << 0) -#define GRUB_USB_REQTYPE_TARGET_ENDP (2 << 0) -#define GRUB_USB_REQTYPE_TARGET_OTHER (3 << 0) -#define GRUB_USB_REQ_GET_STATUS 0x00 -#define GRUB_USB_REQ_CLEAR_FEATURE 0x01 -#define GRUB_USB_REQ_SET_FEATURE 0x03 -#define GRUB_USB_REQ_SET_ADDRESS 0x05 -#define GRUB_USB_REQ_GET_DESCRIPTOR 0x06 -#define GRUB_USB_REQ_SET_DESCRIPTOR 0x07 -#define GRUB_USB_REQ_GET_CONFIGURATION 0x08 -#define GRUB_USB_REQ_SET_CONFIGURATION 0x09 -#define GRUB_USB_REQ_GET_INTERFACE 0x0A -#define GRUB_USB_REQ_SET_INTERFACE 0x0B -#define GRUB_USB_REQ_SYNC_FRAME 0x0C +enum + { + GRUB_USB_REQTYPE_TARGET_DEV = (0 << 0), + GRUB_USB_REQTYPE_TARGET_INTERF = (1 << 0), + GRUB_USB_REQTYPE_TARGET_ENDP = (2 << 0), + GRUB_USB_REQTYPE_TARGET_OTHER = (3 << 0), + GRUB_USB_REQTYPE_STANDARD = (0 << 5), + GRUB_USB_REQTYPE_CLASS = (1 << 5), + GRUB_USB_REQTYPE_VENDOR = (2 << 5), + GRUB_USB_REQTYPE_OUT = (0 << 7), + GRUB_USB_REQTYPE_IN = (1 << 7), + GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT = GRUB_USB_REQTYPE_TARGET_INTERF + | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_OUT, + GRUB_USB_REQTYPE_VENDOR_OUT = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_OUT, + GRUB_USB_REQTYPE_CLASS_INTERFACE_IN = GRUB_USB_REQTYPE_TARGET_INTERF + | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_IN, + GRUB_USB_REQTYPE_VENDOR_IN = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_IN + }; + +enum + { + GRUB_USB_REQ_GET_STATUS = 0x00, + GRUB_USB_REQ_CLEAR_FEATURE = 0x01, + GRUB_USB_REQ_SET_FEATURE = 0x03, + GRUB_USB_REQ_SET_ADDRESS = 0x05, + GRUB_USB_REQ_GET_DESCRIPTOR = 0x06, + GRUB_USB_REQ_SET_DESCRIPTOR = 0x07, + GRUB_USB_REQ_GET_CONFIGURATION = 0x08, + GRUB_USB_REQ_SET_CONFIGURATION = 0x09, + GRUB_USB_REQ_GET_INTERFACE = 0x0A, + GRUB_USB_REQ_SET_INTERFACE = 0x0B, + GRUB_USB_REQ_SYNC_FRAME = 0x0C + }; #define GRUB_USB_FEATURE_ENDP_HALT 0x00 #define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01 #define GRUB_USB_FEATURE_TEST_MODE 0x02 -#define GRUB_USB_HUB_FEATURE_PORT_RESET 0x04 -#define GRUB_USB_HUB_FEATURE_PORT_POWER 0x08 -#define GRUB_USB_HUB_FEATURE_C_CONNECTED 0x10 +enum + { + GRUB_USB_HUB_FEATURE_PORT_RESET = 0x04, + GRUB_USB_HUB_FEATURE_PORT_POWER = 0x08, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED = 0x10, + GRUB_USB_HUB_FEATURE_C_PORT_ENABLED = 0x11, + GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND = 0x12, + GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT = 0x13, + GRUB_USB_HUB_FEATURE_C_PORT_RESET = 0x14 + }; -#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0) -#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9) -#define GRUB_USB_HUB_STATUS_HIGHSPEED (1 << 10) -#define GRUB_USB_HUB_STATUS_C_CONNECTED (1 << 16) -#define GRUB_USB_HUB_STATUS_C_PORT_RESET (1 << 20) +enum + { + GRUB_USB_HUB_STATUS_PORT_CONNECTED = (1 << 0), + GRUB_USB_HUB_STATUS_PORT_ENABLED = (1 << 1), + GRUB_USB_HUB_STATUS_PORT_SUSPEND = (1 << 2), + GRUB_USB_HUB_STATUS_PORT_OVERCURRENT = (1 << 3), + GRUB_USB_HUB_STATUS_PORT_POWERED = (1 << 8), + GRUB_USB_HUB_STATUS_PORT_LOWSPEED = (1 << 9), + GRUB_USB_HUB_STATUS_PORT_HIGHSPEED = (1 << 10), + GRUB_USB_HUB_STATUS_C_PORT_CONNECTED = (1 << 16), + GRUB_USB_HUB_STATUS_C_PORT_ENABLED = (1 << 17), + GRUB_USB_HUB_STATUS_C_PORT_SUSPEND = (1 << 18), + GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT = (1 << 19), + GRUB_USB_HUB_STATUS_C_PORT_RESET = (1 << 20) + }; struct grub_usb_packet_setup { diff --git a/include/grub/util/libzfs.h b/include/grub/util/libzfs.h index 0500f70d7..a02caa335 100644 --- a/include/grub/util/libzfs.h +++ b/include/grub/util/libzfs.h @@ -42,4 +42,6 @@ extern nvlist_t *zpool_get_config (zpool_handle_t *, nvlist_t **); #endif /* ! HAVE_LIBZFS_H */ +libzfs_handle_t *grub_get_libzfs_handle (void); + #endif diff --git a/include/grub/vga.h b/include/grub/vga.h index d4a1523a7..7f112d83a 100644 --- a/include/grub/vga.h +++ b/include/grub/vga.h @@ -19,9 +19,13 @@ #ifndef GRUB_VGA_HEADER #define GRUB_VGA_HEADER 1 +#include + enum { GRUB_VGA_IO_ARX = 0x3c0, + GRUB_VGA_IO_ARX_READ = 0x3c1, + GRUB_VGA_IO_MISC_WRITE = 0x3c2, GRUB_VGA_IO_SR_INDEX = 0x3c4, GRUB_VGA_IO_SR_DATA = 0x3c5, GRUB_VGA_IO_PIXEL_MASK = 0x3c6, @@ -39,8 +43,15 @@ enum enum { - GRUB_VGA_CR_WIDTH = 0x01, + GRUB_VGA_CR_HTOTAL = 0x00, + GRUB_VGA_CR_HORIZ_END = 0x01, + GRUB_VGA_CR_HBLANK_START = 0x02, + GRUB_VGA_CR_HBLANK_END = 0x03, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_START = 0x04, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_END = 0x05, + GRUB_VGA_CR_VERT_TOTAL = 0x06, GRUB_VGA_CR_OVERFLOW = 0x07, + GRUB_VGA_CR_BYTE_PANNING = 0x08, GRUB_VGA_CR_CELL_HEIGHT = 0x09, GRUB_VGA_CR_CURSOR_START = 0x0a, GRUB_VGA_CR_CURSOR_END = 0x0b, @@ -48,14 +59,71 @@ enum GRUB_VGA_CR_START_ADDR_LOW_REGISTER = 0x0d, GRUB_VGA_CR_CURSOR_ADDR_HIGH = 0x0e, GRUB_VGA_CR_CURSOR_ADDR_LOW = 0x0f, + GRUB_VGA_CR_VSYNC_START = 0x10, GRUB_VGA_CR_VSYNC_END = 0x11, - GRUB_VGA_CR_HEIGHT = 0x12, + GRUB_VGA_CR_VDISPLAY_END = 0x12, GRUB_VGA_CR_PITCH = 0x13, + GRUB_VGA_CR_UNDERLINE_LOCATION = 0x14, + GRUB_VGA_CR_VERTICAL_BLANK_START = 0x15, + GRUB_VGA_CR_VERTICAL_BLANK_END = 0x16, GRUB_VGA_CR_MODE = 0x17, GRUB_VGA_CR_LINE_COMPARE = 0x18, }; +enum + { + GRUB_VGA_CR_BYTE_PANNING_NORMAL = 0 + }; + +enum + { + GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE = 0x40 + }; + +enum + { + GRUB_VGA_IO_MISC_COLOR = 0x01, + GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS = 0x02, + GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08, + GRUB_VGA_IO_MISC_28MHZ = 0x04, + GRUB_VGA_IO_MISC_UPPER_64K = 0x20, + GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY = 0x40, + GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY = 0x80, + }; + +enum + { + GRUB_VGA_ARX_MODE = 0x10, + GRUB_VGA_ARX_OVERSCAN = 0x11, + GRUB_VGA_ARX_COLOR_PLANE_ENABLE = 0x12, + GRUB_VGA_ARX_HORIZONTAL_PANNING = 0x13, + GRUB_VGA_ARX_COLOR_SELECT = 0x14 + }; + +enum + { + GRUB_VGA_ARX_MODE_TEXT = 0x00, + GRUB_VGA_ARX_MODE_GRAPHICS = 0x01, + GRUB_VGA_ARX_MODE_ENABLE_256COLOR = 0x40 + }; + #define GRUB_VGA_CR_WIDTH_DIVISOR 8 + +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT 7 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK 0x02 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT 3 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK 0x40 + +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT 8 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK 0x01 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT 4 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK 0x20 + +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT 6 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK 0x04 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT 2 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK 0x80 + #define GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7 #define GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02 #define GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3 @@ -65,7 +133,9 @@ enum #define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 #define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 - +#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK 0x20 +#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT 4 +#define GRUB_VGA_CR_CELL_HEIGHT_DOUBLE_SCAN 0x80 enum { GRUB_VGA_CR_CURSOR_START_DISABLE = (1 << 5) @@ -77,17 +147,26 @@ enum { GRUB_VGA_CR_MODE_NO_CGA = 0x01, GRUB_VGA_CR_MODE_NO_HERCULES = 0x02, + GRUB_VGA_CR_MODE_ADDRESS_WRAP = 0x20, GRUB_VGA_CR_MODE_BYTE_MODE = 0x40, GRUB_VGA_CR_MODE_TIMING_ENABLE = 0x80 }; enum { + GRUB_VGA_SR_RESET = 0, GRUB_VGA_SR_CLOCKING_MODE = 1, GRUB_VGA_SR_MAP_MASK_REGISTER = 2, + GRUB_VGA_SR_CHAR_MAP_SELECT = 3, GRUB_VGA_SR_MEMORY_MODE = 4, }; +enum + { + GRUB_VGA_SR_RESET_ASYNC = 1, + GRUB_VGA_SR_RESET_SYNC = 2 + }; + enum { GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK = 1 @@ -96,19 +175,33 @@ enum enum { GRUB_VGA_SR_MEMORY_MODE_NORMAL = 0, - GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8 + GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY = 2, + GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING = 4, + GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8, }; enum { + GRUB_VGA_GR_SET_RESET_PLANE = 0, + GRUB_VGA_GR_SET_RESET_PLANE_ENABLE = 1, + GRUB_VGA_GR_COLOR_COMPARE = 2, GRUB_VGA_GR_DATA_ROTATE = 3, GRUB_VGA_GR_READ_MAP_REGISTER = 4, GRUB_VGA_GR_MODE = 5, GRUB_VGA_GR_GR6 = 6, + GRUB_VGA_GR_COLOR_COMPARE_DISABLE = 7, GRUB_VGA_GR_BITMASK = 8, GRUB_VGA_GR_MAX }; +#define GRUB_VGA_ALL_PLANES 0xf +#define GRUB_VGA_NO_PLANES 0x0 + +enum + { + GRUB_VGA_GR_DATA_ROTATE_NOP = 0 + }; + enum { GRUB_VGA_TEXT_TEXT_PLANE = 0, @@ -119,6 +212,7 @@ enum enum { GRUB_VGA_GR_GR6_GRAPHICS_MODE = 1, + GRUB_VGA_GR_GR6_MMAP_A0 = (1 << 2), GRUB_VGA_GR_GR6_MMAP_CGA = (3 << 2) }; @@ -126,70 +220,152 @@ enum { GRUB_VGA_GR_MODE_READ_MODE1 = 0x08, GRUB_VGA_GR_MODE_ODD_EVEN = 0x10, + GRUB_VGA_GR_MODE_ODD_EVEN_SHIFT = 0x20, GRUB_VGA_GR_MODE_256_COLOR = 0x40 }; static inline void grub_vga_gr_write (grub_uint8_t val, grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_GR_INDEX); - grub_outb (val, GRUB_VGA_IO_GR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_INDEX); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_DATA); } static inline grub_uint8_t grub_vga_gr_read (grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_GR_INDEX); - return grub_inb (GRUB_VGA_IO_GR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_INDEX); + return grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_DATA); } static inline void grub_vga_cr_write (grub_uint8_t val, grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_CR_INDEX); - grub_outb (val, GRUB_VGA_IO_CR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_INDEX); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_DATA); } static inline grub_uint8_t grub_vga_cr_read (grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_CR_INDEX); - return grub_inb (GRUB_VGA_IO_CR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_INDEX); + return grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_DATA); } static inline void grub_vga_sr_write (grub_uint8_t val, grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_SR_INDEX); - grub_outb (val, GRUB_VGA_IO_SR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA); } static inline grub_uint8_t grub_vga_sr_read (grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_SR_INDEX); - return grub_inb (GRUB_VGA_IO_SR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX); + return grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA); } static inline void grub_vga_palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, grub_uint8_t *b) { - grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX); - *r = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); - *g = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); - *b = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_READ_INDEX); + *r = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + *g = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + *b = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); } static inline void grub_vga_palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, grub_uint8_t b) { - grub_outb (addr, GRUB_VGA_IO_PALLETTE_WRITE_INDEX); - grub_outb (r, GRUB_VGA_IO_PALLETTE_DATA); - grub_outb (g, GRUB_VGA_IO_PALLETTE_DATA); - grub_outb (b, GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_outb (r, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (g, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (b, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); } +static inline void +grub_vga_write_arx (grub_uint8_t val, grub_uint8_t addr) +{ + grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_INPUT_STATUS1_REGISTER); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); + grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX_READ); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); +} + +struct grub_video_hw_config +{ + unsigned vertical_total; + unsigned vertical_blank_start; + unsigned vertical_blank_end; + unsigned vertical_sync_start; + unsigned vertical_sync_end; + unsigned line_compare; + unsigned vdisplay_end; + unsigned pitch; + unsigned horizontal_total; + unsigned horizontal_blank_start; + unsigned horizontal_blank_end; + unsigned horizontal_sync_pulse_start; + unsigned horizontal_sync_pulse_end; + unsigned horizontal_end; +}; + +static inline void +grub_vga_set_geometry (struct grub_video_hw_config *config, + void (*cr_write) (grub_uint8_t val, grub_uint8_t addr)) +{ + unsigned vertical_total = config->vertical_total - 2; + unsigned vertical_blank_start = config->vertical_blank_start - 1; + unsigned vdisplay_end = config->vdisplay_end - 1; + grub_uint8_t overflow, cell_height_reg; + + /* Disable CR0-7 write protection. */ + cr_write (0, GRUB_VGA_CR_VSYNC_END); + + overflow = ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK) + | ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) + | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK) + | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) + | ((config->line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK); + + cell_height_reg = ((vertical_blank_start + >> GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK) + | ((config->line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK); + + cr_write (config->horizontal_total - 1, GRUB_VGA_CR_HTOTAL); + cr_write (config->horizontal_end - 1, GRUB_VGA_CR_HORIZ_END); + cr_write (config->horizontal_blank_start - 1, GRUB_VGA_CR_HBLANK_START); + cr_write (config->horizontal_blank_end, GRUB_VGA_CR_HBLANK_END); + cr_write (config->horizontal_sync_pulse_start, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_START); + cr_write (config->horizontal_sync_pulse_end, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_END); + cr_write (vertical_total & 0xff, GRUB_VGA_CR_VERT_TOTAL); + cr_write (overflow, GRUB_VGA_CR_OVERFLOW); + cr_write (cell_height_reg, GRUB_VGA_CR_CELL_HEIGHT); + cr_write (config->vertical_sync_start & 0xff, GRUB_VGA_CR_VSYNC_START); + cr_write (config->vertical_sync_end & 0x0f, GRUB_VGA_CR_VSYNC_END); + cr_write (vdisplay_end & 0xff, GRUB_VGA_CR_VDISPLAY_END); + cr_write (config->pitch & 0xff, GRUB_VGA_CR_PITCH); + cr_write (vertical_blank_start & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_START); + cr_write (config->vertical_blank_end & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_END); + cr_write (config->line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); +} #endif diff --git a/include/grub/video.h b/include/grub/video.h index 24167281f..5350d87eb 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -38,20 +38,33 @@ struct grub_video_bitmap; /* If following is set render target contains currenly displayed image after swapping buffers (otherwise it contains previously displayed image). */ -#define GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP 0x00000080 -#define GRUB_VIDEO_MODE_TYPE_PURE_TEXT 0x00000040 -#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000020 -#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000010 -#define GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP 0x00000004 -#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002 -#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001 +typedef enum grub_video_mode_type + { + GRUB_VIDEO_MODE_TYPE_RGB = 0x00000001, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR = 0x00000002, + GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP = 0x00000004, + GRUB_VIDEO_MODE_TYPE_YUV = 0x00000008, -/* Defines used to mask flags. */ -#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x0000000F + /* Defines used to mask flags. */ + GRUB_VIDEO_MODE_TYPE_COLOR_MASK = 0x0000000F, -/* Defines used to specify requested bit depth. */ -#define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00 -#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED = 0x00000010, + GRUB_VIDEO_MODE_TYPE_ALPHA = 0x00000020, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT = 0x00000040, + GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP = 0x00000080, + GRUB_VIDEO_MODE_TYPE_OPERATIONAL_MASK = 0x000000F0, + + /* Defines used to specify requested bit depth. */ + GRUB_VIDEO_MODE_TYPE_DEPTH_MASK = 0x0000FF00, +#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 + + GRUB_VIDEO_MODE_TYPE_UNKNOWN = 0x00010000, + GRUB_VIDEO_MODE_TYPE_HERCULES = 0x00020000, + GRUB_VIDEO_MODE_TYPE_PLANAR = 0x00040000, + GRUB_VIDEO_MODE_TYPE_NONCHAIN4 = 0x00080000, + GRUB_VIDEO_MODE_TYPE_CGA = 0x00100000, + GRUB_VIDEO_MODE_TYPE_INFO_MASK = 0x00FF0000, + } grub_video_mode_type_t; /* The basic render target representing the whole display. This always renders to the back buffer when double-buffering is in use. */ @@ -103,7 +116,7 @@ struct grub_video_mode_info /* Mode type bitmask. Contains information like is it Index color or RGB mode. */ - unsigned int mode_type; + grub_video_mode_type_t mode_type; /* Bits per pixel. */ unsigned int bpp; @@ -117,6 +130,9 @@ struct grub_video_mode_info /* In index color mode, number of colors. In RGB mode this is 256. */ unsigned int number_of_colors; + unsigned int mode_number; +#define GRUB_VIDEO_MODE_NUMBER_INVALID 0xffffffff + /* Optimization hint how binary data is coded. */ enum grub_video_blit_format blit_format; @@ -225,7 +241,8 @@ struct grub_video_adapter grub_err_t (*fini) (void); grub_err_t (*setup) (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask); + grub_video_mode_type_t mode_type, + grub_video_mode_type_t mode_mask); grub_err_t (*get_info) (struct grub_video_mode_info *mode_info); @@ -282,6 +299,10 @@ struct grub_video_adapter grub_err_t (*set_active_render_target) (struct grub_video_render_target *target); grub_err_t (*get_active_render_target) (struct grub_video_render_target **target); + + int (*iterate) (int (*hook) (const struct grub_video_mode_info *info)); + + void (*print_adapter_specific_info) (void); }; typedef struct grub_video_adapter *grub_video_adapter_t; @@ -398,8 +419,9 @@ grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modevalue); static inline int -grub_video_check_mode_flag (unsigned int flags, unsigned int mask, - unsigned int flag, int def) +grub_video_check_mode_flag (grub_video_mode_type_t flags, + grub_video_mode_type_t mask, + grub_video_mode_type_t flag, int def) { return (flag & mask) ? !! (flags & flag) : def; } diff --git a/include/grub/x86_64/memory.h b/include/grub/x86_64/memory.h new file mode 100644 index 000000000..27fcd2534 --- /dev/null +++ b/include/grub/x86_64/memory.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/xnu.h b/include/grub/xnu.h index 6089aad34..076aeb5ed 100644 --- a/include/grub/xnu.h +++ b/include/grub/xnu.h @@ -87,7 +87,7 @@ extern struct grub_xnu_devtree_key *grub_xnu_devtree_root; void grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur); -grub_err_t grub_xnu_writetree_toheap (void **start, grub_size_t *size); +grub_err_t grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size); struct grub_xnu_devtree_key *grub_xnu_create_value (struct grub_xnu_devtree_key **parent, char *name); @@ -102,14 +102,15 @@ grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, int maxrecursion); grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, int maxrecursion); -void *grub_xnu_heap_malloc (int size); +grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target); grub_err_t grub_xnu_fill_devicetree (void); -extern grub_uint32_t grub_xnu_heap_real_start; +extern struct grub_relocator *grub_xnu_relocator; + extern grub_size_t grub_xnu_heap_size; -extern void *grub_xnu_heap_start; extern struct grub_video_bitmap *grub_xnu_bitmap; typedef enum {GRUB_XNU_BITMAP_CENTER, GRUB_XNU_BITMAP_STRETCH} grub_xnu_bitmap_mode_t; extern grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode; extern int grub_xnu_is_64bit; +extern grub_addr_t grub_xnu_heap_target_start; #endif diff --git a/include/multiboot.h b/include/multiboot.h index fda863e85..bd133ba1f 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -1,5 +1,5 @@ /* multiboot.h - Multiboot header file. */ -/* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -236,6 +236,7 @@ struct multiboot_mmap_entry #define MULTIBOOT_MEMORY_RESERVED 2 #define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 #define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 multiboot_uint32_t type; } __attribute__((packed)); typedef struct multiboot_mmap_entry multiboot_memory_map_t; @@ -254,6 +255,20 @@ struct multiboot_mod_list }; typedef struct multiboot_mod_list multiboot_module_t; +/* APM BIOS info. */ +struct multiboot_apm_info +{ + grub_uint16_t version; + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; +}; + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ diff --git a/include/multiboot2.h b/include/multiboot2.h index 275debe75..0e26a8ec2 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -52,6 +52,12 @@ #define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 #define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 #define MULTIBOOT_TAG_TYPE_APM 10 +#define MULTIBOOT_TAG_TYPE_EFI32 11 +#define MULTIBOOT_TAG_TYPE_EFI64 12 +#define MULTIBOOT_TAG_TYPE_SMBIOS 13 +#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 +#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 +#define MULTIBOOT_TAG_TYPE_NETWORK 16 #define MULTIBOOT_HEADER_TAG_END 0 #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 @@ -167,6 +173,7 @@ struct multiboot_mmap_entry #define MULTIBOOT_MEMORY_RESERVED 2 #define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 #define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 multiboot_uint32_t type; multiboot_uint32_t zero; } __attribute__((packed)); @@ -309,6 +316,51 @@ struct multiboot_tag_apm multiboot_uint16_t dseg_len; }; +struct multiboot_tag_efi32 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_smbios +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t major; + multiboot_uint8_t minor; + multiboot_uint8_t reserved[6]; + multiboot_uint8_t tables[0]; +}; + +struct multiboot_tag_old_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_new_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_network +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t dhcpack[0]; +}; + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ diff --git a/kern/i386/loader.S b/kern/i386/loader.S deleted file mode 100644 index ed57c43ca..000000000 --- a/kern/i386/loader.S +++ /dev/null @@ -1,120 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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 . - */ - - -/* - * Note: These functions defined in this file may be called from C. - * Be careful of that you must not modify some registers. Quote - * from gcc-2.95.2/gcc/config/i386/i386.h: - - 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. - - ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg -{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } - */ - -/* - * Note: GRUB is compiled with the options -mrtd and -mregparm=3. - * So the first three arguments are passed in %eax, %edx, and %ecx, - * respectively, and if a function has a fixed number of arguments - * and the number if greater than three, the function must return - * with "ret $N" where N is ((the number of arguments) - 3) * 4. - */ - -/* - * This is the area for all of the special variables. - */ - - .p2align 2 /* force 4-byte alignment */ - -/* - * void grub_linux_boot_zimage (void) - */ -VARIABLE(grub_linux_prot_size) - .long 0 -VARIABLE(grub_linux_tmp_addr) - .long 0 -VARIABLE(grub_linux_real_addr) - .long 0 -VARIABLE(grub_linux_is_bzimage) - .long 0 - -FUNCTION(grub_linux16_real_boot) - /* Must be done before zImage copy. */ - call EXT_C(grub_dl_unload_all) - - movl EXT_C(grub_linux_is_bzimage), %ebx - test %ebx, %ebx - jne bzimage - - /* copy the kernel */ - movl EXT_C(grub_linux_prot_size), %ecx - addl $3, %ecx - shrl $2, %ecx - movl $GRUB_LINUX_BZIMAGE_ADDR, %esi - movl $GRUB_LINUX_ZIMAGE_ADDR, %edi - cld - rep - movsl - -bzimage: - movl EXT_C(grub_linux_real_addr), %ebx - - /* copy the real mode code */ - movl EXT_C(grub_linux_tmp_addr), %esi - movl %ebx, %edi - movl $GRUB_LINUX_SETUP_MOVE_SIZE, %ecx - cld - rep - movsb - - /* change %ebx to the segment address */ - shrl $4, %ebx - movl %ebx, %eax - addl $0x20, %eax - movw %ax, linux_setup_seg - - /* XXX new stack pointer in safe area for calling functions */ - movl $0x4000, %esp - call EXT_C(grub_stop_floppy) - - /* final setup for linux boot */ - call prot_to_real - .code16 - - cli - movw %bx, %ss - movw $GRUB_LINUX_SETUP_STACK, %sp - - movw %bx, %ds - movw %bx, %es - movw %bx, %fs - movw %bx, %gs - - /* ljmp */ - .byte 0xea - .word 0 -linux_setup_seg: - .word 0 - .code32 - diff --git a/kern/i386/misc.S b/kern/i386/misc.S deleted file mode 100644 index 7d57df9b9..000000000 --- a/kern/i386/misc.S +++ /dev/null @@ -1,29 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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 - - .text -/* - * This call is special... it never returns... in fact it should simply - * hang at this point! - */ -FUNCTION(grub_stop) - cli -1: hlt - jmp 1b diff --git a/kern/i386/pc/mmap.c b/kern/i386/pc/mmap.c deleted file mode 100644 index 72a6b3539..000000000 --- a/kern/i386/pc/mmap.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2006,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 - -grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) -{ - grub_uint32_t cont; - struct grub_machine_mmap_entry *entry - = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - - grub_memset (entry, 0, sizeof (entry)); - - /* Check if grub_get_mmap_entry works. */ - cont = grub_get_mmap_entry (entry, 0); - - if (entry->size) - do - { - if (hook (entry->addr, entry->len, - /* Multiboot mmaps have been defined to match with the E820 definition. - Therefore, we can just pass type through. */ - entry->type)) - break; - - if (! cont) - break; - - grub_memset (entry, 0, sizeof (entry)); - - cont = grub_get_mmap_entry (entry, cont); - } - while (entry->size); - else - { - grub_uint32_t eisa_mmap = grub_get_eisa_mmap (); - - if (eisa_mmap) - { - if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MACHINE_MEMORY_AVAILABLE) == 0) - hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MACHINE_MEMORY_AVAILABLE); - } - else - hook (0x100000, grub_get_memsize (1) << 10, GRUB_MACHINE_MEMORY_AVAILABLE); - } - - return 0; -} diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S deleted file mode 100644 index 761eb53fe..000000000 --- a/kern/i386/pc/startup.S +++ /dev/null @@ -1,2075 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,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 - * 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 . - */ - - -/* - * Note: These functions defined in this file may be called from C. - * Be careful of that you must not modify some registers. Quote - * from gcc-2.95.2/gcc/config/i386/i386.h: - - 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. - - ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg -{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } - */ - -/* - * Note: GRUB is compiled with the options -mrtd and -mregparm=3. - * So the first three arguments are passed in %eax, %edx, and %ecx, - * respectively, and if a function has a fixed number of arguments - * and the number is greater than three, the function must return - * with "ret $N" where N is ((the number of arguments) - 3) * 4. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) - - .file "startup.S" - - .text - - /* Tell GAS to generate 16-bit instructions so that this code works - in real mode. */ - .code16 - - .globl start, _start -start: -_start: -LOCAL (base): - /* - * Guarantee that "main" is loaded at 0x0:0x8200. - */ -#ifdef __APPLE__ - ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000) -#else - ljmp $0, $ABS(LOCAL (codestart)) -#endif - /* - * Compatibility version number - * - * These MUST be at byte offset 6 and 7 of the executable - * DO NOT MOVE !!! - */ - . = _start + 0x6 - .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR - - /* - * This is a special data area 8 bytes from the beginning. - */ - - . = _start + 0x8 - -VARIABLE(grub_total_module_size) - .long 0 -VARIABLE(grub_kernel_image_size) - .long 0 -VARIABLE(grub_compressed_size) - .long 0 -VARIABLE(grub_install_dos_part) - .long 0xFFFFFFFF -VARIABLE(grub_install_bsd_part) - .long 0xFFFFFFFF -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_DATA_END - -#ifdef APPLE_CC -bss_start: - .long 0 -bss_end: - .long 0 -#endif - -/* - * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). - * This uses the a.out kludge to load raw binary to the area starting at 1MB, - * and relocates itself after loaded. - */ - .p2align 2 /* force 4-byte alignment */ -multiboot_header: - /* magic */ - .long 0x1BADB002 - /* flags */ - .long (1 << 16) - /* checksum */ - .long -0x1BADB002 - (1 << 16) - /* header addr */ - .long multiboot_header - _start + 0x100000 + 0x200 - /* load addr */ - .long 0x100000 - /* load end addr */ - .long 0 - /* bss end addr */ - .long 0 - /* entry addr */ - .long multiboot_entry - _start + 0x100000 + 0x200 - -multiboot_entry: - .code32 - /* obtain the boot device */ - movl 12(%ebx), %edx - - movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp - movl %ebp, %esp - - /* relocate the code */ - movl $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx - addl EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx - movl $0x100000, %esi - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi - cld - rep - movsb - /* jump to the real address */ - movl $multiboot_trampoline, %eax - jmp *%eax - -multiboot_trampoline: - /* fill the boot information */ - movl %edx, %eax - shrl $8, %eax - xorl %ebx, %ebx - cmpb $0xFF, %ah - je 1f - movb %ah, %bl - movl %ebx, EXT_C(grub_install_dos_part) -1: - cmpb $0xFF, %al - je 2f - movb %al, %bl - movl %ebx, EXT_C(grub_install_bsd_part) -2: - shrl $24, %edx - movb $0xFF, %dh - /* enter the usual booting */ - call prot_to_real - .code16 - -/* the real mode code continues... */ -LOCAL (codestart): - cli /* we're not safe here! */ - - /* set up %ds, %ss, and %es */ - xorw %ax, %ax - movw %ax, %ds - movw %ax, %ss - movw %ax, %es - - /* set up the real mode/BIOS stack */ - movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp - movl %ebp, %esp - - sti /* we're safe again */ - - /* save the boot drive */ - ADDR32 movb %dl, EXT_C(grub_boot_drive) - - /* reset disk system (%ah = 0) */ - int $0x13 - - /* transition to protected mode */ - DATA32 call real_to_prot - - /* The ".code32" directive takes GAS out of 16-bit mode. */ - .code32 - - incl %eax - call EXT_C(grub_gate_a20) - -#ifdef ENABLE_LZMA - movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi - movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi - pushl %edi - pushl %esi - movl EXT_C(grub_kernel_image_size), %ecx - addl EXT_C(grub_total_module_size), %ecx - subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx - pushl %ecx - leal (%edi, %ecx), %ebx - call _LzmaDecodeA - /* _LzmaDecodeA clears DF, so no need to run cld */ - popl %ecx - popl %edi - popl %esi -#endif - - /* copy back the decompressed part (except the modules) */ - subl EXT_C(grub_total_module_size), %ecx - rep - movsb - -#if 0 - /* copy modules before cleaning out the bss */ - movl EXT_C(grub_total_module_size), %ecx - movl EXT_C(grub_kernel_image_size), %esi - addl %ecx, %esi - addl $_start, %esi - decl %esi - movl $END_SYMBOL, %edi - addl %ecx, %edi - decl %edi - std - rep - movsb -#endif - -#ifdef APPLE_CC - /* clean out the bss */ - bss_start_abs = ABS (bss_start) - bss_end_abs = ABS (bss_end) - - movl bss_start_abs, %edi - - /* compute the bss length */ - movl bss_end_abs, %ecx - subl %edi, %ecx -#else - /* clean out the bss */ - movl $BSS_START_SYMBOL, %edi - - /* compute the bss length */ - movl $END_SYMBOL, %ecx - subl %edi, %ecx -#endif - - /* clean out */ - xorl %eax, %eax - cld - rep - stosb - - /* - * Call the start of main body of C code. - */ - call EXT_C(grub_main) - -/* - * This is the area for all of the special variables. - */ - -VARIABLE(grub_boot_drive) - .byte 0 - - .p2align 2 /* force 4-byte alignment */ - -#include "../realmode.S" - -/* - * grub_gate_a20(int on) - * - * Gate address-line 20 for high memory. - * - * This routine is probably overconservative in what it does, but so what? - * - * It also eats any keystrokes in the keyboard buffer. :-( - */ - -FUNCTION(grub_gate_a20) - movl %eax, %edx - -gate_a20_test_current_state: - /* first of all, test if already in a good state */ - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_bios - ret - -gate_a20_try_bios: - /* second, try a BIOS call */ - pushl %ebp - call prot_to_real - - .code16 - movw $0x2400, %ax - testb %dl, %dl - jz 1f - incw %ax -1: int $0x15 - - DATA32 call real_to_prot - .code32 - - popl %ebp - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_system_control_port_a - ret - -gate_a20_try_system_control_port_a: - /* - * In macbook, the keyboard test would hang the machine, so we move - * this forward. - */ - /* fourth, try the system control port A */ - inb $0x92 - andb $(~0x03), %al - testb %dl, %dl - jz 6f - orb $0x02, %al -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 - cmpb %al, %dl - jnz gate_a20_try_keyboard_controller -7: ret - -gate_a20_flush_keyboard_buffer: - inb $0x64 - andb $0x02, %al - jnz gate_a20_flush_keyboard_buffer -2: - inb $0x64 - andb $0x01, %al - jz 3f - inb $0x60 - jmp 2b -3: - ret - -gate_a20_try_keyboard_controller: - /* third, try the keyboard controller */ - call gate_a20_flush_keyboard_buffer - - movb $0xd1, %al - outb $0x64 -4: - inb $0x64 - andb $0x02, %al - jnz 4b - - 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) */ - movb $0xff, %al - outb $0x64 - call gate_a20_flush_keyboard_buffer - - call gate_a20_check_state - cmpb %al, %dl - /* everything failed, so restart from the beginning */ - jnz gate_a20_try_bios - ret - -gate_a20_check_state: - /* iterate the checking for a while */ - movl $100, %ecx -1: - call 3f - cmpb %al, %dl - jz 2f - loop 1b -2: - ret -3: - pushl %ebx - pushl %ecx - xorl %eax, %eax - /* compare the byte at 0x8000 with that at 0x108000 */ - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx - pushl %ebx - /* save the original byte in CL */ - movb (%ebx), %cl - /* store the value at 0x108000 in AL */ - addl $0x100000, %ebx - movb (%ebx), %al - /* try to set one less value at 0x8000 */ - popl %ebx - movb %al, %ch - decb %ch - movb %ch, (%ebx) - /* serialize */ - outb %al, $0x80 - outb %al, $0x80 - /* obtain the value at 0x108000 in CH */ - pushl %ebx - addl $0x100000, %ebx - movb (%ebx), %ch - /* 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) - popl %ecx - popl %ebx - ret - -#ifdef ENABLE_LZMA -#include "lzma_decode.S" -#endif - -/* - * The code beyond this point is compressed. Assert that the uncompressed - * code fits GRUB_KERNEL_MACHINE_RAW_SIZE. - */ - . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE - - /* - * This next part is sort of evil. It takes advantage of the - * byte ordering on the x86 to work in either 16-bit or 32-bit - * mode, so think about it before changing it. - */ - -FUNCTION(grub_hard_stop) - hlt - jmp EXT_C(grub_hard_stop) - - -/* - * grub_stop_floppy() - * - * Stop the floppy drive from spinning, so that other software is - * jumped to with a known state. - */ -FUNCTION(grub_stop_floppy) - movw $0x3F2, %dx - xorb %al, %al - outb %al, %dx - ret - -/* - * grub_exit() - * - * Exit the system. - */ -FUNCTION(grub_exit) - call prot_to_real - .code16 - /* Tell the BIOS a boot failure. If this does not work, reboot. */ - int $0x18 - jmp cold_reboot - .code32 - -/* - * grub_halt(int no_apm) - * - * Halt the system, using APM if possible. If NO_APM is true, don't use - * APM even if it is available. - */ -FUNCTION(grub_halt) - /* see if zero */ - testl %eax, %eax - jnz EXT_C(grub_stop) - - call prot_to_real - .code16 - - /* detect APM */ - movw $0x5300, %ax - xorw %bx, %bx - int $0x15 - jc EXT_C(grub_hard_stop) - /* don't check %bx for buggy BIOSes... */ - - /* disconnect APM first */ - movw $0x5304, %ax - xorw %bx, %bx - int $0x15 - - /* connect APM */ - movw $0x5301, %ax - xorw %bx, %bx - int $0x15 - jc EXT_C(grub_hard_stop) - - /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */ - movw $0x530E, %ax - xorw %bx, %bx - movw $0x0101, %cx - int $0x15 - jc EXT_C(grub_hard_stop) - - /* set the power state to off */ - movw $0x5307, %ax - movw $1, %bx - movw $3, %cx - int $0x15 - - /* shouldn't reach here */ - jmp EXT_C(grub_hard_stop) - .code32 - - -/* - * void grub_chainloader_real_boot (int drive, void *part_addr) - * - * This starts another boot loader. - */ - -FUNCTION(grub_chainloader_real_boot) - pushl %edx - pushl %eax - - call EXT_C(grub_dl_unload_all) - - /* Turn off Gate A20 */ - xorl %eax, %eax - call EXT_C(grub_gate_a20) - - /* set up to pass boot drive */ - popl %edx - - /* ESI must point to a partition table entry */ - popl %esi - - call prot_to_real - .code16 - ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR - .code32 - -#include "../loader.S" - -/* - * int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) - * - * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP - * is passed for disk address packet. If an error occurs, return - * non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_rw_int13_extensions) - pushl %ebp - pushl %esi - - /* compute the address of disk_address_packet */ - movw %cx, %si - xorw %cx, %cx - shrl $4, %ecx /* save the segment to cx */ - - /* ah */ - movb %al, %dh - /* enter real mode */ - call prot_to_real - - .code16 - movb %dh, %ah - movw %cx, %ds - int $0x13 /* do the operation */ - movb %ah, %dl /* save return value */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %dl, %al /* return value in %eax */ - - popl %esi - popl %ebp - - ret - -/* - * int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, - * int soff, int nsec, int segment) - * - * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write - * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, - * return non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_rw_standard) - pushl %ebp - movl %esp, %ebp - - pushl %ebx - pushl %edi - pushl %esi - - /* set up CHS information */ - - /* set %ch to low eight bits of cylinder */ - xchgb %cl, %ch - /* set bits 6-7 of %cl to high two bits of cylinder */ - shlb $6, %cl - /* set bits 0-5 of %cl to sector */ - addb 0xc(%ebp), %cl - /* set %dh to head */ - movb 0x8(%ebp), %dh - /* set %ah to AH */ - movb %al, %ah - /* set %al to NSEC */ - movb 0x10(%ebp), %al - /* save %ax in %di */ - movw %ax, %di - /* save SEGMENT in %bx */ - movw 0x14(%ebp), %bx - - /* enter real mode */ - call prot_to_real - - .code16 - movw %bx, %es - xorw %bx, %bx - movw $3, %si /* attempt at least three times */ - -1: - movw %di, %ax - int $0x13 /* do the operation */ - jnc 2f /* check if successful */ - - movb %ah, %bl /* save return value */ - /* if fail, reset the disk system */ - xorw %ax, %ax - int $0x13 - - decw %si - cmpw $0, %si - je 2f - xorb %bl, %bl - jmp 1b /* retry */ -2: - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %bl, %al /* return value in %eax */ - - popl %esi - popl %edi - popl %ebx - popl %ebp - - ret $(4 * 4) - - -/* - * int grub_biosdisk_check_int13_extensions (int drive) - * - * Check if LBA is supported for DRIVE. If it is supported, then return - * the major version of extensions, otherwise zero. - */ - -FUNCTION(grub_biosdisk_check_int13_extensions) - pushl %ebp - pushl %ebx - - /* drive */ - movb %al, %dl - /* enter real mode */ - call prot_to_real - - .code16 - movb $0x41, %ah - movw $0x55aa, %bx - int $0x13 /* do the operation */ - - /* check the result */ - jc 1f - cmpw $0xaa55, %bx - jne 1f - - movb %ah, %bl /* save the major version into %bl */ - - /* check if AH=0x42 is supported */ - andw $1, %cx - jnz 2f - -1: - xorb %bl, %bl -2: - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %bl, %al /* return value in %eax */ - - popl %ebx - popl %ebp - - ret - - -/* - * int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp) - * - * Return the cdrom information of DRIVE in CDRP. If an error occurs, - * then return non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions) - movw $0x4B01, %cx - jmp 1f - -/* - * int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp) - * - * Return the geometry of DRIVE in a drive parameters, DRP. If an error - * occurs, then return non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions) - movb $0x48, %ch -1: - pushl %ebp - pushl %ebx - pushl %esi - - /* compute the address of drive parameters */ - movw %dx, %si - andl $0xf, %esi - shrl $4, %edx - movw %dx, %bx /* save the segment into %bx */ - /* drive */ - movb %al, %dl - /* enter real mode */ - call prot_to_real - - .code16 - movw %cx, %ax - movw %bx, %ds - int $0x13 /* do the operation */ - jc noclean - /* Clean return value if carry isn't set to workaround - some buggy BIOSes. */ - xor %ax, %ax -noclean: - movb %ah, %bl /* save return value in %bl */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %bl, %al /* return value in %eax */ - - popl %esi - popl %ebx - popl %ebp - - ret - - -/* - * int grub_biosdisk_get_diskinfo_standard (int drive, - * unsigned long *cylinders, - * unsigned long *heads, - * unsigned long *sectors) - * - * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an - * error occurs, then return non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_get_diskinfo_standard) - pushl %ebp - pushl %ebx - pushl %edi - - /* push CYLINDERS */ - pushl %edx - /* push HEADS */ - pushl %ecx - /* SECTORS is on the stack */ - - /* drive */ - movb %al, %dl - /* enter real mode */ - call prot_to_real - - .code16 - movb $0x8, %ah - int $0x13 /* do the operation */ - jc noclean2 - /* Clean return value if carry isn't set to workaround - some buggy BIOSes. */ - xor %ax, %ax -noclean2: - /* check if successful */ - testb %ah, %ah - jnz 1f - /* bogus BIOSes may not return an error number */ - testb $0x3f, %cl /* 0 sectors means no disk */ - jnz 1f /* if non-zero, then succeed */ - /* XXX 0x60 is one of the unused error numbers */ - movb $0x60, %ah -1: - movb %ah, %bl /* save return value in %bl */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - /* pop HEADS */ - popl %edi - movb %dh, %al - incl %eax /* the number of heads is counted from zero */ - movl %eax, (%edi) - - /* pop CYLINDERS */ - popl %edi - movb %ch, %al - movb %cl, %ah - shrb $6, %ah /* the number of cylinders is counted from zero */ - incl %eax - movl %eax, (%edi) - - /* SECTORS */ - movl 0x10(%esp), %edi - andb $0x3f, %cl - movzbl %cl, %eax - movl %eax, (%edi) - - xorl %eax, %eax - movb %bl, %al /* return value in %eax */ - - popl %edi - popl %ebx - popl %ebp - - ret $4 - - -/* - * int grub_biosdisk_get_num_floppies (void) - */ -FUNCTION(grub_biosdisk_get_num_floppies) - pushl %ebp - - xorl %edx, %edx - call prot_to_real - - .code16 - /* reset the disk system first */ - int $0x13 -1: - stc - - /* call GET DISK TYPE */ - movb $0x15, %ah - int $0x13 - - jc 2f - - /* check if this drive exists */ - testb $0x3, %ah - jz 2f - - incb %dl - cmpb $2, %dl - jne 1b -2: - DATA32 call real_to_prot - .code32 - - movl %edx, %eax - popl %ebp - ret - - -/* - * - * grub_get_memsize(i) : return the memory size in KB. i == 0 for conventional - * memory, i == 1 for extended memory - * BIOS call "INT 12H" to get conventional memory size - * BIOS call "INT 15H, AH=88H" to get extended memory size - * Both have the return value in AX. - * - */ - -FUNCTION(grub_get_memsize) - pushl %ebp - - movl %eax, %edx - - call prot_to_real /* enter real mode */ - .code16 - - testl %edx, %edx - jnz xext - - int $0x12 - jmp xdone - -xext: - movb $0x88, %ah - int $0x15 - -xdone: - movw %ax, %dx - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - - popl %ebp - ret - - -/* - * - * grub_get_eisa_mmap() : return packed EISA memory map, lower 16 bits is - * memory between 1M and 16M in 1K parts, upper 16 bits is - * memory above 16M in 64K parts. If error, return zero. - * BIOS call "INT 15H, AH=E801H" to get EISA memory map, - * AX = memory between 1M and 16M in 1K parts. - * BX = memory above 16M in 64K parts. - * - */ - -FUNCTION(grub_get_eisa_mmap) - pushl %ebp - pushl %ebx - - call prot_to_real /* enter real mode */ - .code16 - - movw $0xe801, %ax - int $0x15 - - shll $16, %ebx - movw %ax, %bx - - DATA32 call real_to_prot - .code32 - - cmpb $0x86, %bh - je xnoteisa - - movl %ebx, %eax - -xnoteisa: - popl %ebx - popl %ebp - ret - -/* - * - * grub_get_mmap_entry(addr, cont) : address and old continuation value (zero to - * start), for the Query System Address Map BIOS call. - * - * Sets the first 4-byte int value of "addr" to the size returned by - * the call. If the call fails, sets it to zero. - * - * Returns: new (non-zero) continuation value, 0 if done. - */ - -FUNCTION(grub_get_mmap_entry) - pushl %ebp - pushl %ebx - pushl %edi - pushl %esi - - /* push ADDR */ - pushl %eax - - /* place address (+4) in ES:DI */ - addl $4, %eax - movl %eax, %edi - andl $0xf, %edi - shrl $4, %eax - movl %eax, %esi - - /* set continuation value */ - movl %edx, %ebx - - /* set default maximum buffer size */ - movl $0x14, %ecx - - /* set EDX to 'SMAP' */ - movl $0x534d4150, %edx - - call prot_to_real /* enter real mode */ - .code16 - - movw %si, %es - movl $0xe820, %eax - int $0x15 - - DATA32 jc xnosmap - - cmpl $0x534d4150, %eax - jne xnosmap - - cmpl $0x14, %ecx - jl xnosmap - - cmpl $0x400, %ecx - jg xnosmap - - jmp xsmap - -xnosmap: - xorl %ecx, %ecx - -/* Apple's cc jumps few bytes before the correct - label in this context. Hence nops. */ -#ifdef APPLE_CC - nop - nop - nop - nop - nop - nop -#endif - -xsmap: - DATA32 call real_to_prot - .code32 - - /* write length of buffer (zero if error) into ADDR */ - popl %eax - movl %ecx, (%eax) - - /* set return value to continuation */ - movl %ebx, %eax - - popl %esi - popl %edi - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_putchar (const struct grub_unicode_glyph *c) - * - * Put the character C on the console. Because GRUB wants to write a - * character with an attribute, this implementation is a bit tricky. - * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh - * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, - * save the current position, restore the original position, write the - * character and the attribute, and restore the current position. - * - * The reason why this is so complicated is that there is no easy way to - * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't - * support setting a background attribute. - */ -FUNCTION(grub_console_putchar) - /* Retrieve the base character. */ - movl 0(%edx), %edx - pusha - movb EXT_C(grub_console_cur_color), %bl - - call prot_to_real - .code16 - movb %dl, %al - xorb %bh, %bh - - /* use teletype output if control character */ - cmpb $0x7, %al - je 1f - cmpb $0x8, %al - je 1f - cmpb $0xa, %al - je 1f - cmpb $0xd, %al - je 1f - - /* save the character and the attribute on the stack */ - pushw %ax - pushw %bx - - /* get the current position */ - movb $0x3, %ah - int $0x10 - - /* check the column with the width */ - cmpb $79, %dl - jl 2f - - /* print CR and LF, if next write will exceed the width */ - movw $0x0e0d, %ax - int $0x10 - movb $0x0a, %al - int $0x10 - - /* get the current position */ - movb $0x3, %ah - int $0x10 - -2: - /* restore the character and the attribute */ - popw %bx - popw %ax - - /* write the character with the attribute */ - movb $0x9, %ah - movw $1, %cx - int $0x10 - - /* move the cursor forward */ - incb %dl - movb $0x2, %ah - int $0x10 - - jmp 3f - -1: movw $1, %bx - movb $0xe, %ah - int $0x10 - -3: DATA32 call real_to_prot - .code32 - - popa - ret - - -/* - * int grub_console_getkey (void) - * BIOS call "INT 16H Function 00H" to read character from keyboard - * Call with %ah = 0x0 - * Return: %ah = keyboard scan code - * %al = ASCII character - */ - -/* this table is used in translate_keycode below */ -LOCAL (translation_table): - .word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT - .word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT - .word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP - .word GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN - .word GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME - .word GRUB_CONSOLE_KEY_END, GRUB_TERM_END - .word GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC - .word GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE - .word GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE - .word GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE - .word 0 - -/* - * translate_keycode translates the key code %dx to an ascii code. - */ - .code16 - -translate_keycode: - pushw %bx - pushw %si - -#ifdef __APPLE__ - movw $(ABS(LOCAL (translation_table)) - 0x10000), %si -#else - movw $ABS(LOCAL (translation_table)), %si -#endif - -1: lodsw - /* check if this is the end */ - testw %ax, %ax - jz 2f - /* load the ascii code into %ax */ - movw %ax, %bx - lodsw - /* check if this matches the key code */ - cmpw %bx, %dx - jne 1b - /* translate %dx, if successful */ - movw %ax, %dx - -2: popw %si - popw %bx - ret - - .code32 - -FUNCTION(grub_console_getkey) - pushl %ebp - - call prot_to_real - .code16 - - /* - * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would - * cause the machine to hang at the second keystroke. However, we can - * work around this problem by ensuring the presence of keystroke with - * INT 16/AH = 1 before calling INT 16/AH = 0. - */ - -1: - movb $1, %ah - int $0x16 - jnz 2f - hlt - jmp 1b - -2: - - movb $0, %ah - int $0x16 - - movw %ax, %dx /* real_to_prot uses %eax */ - call translate_keycode - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - - popl %ebp - ret - - -/* - * int grub_console_checkkey (void) - * if there is a character pending, return it; otherwise return -1 - * BIOS call "INT 16H Function 01H" to check whether a character is pending - * Call with %ah = 0x1 - * Return: - * If key waiting to be input: - * %ah = keyboard scan code - * %al = ASCII character - * Zero flag = clear - * else - * Zero flag = set - */ -FUNCTION(grub_console_checkkey) - pushl %ebp - xorl %edx, %edx - - call prot_to_real /* enter real mode */ - .code16 - - movb $0x1, %ah - int $0x16 - - jz notpending - - movw %ax, %dx - DATA32 jmp pending - -notpending: - decl %edx - -pending: - DATA32 call real_to_prot - .code32 - - movl %edx, %eax - - popl %ebp - ret - - -/* - * grub_uint16_t grub_console_getxy (void) - * BIOS call "INT 10H Function 03h" to get cursor position - * Call with %ah = 0x03 - * %bh = page - * Returns %ch = starting scan line - * %cl = ending scan line - * %dh = row (0 is top) - * %dl = column (0 is left) - */ - - -FUNCTION(grub_console_getxy) - pushl %ebp - pushl %ebx /* save EBX */ - - call prot_to_real - .code16 - - xorb %bh, %bh /* set page to 0 */ - movb $0x3, %ah - int $0x10 /* get cursor position */ - - DATA32 call real_to_prot - .code32 - - movb %dl, %ah - movb %dh, %al - - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y) - * BIOS call "INT 10H Function 02h" to set cursor position - * Call with %ah = 0x02 - * %bh = page - * %dh = row (0 is top) - * %dl = column (0 is left) - */ - - -FUNCTION(grub_console_gotoxy) - pushl %ebp - pushl %ebx /* save EBX */ - - movb %cl, %dh /* %dh = y */ - /* %dl = x */ - - call prot_to_real - .code16 - - xorb %bh, %bh /* set page to 0 */ - movb $0x2, %ah - int $0x10 /* set cursor position */ - - DATA32 call real_to_prot - .code32 - - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_cls (void) - * BIOS call "INT 10H Function 09h" to write character and attribute - * Call with %ah = 0x09 - * %al = (character) - * %bh = (page number) - * %bl = (attribute) - * %cx = (number of times) - */ - -FUNCTION(grub_console_cls) - pushl %ebp - pushl %ebx /* save EBX */ - - call prot_to_real - .code16 - - /* move the cursor to the beginning */ - movb $0x02, %ah - xorb %bh, %bh - xorw %dx, %dx - int $0x10 - - /* write spaces to the entire screen */ - movw $0x0920, %ax - movw $0x07, %bx - movw $(80 * 25), %cx - int $0x10 - - /* move back the cursor */ - movb $0x02, %ah - int $0x10 - - DATA32 call real_to_prot - .code32 - - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_setcursor (int on) - * BIOS call "INT 10H Function 01h" to set cursor type - * Call with %ah = 0x01 - * %ch = cursor starting scanline - * %cl = cursor ending scanline - */ - -console_cursor_state: - .byte 1 -console_cursor_shape: - .word 0 - -FUNCTION(grub_console_setcursor) - pushl %ebp - pushl %ebx - - /* push ON */ - pushl %edx - - /* check if the standard cursor shape has already been saved */ - movw console_cursor_shape, %ax - testw %ax, %ax - jne 1f - - call prot_to_real - .code16 - - movb $0x03, %ah - xorb %bh, %bh - int $0x10 - - DATA32 call real_to_prot - .code32 - - movw %cx, console_cursor_shape -1: - /* set %cx to the designated cursor shape */ - movw $0x2000, %cx - popl %eax - testl %eax, %eax - jz 2f - movw console_cursor_shape, %cx -2: - call prot_to_real - .code16 - - movb $0x1, %ah - int $0x10 - - DATA32 call real_to_prot - .code32 - - popl %ebx - popl %ebp - ret - -/* - * grub_get_rtc() - * return the real time in ticks, of which there are about - * 18-20 per second - */ -FUNCTION(grub_get_rtc) - pushl %ebp - - call prot_to_real /* enter real mode */ - .code16 - - /* %ax is already zero */ - int $0x1a - - DATA32 call real_to_prot - .code32 - - movl %ecx, %eax - shll $16, %eax - movw %dx, %ax - - popl %ebp - ret - - -/* - * unsigned char grub_vga_set_mode (unsigned char mode) - */ -FUNCTION(grub_vga_set_mode) - pushl %ebp - pushl %ebx - movl %eax, %ecx - - call prot_to_real - .code16 - /* get current mode */ - xorw %bx, %bx - movb $0x0f, %ah - int $0x10 - movb %al, %dl - - /* set the new mode */ - movb %cl, %al - xorb %ah, %ah - int $0x10 - - DATA32 call real_to_prot - .code32 - - movb %dl, %al - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info) - * - * Register allocations for parameters: - * %eax *controller_info - */ -FUNCTION(grub_vbe_bios_get_controller_info) - pushl %ebp - pushl %edi - pushl %edx - - movw %ax, %di /* Store *controller_info to %edx:%di. */ - xorw %ax, %ax - shrl $4, %eax - mov %eax, %edx /* prot_to_real destroys %eax. */ - - call prot_to_real - .code16 - - pushw %es - - movw %dx, %es /* *controller_info is now on %es:%di. */ - movw $0x4f00, %ax - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - popw %es - - DATA32 call real_to_prot - .code32 - - movl %edx, %eax - andl $0x0FFFF, %eax /* Return value in %eax. */ - - pop %edx - popl %edi - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode, - * struct grub_vbe_mode_info_block *mode_info) - * - * Register allocations for parameters: - * %eax mode - * %edx *mode_info - */ -FUNCTION(grub_vbe_bios_get_mode_info) - pushl %ebp - pushl %edi - - movl %eax, %ecx /* Store mode number to %ecx. */ - - movw %dx, %di /* Store *mode_info to %edx:%di. */ - xorw %dx, %dx - shrl $4, %edx - - call prot_to_real - .code16 - - pushw %es - - movw %dx, %es /* *mode_info is now on %es:%di. */ - movw $0x4f01, %ax - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - popw %es - - DATA32 call real_to_prot - .code32 - - movl %edx, %eax - andl $0x0FFFF, %eax /* Return value in %eax. */ - - popl %edi - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode, - * struct grub_vbe_crtc_info_block *crtc_info) - * - * Register allocations for parameters: - * %eax mode - * %edx *crtc_info - */ -FUNCTION(grub_vbe_bios_set_mode) - pushl %ebp - pushl %ebx - pushl %edi - - movl %eax, %ebx /* Store mode in %ebx. */ - - movw %dx, %di /* Store *crtc_info to %edx:%di. */ - xorw %dx, %dx - shrl $4, %edx - - call prot_to_real - .code16 - - pushw %es - - movw %dx, %es /* *crtc_info is now on %es:%di. */ - - movw $0x4f02, %ax - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - popw %es - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edi - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode) - * - * Register allocations for parameters: - * %eax *mode - */ -FUNCTION(grub_vbe_bios_get_mode) - pushl %ebp - pushl %ebx - pushl %edi - pushl %edx - pushl %eax /* Push *mode to stack. */ - - call prot_to_real - .code16 - - movw $0x4f03, %ax - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - popl %edi /* Pops *mode from stack to %edi. */ - andl $0xFFFF, %ebx - movl %ebx, (%edi) - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edx - popl %edi - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size) - * - * Register allocations for parameters: - * %eax set - * %edx *dac_mask_size - */ -FUNCTION(grub_vbe_bios_getset_dac_palette_width) - pushl %ebp - pushl %ebx - - xorl %ebx, %ebx - - /* If we only want to fetch the value, set %bl to 1. */ - testl %eax, %eax - jne 1f - incb %bl -1: - - /* Put desired width in %bh. */ - movl (%edx), %eax - movb %al, %bh - - call prot_to_real - .code16 - - movw $0x4f08, %ax - int $0x10 - - movw %ax, %cx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - /* Move result back to *dac_mask_size. */ - xorl %eax, %eax - movb %bh, %al - movl %eax, (%edx) - - /* Return value in %eax. */ - movw %cx, %ax - - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window, - * grub_uint32_t position); - * - * Register allocations for parameters: - * %eax window - * %edx position - */ -FUNCTION(grub_vbe_bios_set_memory_window) - pushl %ebp - pushl %ebx - - movl %eax, %ebx - - call prot_to_real - .code16 - - movw $0x4f05, %ax - andw $0x00ff, %bx /* BL = window, BH = 0, Set memory window. */ - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window, - * grub_uint32_t *position); - * - * Register allocations for parameters: - * %eax window - * %edx *position - */ -FUNCTION(grub_vbe_bios_get_memory_window) - pushl %ebp - pushl %ebx - pushl %edi - pushl %edx /* Push *position to stack. */ - - movl %eax, %ebx /* Store window in %ebx. */ - - call prot_to_real - .code16 - - movw $0x4f05, %ax - andw $0x00ff, %bx /* BL = window. */ - orw $0x0100, %bx /* BH = 1, Get memory window. */ - int $0x10 - - movw %ax, %bx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - popl %edi /* pops *position from stack to %edi. */ - andl $0xFFFF, %edx - movl %edx, (%edi) /* Return position to caller. */ - - movw %bx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edi - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length) - * - * Register allocations for parameters: - * %eax length - */ -FUNCTION(grub_vbe_bios_set_scanline_length) - pushl %ebp - pushl %ebx - pushl %edx - - movl %eax, %ecx /* Store length in %ecx. */ - - call prot_to_real - .code16 - - movw $0x4f06, %ax - movw $0x0002, %bx /* BL = 2, Set Scan Line in Bytes. */ - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edx - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length) - * - * Register allocations for parameters: - * %eax *length - */ -FUNCTION(grub_vbe_bios_get_scanline_length) - pushl %ebp - pushl %ebx - pushl %edi - pushl %edx /* Push *length to stack. */ - - call prot_to_real - .code16 - - movw $0x4f06, %ax - movw $0x0001, %bx /* BL = 1, Get Scan Line Length (in bytes). */ - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - popl %edi /* Pops *length from stack to %edi. */ - andl $0xFFFF, %ebx - movl %ebx, (%edi) /* Return length to caller. */ - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edi - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x, - * grub_uint32_t y) - * - * Register allocations for parameters: - * %eax x - * %edx y - */ -FUNCTION(grub_vbe_bios_set_display_start) - pushl %ebp - pushl %ebx - - movl %eax, %ecx /* Store x in %ecx. */ - - call prot_to_real - .code16 - - movw $0x4f07, %ax - movw $0x0080, %bx /* BL = 80h, Set Display Start - during Vertical Retrace. */ - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x, - * grub_uint32_t *y) - * - * Register allocations for parameters: - * %eax *x - * %edx *y - */ -FUNCTION(grub_vbe_bios_get_display_start) - pushl %ebp - pushl %ebx - pushl %edi - pushl %eax /* Push *x to stack. */ - pushl %edx /* Push *y to stack. */ - - call prot_to_real - .code16 - - movw $0x4f07, %ax - movw $0x0001, %bx /* BL = 1, Get Display Start. */ - int $0x10 - - movw %ax, %bx /* real_to_prot destroys %eax. */ - - DATA32 call real_to_prot - .code32 - - popl %edi /* Pops *y from stack to %edi. */ - andl $0xFFFF, %edx - movl %edx, (%edi) /* Return y-position to caller. */ - - popl %edi /* Pops *x from stack to %edi. */ - andl $0xFFFF, %ecx - movl %ecx, (%edi) /* Return x-position to caller. */ - - movw %bx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edi - popl %ebx - popl %ebp - ret - -/* - * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count, - * grub_uint32_t start_index, - * struct grub_vbe_palette_data *palette_data) - * - * Register allocations for parameters: - * %eax color_count - * %edx start_index - * %ecx *palette_data - */ -FUNCTION(grub_vbe_bios_set_palette_data) - pushl %ebp - pushl %ebx - pushl %edi - - movl %eax, %ebx /* Store color_count in %ebx. */ - - movw %cx, %di /* Store *palette_data to %ecx:%di. */ - xorw %cx, %cx - shrl $4, %ecx - - call prot_to_real - .code16 - - pushw %es - - movw %cx, %es /* *palette_data is now on %es:%di. */ - movw %bx, %cx /* color_count is now on %cx. */ - - movw $0x4f09, %ax - xorw %bx, %bx /* BL = 0, Set Palette Data. */ - int $0x10 - - movw %ax, %dx /* real_to_prot destroys %eax. */ - - popw %es - - DATA32 call real_to_prot - .code32 - - movw %dx, %ax - andl $0xFFFF, %eax /* Return value in %eax. */ - - popl %edi - popl %ebx - popl %ebp - ret - - -pxe_rm_entry: - .long 0 - -/* - * struct grub_pxenv *grub_pxe_scan (void); - */ -FUNCTION(grub_pxe_scan) - pushl %ebp - pushl %ebx - - xorl %ebx, %ebx - xorl %ecx, %ecx - - call prot_to_real - .code16 - - pushw %es - - movw $0x5650, %ax - int $0x1A - cmpw $0x564E, %ax - jnz 1f - cmpl $0x4E455850, %es:(%bx) /* PXEN(V+) */ - jnz 1f - cmpw $0x201, %es:6(%bx) /* API version */ - jb 1f - lesw %es:0x28(%bx), %bx /* !PXE structure */ - cmpl $0x45585021, %es:(%bx) /* !PXE */ - jnz 1f - movw %es, %cx - jmp 2f -1: - xorw %bx, %bx - xorw %cx, %cx -2: - - popw %es - - DATA32 call real_to_prot - .code32 - - xorl %eax, %eax - leal (%eax, %ecx, 4), %ecx - leal (%ebx, %ecx, 4), %eax /* eax = ecx * 16 + ebx */ - - orl %eax, %eax - jz 1f - - movl 0x10(%eax), %ecx - movl %ecx, pxe_rm_entry - -1: - - popl %ebx - popl %ebp - ret - -/* - * int grub_pxe_call (int func, void* data); - */ -FUNCTION(grub_pxe_call) - pushl %ebp - movl %esp, %ebp - pushl %esi - pushl %edi - pushl %ebx - - movl %eax, %ecx - movl %edx, %eax - andl $0xF, %eax - shrl $4, %edx - shll $16, %edx - addl %eax, %edx - movl pxe_rm_entry, %ebx - - call prot_to_real - .code16 - - pushl %ebx - pushl %edx - pushw %cx - movw %sp, %bx - lcall *%ss:6(%bx) - cld - addw $10, %sp - movw %ax, %cx - - DATA32 call real_to_prot - .code32 - - movzwl %cx, %eax - - popl %ebx - popl %edi - popl %esi - popl %ebp - ret diff --git a/lib/crc.c b/lib/crc.c deleted file mode 100644 index bc0d8aa8d..000000000 --- a/lib/crc.c +++ /dev/null @@ -1,75 +0,0 @@ -/* crc.c - crc function */ -/* - * 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 - -static grub_uint32_t crc32_table [256]; - -static void -init_crc32_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 = 0x04c11db7; - int i, j; - - for(i = 0; i < 256; i++) - { - crc32_table[i] = reflect(i, 8) << 24; - for (j = 0; j < 8; j++) - crc32_table[i] = (crc32_table[i] << 1) ^ - (crc32_table[i] & (1 << 31) ? polynomial : 0); - crc32_table[i] = reflect(crc32_table[i], 32); - } -} - -grub_uint32_t -grub_getcrc32 (grub_uint32_t crc, void *buf, int size) -{ - int i; - grub_uint8_t *data = buf; - - if (! crc32_table[1]) - init_crc32_table (); - - crc^= 0xffffffff; - - for (i = 0; i < size; i++) - { - crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *data]; - data++; - } - - return crc ^ 0xffffffff; -} diff --git a/lib/i386/relocator.c b/lib/i386/relocator.c deleted file mode 100644 index 453f73fdd..000000000 --- a/lib/i386/relocator.c +++ /dev/null @@ -1,102 +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 - -extern grub_uint8_t grub_relocator32_forward_start; -extern grub_uint8_t grub_relocator32_forward_end; -extern grub_uint8_t grub_relocator32_backward_start; -extern grub_uint8_t grub_relocator32_backward_end; - -extern grub_uint32_t grub_relocator32_backward_dest; -extern grub_uint32_t grub_relocator32_backward_size; -extern grub_addr_t grub_relocator32_backward_src; - -extern grub_uint32_t grub_relocator32_forward_dest; -extern grub_uint32_t grub_relocator32_forward_size; -extern grub_addr_t grub_relocator32_forward_src; - -extern grub_uint32_t grub_relocator32_forward_eax; -extern grub_uint32_t grub_relocator32_forward_ebx; -extern grub_uint32_t grub_relocator32_forward_ecx; -extern grub_uint32_t grub_relocator32_forward_edx; -extern grub_uint32_t grub_relocator32_forward_eip; -extern grub_uint32_t grub_relocator32_forward_esp; - -extern grub_uint32_t grub_relocator32_backward_eax; -extern grub_uint32_t grub_relocator32_backward_ebx; -extern grub_uint32_t grub_relocator32_backward_ecx; -extern grub_uint32_t grub_relocator32_backward_edx; -extern grub_uint32_t grub_relocator32_backward_eip; -extern grub_uint32_t grub_relocator32_backward_esp; - -#define RELOCATOR_SIZEOF(x) (&grub_relocator32_##x##_end - &grub_relocator32_##x##_start) -#define RELOCATOR_ALIGN 16 -#define PREFIX(x) grub_relocator32_ ## x - -static void -write_call_relocator_bw (void *ptr, void *src, grub_uint32_t dest, - grub_size_t size, struct grub_relocator32_state state) -{ - grub_relocator32_backward_dest = dest; - grub_relocator32_backward_src = PTR_TO_UINT64 (src); - grub_relocator32_backward_size = size; - - grub_relocator32_backward_eax = state.eax; - grub_relocator32_backward_ebx = state.ebx; - grub_relocator32_backward_ecx = state.ecx; - grub_relocator32_backward_edx = state.edx; - grub_relocator32_backward_eip = state.eip; - grub_relocator32_backward_esp = state.esp; - - grub_memmove (ptr, - &grub_relocator32_backward_start, - RELOCATOR_SIZEOF (backward)); - ((void (*) (void)) ptr) (); -} - -static void -write_call_relocator_fw (void *ptr, void *src, grub_uint32_t dest, - grub_size_t size, struct grub_relocator32_state state) -{ - - grub_relocator32_forward_dest = dest; - grub_relocator32_forward_src = PTR_TO_UINT64 (src); - grub_relocator32_forward_size = size; - - grub_relocator32_forward_eax = state.eax; - grub_relocator32_forward_ebx = state.ebx; - grub_relocator32_forward_ecx = state.ecx; - grub_relocator32_forward_edx = state.edx; - grub_relocator32_forward_eip = state.eip; - grub_relocator32_forward_esp = state.esp; - - grub_memmove (ptr, - &grub_relocator32_forward_start, - RELOCATOR_SIZEOF (forward)); - ((void (*) (void)) ptr) (); -} - -#include "../relocator.c" diff --git a/lib/i386/relocator_asm.S b/lib/i386/relocator_asm.S deleted file mode 100644 index 22490a3f8..000000000 --- a/lib/i386/relocator_asm.S +++ /dev/null @@ -1,250 +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 - -#ifdef BACKWARD -#define RELOCATOR_VARIABLE(x) VARIABLE(grub_relocator32_backward_ ## x) -#else -#define RELOCATOR_VARIABLE(x) VARIABLE(grub_relocator32_forward_ ## x) -#endif -#ifdef __x86_64__ -#define RAX %rax -#define RCX %rcx -#define RDI %rdi -#define RSI %rdi -#else -#define RAX %eax -#define RCX %ecx -#define RDI %edi -#define RSI %esi -#endif - -/* The code segment of the protected mode. */ -#define CODE_SEGMENT 0x10 - -/* The data segment of the protected mode. */ -#define DATA_SEGMENT 0x18 - - .p2align 4 /* force 16-byte alignment */ - -RELOCATOR_VARIABLE(start) -#ifdef BACKWARD -LOCAL(base): -#endif - cli - -#ifndef __x86_64__ - /* mov imm32, %eax */ - .byte 0xb8 -RELOCATOR_VARIABLE(dest) - .long 0 - movl %eax, %edi - - /* mov imm32, %eax */ - .byte 0xb8 -RELOCATOR_VARIABLE(src) - .long 0 - movl %eax, %esi - - /* mov imm32, %ecx */ - .byte 0xb9 -RELOCATOR_VARIABLE(size) - .long 0 -#else - xorq %rax, %rax - - /* mov imm32, %eax */ - .byte 0xb8 -RELOCATOR_VARIABLE(dest) - .long 0 - movq %rax, %rdi - - /* mov imm64, %rax */ - .byte 0x48 - .byte 0xb8 -RELOCATOR_VARIABLE(src) - .long 0, 0 - movq %rax, %rsi - - xorq %rcx, %rcx - /* mov imm32, %ecx */ - .byte 0xb9 -RELOCATOR_VARIABLE(size) - .long 0 - -#endif - - mov RDI, RAX - -#ifdef BACKWARD - add RCX, RSI - add RCX, RDI -#endif - -#ifndef BACKWARD - add RCX, RAX -#endif - add $0x3, RCX - shr $2, RCX - - -#ifdef BACKWARD - /* Backward movsl is implicitly off-by-four. compensate that. */ - sub $4, RSI - sub $4, RDI - - /* Backward copy. */ - std - - rep - movsl - -#else - /* Forward copy. */ - cld - rep - movsl -#endif - - /* %rax contains now our new 'base'. */ - mov RAX, RSI - add $(LOCAL(cont0) - LOCAL(base)), RAX - jmp *RAX -LOCAL(cont0): - lea (LOCAL(cont1) - LOCAL(base)) (RSI, 1), RAX - movl %eax, (LOCAL(jump_vector) - LOCAL(base)) (RSI, 1) - - lea (LOCAL(gdt) - LOCAL(base)) (RSI, 1), RAX - mov RAX, (LOCAL(gdt_addr) - LOCAL(base)) (RSI, 1) - - /* Switch to compatibility mode. */ - - lgdt (LOCAL(gdtdesc) - LOCAL(base)) (RSI, 1) - - /* Update %cs. */ - ljmp *(LOCAL(jump_vector) - LOCAL(base)) (RSI, 1) - -LOCAL(cont1): - .code32 - - /* Update other registers. */ - movl $DATA_SEGMENT, %eax - movl %eax, %ds - movl %eax, %es - movl %eax, %fs - movl %eax, %gs - movl %eax, %ss - - /* Disable paging. */ - movl %cr0, %eax - andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax - movl %eax, %cr0 - -#ifdef __x86_64__ - /* Disable amd64. */ - movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx - rdmsr - andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax - wrmsr -#endif - - /* Turn off PAE. */ - movl %cr4, %eax - andl $GRUB_MEMORY_CPU_CR4_PAE_ON, %eax - movl %eax, %cr4 - - jmp LOCAL(cont2) -LOCAL(cont2): - .code32 - - /* mov imm32, %eax */ - .byte 0xb8 -RELOCATOR_VARIABLE (esp) - .long 0 - - movl %eax, %esp - - /* mov imm32, %eax */ - .byte 0xb8 -RELOCATOR_VARIABLE (eax) - .long 0 - - /* mov imm32, %ebx */ - .byte 0xbb -RELOCATOR_VARIABLE (ebx) - .long 0 - - /* mov imm32, %ecx */ - .byte 0xb9 -RELOCATOR_VARIABLE (ecx) - .long 0 - - /* mov imm32, %edx */ - .byte 0xba -RELOCATOR_VARIABLE (edx) - .long 0 - - /* Cleared direction flag is of no problem with any current - payload and makes this implementation easier. */ - cld - - .byte 0xea -RELOCATOR_VARIABLE (eip) - .long 0 - .word CODE_SEGMENT - - /* GDT. Copied from loader/i386/linux.c. */ - .p2align 4 -LOCAL(gdt): - /* NULL. */ - .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* Reserved. */ - .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* Code segment. */ - .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 - - /* Data segment. */ - .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 - - .p2align 4 -LOCAL(gdtdesc): - .word 0x27 -LOCAL(gdt_addr): -#ifdef __x86_64__ - /* Filled by the code. */ - .quad 0 -#else - /* Filled by the code. */ - .long 0 -#endif - - .p2align 4 -LOCAL(jump_vector): - /* Jump location. Is filled by the code */ - .long 0 - .long CODE_SEGMENT - -#ifndef BACKWARD -LOCAL(base): -#endif - -RELOCATOR_VARIABLE(end) diff --git a/lib/mips/relocator.c b/lib/mips/relocator.c deleted file mode 100644 index 118ddbd6f..000000000 --- a/lib/mips/relocator.c +++ /dev/null @@ -1,112 +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 - -#include - -/* Remark: doesn't work with source outside of 4G. - Use relocator64 in this case. - */ - -extern grub_uint8_t grub_relocator32_forward_start; -extern grub_uint8_t grub_relocator32_forward_end; -extern grub_uint8_t grub_relocator32_backward_start; -extern grub_uint8_t grub_relocator32_backward_end; - -#define REGW_SIZEOF (2 * sizeof (grub_uint32_t)) -#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t)) - -#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator32_##x##_end \ - - &grub_relocator32_##x##_start) -#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ - + REGW_SIZEOF * (31 + 3) + JUMP_SIZEOF) -#define RELOCATOR_ALIGN 16 - -#define PREFIX(x) grub_relocator32_ ## x - -static void -write_reg (int regn, grub_uint32_t val, void **target) -{ - /* lui $r, (val+0x8000). */ - *(grub_uint32_t *) *target = ((0x3c00 | regn) << 16) | ((val + 0x8000) >> 16); - *target = ((grub_uint32_t *) *target) + 1; - /* addiu $r, $r, val. */ - *(grub_uint32_t *) *target = (((0x2400 | regn << 5 | regn) << 16) - | (val & 0xffff)); - *target = ((grub_uint32_t *) *target) + 1; -} - -static void -write_jump (int regn, void **target) -{ - /* j $r. */ - *(grub_uint32_t *) *target = (regn<<21) | 0x8; - *target = ((grub_uint32_t *) *target) + 1; - /* nop. */ - *(grub_uint32_t *) *target = 0; - *target = ((grub_uint32_t *) *target) + 1; -} - -static void -write_call_relocator_bw (void *ptr0, void *src, grub_uint32_t dest, - grub_size_t size, struct grub_relocator32_state state) -{ - void *ptr = ptr0; - int i; - write_reg (8, (grub_uint32_t) src, &ptr); - write_reg (9, dest, &ptr); - write_reg (10, size, &ptr); - grub_memcpy (ptr, &grub_relocator32_backward_start, - RELOCATOR_SRC_SIZEOF (backward)); - ptr = (grub_uint8_t *) ptr + RELOCATOR_SRC_SIZEOF (backward); - for (i = 1; i < 32; i++) - write_reg (i, state.gpr[i], &ptr); - write_jump (state.jumpreg, &ptr); - grub_arch_sync_caches (ptr0, (grub_uint8_t *) ptr - (grub_uint8_t *) ptr0); - grub_dprintf ("relocator", "Backward relocator: about to jump to %p\n", ptr0); - ((void (*) (void)) ptr0) (); -} - -static void -write_call_relocator_fw (void *ptr0, void *src, grub_uint32_t dest, - grub_size_t size, struct grub_relocator32_state state) -{ - void *ptr = ptr0; - int i; - write_reg (8, (grub_uint32_t) src, &ptr); - write_reg (9, dest, &ptr); - write_reg (10, size, &ptr); - grub_memcpy (ptr, &grub_relocator32_forward_start, - RELOCATOR_SRC_SIZEOF (forward)); - ptr = (grub_uint8_t *) ptr + RELOCATOR_SRC_SIZEOF (forward); - for (i = 1; i < 32; i++) - write_reg (i, state.gpr[i], &ptr); - write_jump (state.jumpreg, &ptr); - grub_arch_sync_caches (ptr0, (grub_uint8_t *) ptr - (grub_uint8_t *) ptr0); - grub_dprintf ("relocator", "Forward relocator: about to jump to %p\n", ptr0); - ((void (*) (void)) ptr0) (); -} - -#include "../relocator.c" diff --git a/lib/relocator.c b/lib/relocator.c deleted file mode 100644 index 6a5acc548..000000000 --- a/lib/relocator.c +++ /dev/null @@ -1,137 +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 . - */ - -#define MAX_OVERHEAD ((RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) \ - + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN) \ - + (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) \ - + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN)) -#define PRE_REGION_SIZE (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN) - -void * -PREFIX (alloc) (grub_size_t size) -{ - char *playground; - - playground = grub_malloc (size + MAX_OVERHEAD); - if (!playground) - return 0; - - *(grub_size_t *) playground = size; - - return playground + PRE_REGION_SIZE; -} - -void * -PREFIX (realloc) (void *relocator, grub_size_t size) -{ - char *playground; - - if (!relocator) - return PREFIX (alloc) (size); - - playground = (char *) relocator - PRE_REGION_SIZE; - - playground = grub_realloc (playground, size + MAX_OVERHEAD); - if (!playground) - return 0; - - *(grub_size_t *) playground = size; - - return playground + PRE_REGION_SIZE; -} - -void -PREFIX(free) (void *relocator) -{ - if (relocator) - grub_free ((char *) relocator - PRE_REGION_SIZE); -} - -grub_err_t -PREFIX (boot) (void *relocator, grub_uint32_t dest, - struct grub_relocator32_state state) -{ - grub_size_t size; - char *playground; - - playground = (char *) relocator - PRE_REGION_SIZE; - size = *(grub_size_t *) playground; - - grub_dprintf ("relocator", - "Relocator: source: %p, destination: 0x%x, size: 0x%lx\n", - relocator, (unsigned) dest, (unsigned long) size); - - /* Very unlikely condition: Relocator may risk overwrite itself. - Just move it a bit up. */ - if ((grub_addr_t) dest < (grub_addr_t) relocator - + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN) - && (grub_addr_t) dest + (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) - > (grub_addr_t) relocator) - { - void *relocator_new = ((grub_uint8_t *) relocator) - + (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) - + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN); - grub_dprintf ("relocator", "Overwrite condition detected moving " - "relocator from %p to %p\n", relocator, relocator_new); - grub_memmove (relocator_new, relocator, - (RELOCATOR_SIZEOF (forward) + RELOCATOR_ALIGN) - + size - + (RELOCATOR_SIZEOF (backward) + RELOCATOR_ALIGN)); - relocator = relocator_new; - } - - if ((grub_addr_t) dest >= (grub_addr_t) relocator) - { - int overhead; - overhead = dest - - ALIGN_UP (dest - RELOCATOR_SIZEOF (backward) - RELOCATOR_ALIGN, - RELOCATOR_ALIGN); - grub_dprintf ("relocator", - "Backward relocator: code %p, source: %p, " - "destination: 0x%x, size: 0x%lx\n", - (char *) relocator - overhead, - (char *) relocator - overhead, - (unsigned) dest - overhead, - (unsigned long) size + overhead); - - write_call_relocator_bw ((char *) relocator - overhead, - (char *) relocator - overhead, - dest - overhead, size + overhead, state); - } - else - { - int overhead; - - overhead = ALIGN_UP (dest + size, RELOCATOR_ALIGN) - + RELOCATOR_SIZEOF (forward) - (dest + size); - grub_dprintf ("relocator", - "Forward relocator: code %p, source: %p, " - "destination: 0x%x, size: 0x%lx\n", - (char *) relocator + size + overhead - - RELOCATOR_SIZEOF (forward), - relocator, (unsigned) dest, - (unsigned long) size + overhead); - - write_call_relocator_fw ((char *) relocator + size + overhead - - RELOCATOR_SIZEOF (forward), - relocator, dest, size + overhead, state); - } - - /* Not reached. */ - return GRUB_ERR_NONE; -} diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c deleted file mode 100644 index 3c7fe2fee..000000000 --- a/loader/i386/bsd.c +++ /dev/null @@ -1,1326 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef GRUB_MACHINE_PCBIOS -#include -#endif -#include -#include -#include - -#define ALIGN_DWORD(a) ALIGN_UP (a, 4) -#define ALIGN_QWORD(a) ALIGN_UP (a, 8) -#define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a))) -#define ALIGN_PAGE(a) ALIGN_UP (a, 4096) - -#define MOD_BUF_ALLOC_UNIT 4096 - -static int kernel_type = KERNEL_TYPE_NONE; -static grub_dl_t my_mod; -static grub_addr_t entry, entry_hi, kern_start, kern_end; -static grub_uint32_t bootflags; -static char *mod_buf; -static grub_uint32_t mod_buf_len, mod_buf_max, kern_end_mdofs; -static int is_elf_kernel, is_64bit; -static char *netbsd_root = NULL; -static grub_uint32_t openbsd_root; - -static const struct grub_arg_option freebsd_opts[] = - { - {"dual", 'D', 0, N_("Display output on all consoles."), 0, 0}, - {"serial", 'h', 0, N_("Use serial console."), 0, 0}, - {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0}, - {"cdrom", 'C', 0, N_("Use CDROM as root."), 0, 0}, - {"config", 'c', 0, N_("Invoke user configuration routing."), 0, 0}, - {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, - {"gdb", 'g', 0, N_("Use GDB remote debugger instead of DDB."), 0, 0}, - {"mute", 'm', 0, N_("Disable all boot output."), 0, 0}, - {"nointr", 'n', 0, "", 0, 0}, - {"pause", 'p', 0, N_("Wait for keypress after every line of output."), 0, 0}, - {"quiet", 'q', 0, "", 0, 0}, - {"dfltroot", 'r', 0, N_("Use compiled-in rootdev."), 0, 0}, - {"single", 's', 0, N_("Boot into single mode."), 0, 0}, - {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0}, - {0, 0, 0, 0, 0, 0} - }; - -static const grub_uint32_t freebsd_flags[] = -{ - FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME, - FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB, - FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR, - FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT, - FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE, 0 -}; - -static const struct grub_arg_option openbsd_opts[] = - { - {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0}, - {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0}, - {"config", 'c', 0, N_("Change configured devices."), 0, 0}, - {"single", 's', 0, N_("Boot into single mode."), 0, 0}, - {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, - {"root", 'r', 0, N_("Set root device."), "wdXY", ARG_TYPE_STRING}, - {0, 0, 0, 0, 0, 0} - }; - -static const grub_uint32_t openbsd_flags[] = -{ - OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG, - OPENBSD_RB_SINGLE, OPENBSD_RB_KDB, 0 -}; - -#define OPENBSD_ROOT_ARG (ARRAY_SIZE (openbsd_flags) - 1) - -static const struct grub_arg_option netbsd_opts[] = - { - {"no-smp", '1', 0, N_("Disable SMP."), 0, 0}, - {"no-acpi", '2', 0, N_("Disable ACPI."), 0, 0}, - {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0}, - {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0}, - {"config", 'c', 0, N_("Change configured devices."), 0, 0}, - {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, - {"miniroot", 'm', 0, "", 0, 0}, - {"quiet", 'q', 0, N_("Don't display boot diagnostic messages."), 0, 0}, - {"single", 's', 0, N_("Boot into single mode."), 0, 0}, - {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0}, - {"debug", 'x', 0, N_("Boot with debug messages."), 0, 0}, - {"silent", 'z', 0, N_("Supress normal output (warnings remain)."), 0, 0}, - {"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING}, - {0, 0, 0, 0, 0, 0} - }; - -static const grub_uint32_t netbsd_flags[] = -{ - NETBSD_AB_NOSMP, NETBSD_AB_NOACPI, NETBSD_RB_ASKNAME, - NETBSD_RB_HALT, NETBSD_RB_USERCONFIG, NETBSD_RB_KDB, - NETBSD_RB_MINIROOT, NETBSD_AB_QUIET, NETBSD_RB_SINGLE, - NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG, NETBSD_AB_SILENT, 0 -}; - -#define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1) - -static void -grub_bsd_get_device (grub_uint32_t * biosdev, - grub_uint32_t * unit, - grub_uint32_t * slice, grub_uint32_t * part) -{ - grub_device_t dev; - -#ifdef GRUB_MACHINE_PCBIOS - *biosdev = grub_get_root_biosnumber () & 0xff; -#else - *biosdev = 0xff; -#endif - *unit = (*biosdev & 0x7f); - *slice = 0xff; - *part = 0xff; - dev = grub_device_open (0); - if (dev && dev->disk && dev->disk->partition) - { - if (dev->disk->partition->parent) - { - *part = dev->disk->partition->number; - *slice = dev->disk->partition->parent->number + 1; - } - else - *slice = dev->disk->partition->number + 1; - } - if (dev) - grub_device_close (dev); -} - -grub_err_t -grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len) -{ - if (mod_buf_max < mod_buf_len + len + 8) - { - char *new_buf; - - do - { - mod_buf_max += MOD_BUF_ALLOC_UNIT; - } - while (mod_buf_max < mod_buf_len + len + 8); - - new_buf = grub_malloc (mod_buf_max); - if (!new_buf) - return grub_errno; - - grub_memcpy (new_buf, mod_buf, mod_buf_len); - grub_free (mod_buf); - - mod_buf = new_buf; - } - - *((grub_uint32_t *) (mod_buf + mod_buf_len)) = type; - *((grub_uint32_t *) (mod_buf + mod_buf_len + 4)) = len; - mod_buf_len += 8; - - if (len) - grub_memcpy (mod_buf + mod_buf_len, data, len); - - mod_buf_len = ALIGN_VAR (mod_buf_len + len); - - return GRUB_ERR_NONE; -} - -struct grub_e820_mmap -{ - grub_uint64_t addr; - grub_uint64_t size; - grub_uint32_t type; -} __attribute__((packed)); -#define GRUB_E820_RAM 1 -#define GRUB_E820_RESERVED 2 -#define GRUB_E820_ACPI 3 -#define GRUB_E820_NVS 4 -#define GRUB_E820_EXEC_CODE 5 - -static grub_err_t -grub_freebsd_add_mmap (void) -{ - grub_size_t len = 0; - struct grub_e820_mmap *mmap_buf = 0; - struct grub_e820_mmap *mmap = 0; - int isfirstrun = 1; - - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) - { - /* FreeBSD assumes that first 64KiB are available. - Not always true but try to prevent panic somehow. */ - if (isfirstrun && addr != 0) - { - if (mmap) - { - mmap->addr = 0; - mmap->size = (addr < 0x10000) ? addr : 0x10000; - mmap->type = GRUB_E820_RAM; - mmap++; - } - else - len += sizeof (struct grub_e820_mmap); - } - isfirstrun = 0; - if (mmap) - { - mmap->addr = addr; - mmap->size = size; - switch (type) - { - case GRUB_MACHINE_MEMORY_AVAILABLE: - mmap->type = GRUB_E820_RAM; - break; - -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: - mmap->type = GRUB_E820_ACPI; - break; -#endif - -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: - mmap->type = GRUB_E820_NVS; - break; -#endif - - default: -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: -#endif -#ifdef GRUB_MACHINE_MEMORY_RESERVED - case GRUB_MACHINE_MEMORY_RESERVED: -#endif - mmap->type = GRUB_E820_RESERVED; - break; - } - - /* Merge regions if possible. */ - if (mmap != mmap_buf && mmap->type == mmap[-1].type && - mmap->addr == mmap[-1].addr + mmap[-1].size) - mmap[-1].size += mmap->size; - else - mmap++; - } - else - len += sizeof (struct grub_e820_mmap); - - return 0; - } - - grub_mmap_iterate (hook); - mmap_buf = mmap = grub_malloc (len); - if (! mmap) - return grub_errno; - - isfirstrun = 1; - grub_mmap_iterate (hook); - - len = (mmap - mmap_buf) * sizeof (struct grub_e820_mmap); - int i; - for (i = 0; i < mmap - mmap_buf; i++) - grub_dprintf ("bsd", "smap %d, %d:%llx - %llx\n", i, - mmap_buf[i].type, - (unsigned long long) mmap_buf[i].addr, - (unsigned long long) mmap_buf[i].size); - - grub_dprintf ("bsd", "%d entries in smap\n", mmap - mmap_buf); - grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_SMAP, mmap_buf, len); - - grub_free (mmap_buf); - - return grub_errno; -} - -grub_err_t -grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv, - grub_addr_t addr, grub_uint32_t size) -{ - char *name; - name = grub_strrchr (filename, '/'); - if (name) - name++; - else - name = filename; - if (grub_strcmp (type, "/boot/zfs/zpool.cache") == 0) - name = "/boot/zfs/zpool.cache"; - - if (grub_freebsd_add_meta (FREEBSD_MODINFO_NAME, name, - grub_strlen (name) + 1)) - return grub_errno; - - if (is_64bit) - { - grub_uint64_t addr64 = addr, size64 = size; - if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type, - grub_strlen (type) + 1)) || - (grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64, - sizeof (addr64))) || - (grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size64, - sizeof (size64)))) - return grub_errno; - } - else - { - if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type, - grub_strlen (type) + 1)) || - (grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, - sizeof (addr))) || - (grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size, - sizeof (size)))) - return grub_errno; - } - - if (argc) - { - int i, n; - - n = 0; - for (i = 0; i < argc; i++) - { - n += grub_strlen (argv[i]) + 1; - } - - if (n) - { - char cmdline[n], *p; - - p = cmdline; - for (i = 0; i < argc; i++) - { - grub_strcpy (p, argv[i]); - p += grub_strlen (argv[i]); - *(p++) = ' '; - } - *p = 0; - - if (grub_freebsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n)) - return grub_errno; - } - } - - return GRUB_ERR_NONE; -} - -static void -grub_freebsd_list_modules (void) -{ - grub_uint32_t pos = 0; - - grub_printf (" %-18s %-18s%14s%14s\n", "name", "type", "addr", "size"); - while (pos < mod_buf_len) - { - grub_uint32_t type, size; - - type = *((grub_uint32_t *) (mod_buf + pos)); - size = *((grub_uint32_t *) (mod_buf + pos + 4)); - pos += 8; - switch (type) - { - case FREEBSD_MODINFO_NAME: - case FREEBSD_MODINFO_TYPE: - grub_printf (" %-18s", mod_buf + pos); - break; - case FREEBSD_MODINFO_ADDR: - { - grub_addr_t addr; - - addr = *((grub_addr_t *) (mod_buf + pos)); - grub_printf (" 0x%08x", addr); - break; - } - case FREEBSD_MODINFO_SIZE: - { - grub_uint32_t len; - - len = *((grub_uint32_t *) (mod_buf + pos)); - grub_printf (" 0x%08x\n", len); - } - } - - pos = ALIGN_VAR (pos + size); - } -} - -/* This function would be here but it's under different license. */ -#include "bsd_pagetable.c" - -struct gdt_descriptor -{ - grub_uint16_t limit; - void *base; -} __attribute__ ((packed)); - -static grub_err_t -grub_freebsd_boot (void) -{ - struct grub_freebsd_bootinfo bi; - char *p; - grub_uint32_t bootdev, biosdev, unit, slice, part; - - auto int iterate_env (struct grub_env_var *var); - int iterate_env (struct grub_env_var *var) - { - if ((!grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1)) && (var->name[sizeof("kFreeBSD.") - 1])) - { - grub_strcpy (p, &var->name[sizeof("kFreeBSD.") - 1]); - p += grub_strlen (p); - *(p++) = '='; - grub_strcpy (p, var->value); - p += grub_strlen (p) + 1; - } - - return 0; - } - - grub_memset (&bi, 0, sizeof (bi)); - bi.version = FREEBSD_BOOTINFO_VERSION; - bi.length = sizeof (bi); - - grub_bsd_get_device (&biosdev, &unit, &slice, &part); - bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) + - (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT)); - - bi.boot_device = biosdev; - - p = (char *) kern_end; - - grub_env_iterate (iterate_env); - - if (p != (char *) kern_end) - { - *(p++) = 0; - - bi.environment = kern_end; - kern_end = ALIGN_PAGE ((grub_uint32_t) p); - } - - if (is_elf_kernel) - { - grub_addr_t md_ofs; - int ofs; - - if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0)) - return grub_errno; - - grub_memcpy ((char *) kern_end, mod_buf, mod_buf_len); - bi.tags = kern_end; - - kern_end = ALIGN_PAGE (kern_end + mod_buf_len); - - if (is_64bit) - kern_end += 4096 * 4; - - md_ofs = bi.tags + kern_end_mdofs; - ofs = (is_64bit) ? 16 : 12; - *((grub_uint32_t *) md_ofs) = kern_end; - md_ofs -= ofs; - *((grub_uint32_t *) md_ofs) = bi.environment; - md_ofs -= ofs; - *((grub_uint32_t *) md_ofs) = bootflags; - } - - bi.kern_end = kern_end; - - grub_video_set_mode ("text", 0, 0); - - if (is_64bit) - { - grub_uint32_t *gdt; - grub_uint8_t *trampoline; - void (*launch_trampoline) (grub_addr_t entry_lo, ...) - __attribute__ ((cdecl, regparm (0))); - grub_uint8_t *pagetable; - - struct gdt_descriptor *gdtdesc; - - pagetable = (grub_uint8_t *) (kern_end - 16384); - fill_bsd64_pagetable (pagetable); - - /* Create GDT. */ - gdt = (grub_uint32_t *) (kern_end - 4096); - gdt[0] = 0; - gdt[1] = 0; - gdt[2] = 0; - gdt[3] = 0x00209800; - gdt[4] = 0; - gdt[5] = 0x00008000; - - /* Create GDT descriptor. */ - gdtdesc = (struct gdt_descriptor *) (kern_end - 4096 + 24); - gdtdesc->limit = 24; - gdtdesc->base = gdt; - - /* Prepare trampoline. */ - trampoline = (grub_uint8_t *) (kern_end - 4096 + 24 - + sizeof (struct gdt_descriptor)); - launch_trampoline = (void __attribute__ ((cdecl, regparm (0))) - (*) (grub_addr_t entry_lo, ...)) trampoline; - grub_bsd64_trampoline_gdt = (grub_uint32_t) gdtdesc; - grub_bsd64_trampoline_selfjump - = (grub_uint32_t) (trampoline + 6 - + ((grub_uint8_t *) &grub_bsd64_trampoline_selfjump - - &grub_bsd64_trampoline_start)); - - /* Copy trampoline. */ - grub_memcpy (trampoline, &grub_bsd64_trampoline_start, - &grub_bsd64_trampoline_end - &grub_bsd64_trampoline_start); - - /* Launch trampoline. */ - launch_trampoline (entry, entry_hi, pagetable, bi.tags, - kern_end); - } - else - grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev, - 0, 0, 0, &bi, bi.tags, kern_end); - - /* Not reached. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_openbsd_boot (void) -{ - char *buf = (char *) GRUB_BSD_TEMP_BUFFER; - struct grub_openbsd_bios_mmap *pm; - struct grub_openbsd_bootargs *pa; - - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) - { - pm->addr = addr; - pm->len = size; - - switch (type) - { - case GRUB_MACHINE_MEMORY_AVAILABLE: - pm->type = OPENBSD_MMAP_AVAILABLE; - break; - - case GRUB_MACHINE_MEMORY_ACPI: - pm->type = OPENBSD_MMAP_ACPI; - break; - - case GRUB_MACHINE_MEMORY_NVS: - pm->type = OPENBSD_MMAP_NVS; - break; - - default: - pm->type = OPENBSD_MMAP_RESERVED; - break; - } - pm++; - - return 0; - } - - pa = (struct grub_openbsd_bootargs *) buf; - - pa->ba_type = OPENBSD_BOOTARG_MMAP; - pm = (struct grub_openbsd_bios_mmap *) (pa + 1); - grub_mmap_iterate (hook); - - /* Memory map terminator. */ - pm->addr = 0; - pm->len = 0; - pm->type = 0; - pm++; - - pa->ba_size = (char *) pm - (char *) pa; - pa->ba_next = (struct grub_openbsd_bootargs *) pm; - pa = pa->ba_next; - pa->ba_type = OPENBSD_BOOTARG_END; - pa++; - - grub_video_set_mode ("text", 0, 0); - - grub_unix_real_boot (entry, bootflags, openbsd_root, OPENBSD_BOOTARG_APIVER, - 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), - (grub_uint32_t) (grub_mmap_get_lower () >> 10), - (char *) pa - buf, buf); - - /* Not reached. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_netbsd_boot (void) -{ - struct grub_netbsd_bootinfo *bootinfo; - int count = 0; - struct grub_netbsd_btinfo_mmap_header *mmap; - struct grub_netbsd_btinfo_mmap_entry *pm; - void *curarg; - - auto int NESTED_FUNC_ATTR count_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) - { - count++; - return 0; - } - - auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) - { - pm->addr = addr; - pm->len = size; - - switch (type) - { - case GRUB_MACHINE_MEMORY_AVAILABLE: - pm->type = NETBSD_MMAP_AVAILABLE; - break; - - case GRUB_MACHINE_MEMORY_ACPI: - pm->type = NETBSD_MMAP_ACPI; - break; - - case GRUB_MACHINE_MEMORY_NVS: - pm->type = NETBSD_MMAP_NVS; - break; - - default: - pm->type = NETBSD_MMAP_RESERVED; - break; - } - pm++; - - return 0; - } - - grub_mmap_iterate (count_hook); - - if (kern_end + sizeof (struct grub_netbsd_btinfo_rootdevice) - + sizeof (struct grub_netbsd_bootinfo) - + sizeof (struct grub_netbsd_btinfo_mmap_header) - + count * sizeof (struct grub_netbsd_btinfo_mmap_entry) - > grub_os_area_addr + grub_os_area_size) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); - - curarg = mmap = (struct grub_netbsd_btinfo_mmap_header *) kern_end; - pm = (struct grub_netbsd_btinfo_mmap_entry *) (mmap + 1); - - grub_mmap_iterate (fill_hook); - mmap->common.type = NETBSD_BTINFO_MEMMAP; - mmap->common.len = (char *) pm - (char *) mmap; - mmap->count = count; - curarg = pm; - - if (netbsd_root) - { - struct grub_netbsd_btinfo_rootdevice *rootdev; - - rootdev = (struct grub_netbsd_btinfo_rootdevice *) curarg; - - rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice); - rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE; - grub_strncpy (rootdev->devname, netbsd_root, sizeof (rootdev->devname)); - - bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1); - bootinfo->bi_count = 2; - bootinfo->bi_data[0] = mmap; - bootinfo->bi_data[1] = rootdev; - } - else - { - bootinfo = (struct grub_netbsd_bootinfo *) curarg; - bootinfo->bi_count = 1; - bootinfo->bi_data[0] = mmap; - } - - grub_video_set_mode ("text", 0, 0); - - grub_unix_real_boot (entry, bootflags, 0, bootinfo, - 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), - (grub_uint32_t) (grub_mmap_get_lower () >> 10)); - - /* Not reached. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_bsd_unload (void) -{ - if (mod_buf) - { - grub_free (mod_buf); - mod_buf = 0; - mod_buf_max = 0; - } - - kernel_type = KERNEL_TYPE_NONE; - grub_dl_unref (my_mod); - - grub_free (netbsd_root); - netbsd_root = NULL; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_bsd_load_aout (grub_file_t file) -{ - grub_addr_t load_addr, bss_end_addr; - int ofs, align_page; - union grub_aout_header ah; - - if ((grub_file_seek (file, 0)) == (grub_off_t) - 1) - return grub_errno; - - if (grub_file_read (file, &ah, sizeof (ah)) != sizeof (ah)) - return grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header"); - - if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32) - return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header"); - - entry = ah.aout32.a_entry & 0xFFFFFF; - - if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC) - { - load_addr = entry; - ofs = 0x1000; - align_page = 0; - } - else - { - load_addr = entry & 0xF00000; - ofs = sizeof (struct grub_aout32_header); - align_page = 1; - } - - if (load_addr < 0x100000) - return grub_error (GRUB_ERR_BAD_OS, "load address below 1M"); - - kern_start = load_addr; - kern_end = load_addr + ah.aout32.a_text + ah.aout32.a_data; - if (align_page) - kern_end = ALIGN_PAGE (kern_end); - - if (ah.aout32.a_bss) - { - kern_end += ah.aout32.a_bss; - if (align_page) - kern_end = ALIGN_PAGE (kern_end); - - bss_end_addr = kern_end; - } - else - bss_end_addr = 0; - - return grub_aout_load (file, ofs, load_addr, - ah.aout32.a_text + ah.aout32.a_data, bss_end_addr); -} - -static grub_err_t -grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load) -{ - Elf32_Addr paddr; - - if (phdr->p_type != PT_LOAD - && phdr->p_type != PT_DYNAMIC) - { - *do_load = 0; - return 0; - } - - *do_load = 1; - phdr->p_paddr &= 0xFFFFFF; - paddr = phdr->p_paddr; - - if ((paddr < grub_os_area_addr) - || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "address 0x%x is out of range", - paddr); - - if ((!kern_start) || (paddr < kern_start)) - kern_start = paddr; - - if (paddr + phdr->p_memsz > kern_end) - kern_end = paddr + phdr->p_memsz; - - *addr = paddr; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_bsd_elf64_hook (Elf64_Phdr * phdr, grub_addr_t * addr, int *do_load) -{ - Elf64_Addr paddr; - - if (phdr->p_type != PT_LOAD - && phdr->p_type != PT_DYNAMIC) - { - *do_load = 0; - return 0; - } - - *do_load = 1; - paddr = phdr->p_paddr & 0xffffff; - - if ((paddr < grub_os_area_addr) - || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "address 0x%x is out of range", - paddr); - - if ((!kern_start) || (paddr < kern_start)) - kern_start = paddr; - - if (paddr + phdr->p_memsz > kern_end) - kern_end = paddr + phdr->p_memsz; - - *addr = paddr; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_bsd_load_elf (grub_elf_t elf) -{ - kern_start = kern_end = 0; - - if (grub_elf_is_elf32 (elf)) - { - entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; - return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0); - } - else if (grub_elf_is_elf64 (elf)) - { - is_64bit = 1; - - if (! grub_cpuid_has_longmode) - return grub_error (GRUB_ERR_BAD_OS, "your CPU does not implement AMD64 architecture"); - - /* FreeBSD has 64-bit entry point. */ - if (kernel_type == KERNEL_TYPE_FREEBSD) - { - entry = elf->ehdr.ehdr64.e_entry & 0xffffffff; - entry_hi = (elf->ehdr.ehdr64.e_entry >> 32) & 0xffffffff; - } - else - { - entry = elf->ehdr.ehdr64.e_entry & 0x0fffffff; - entry_hi = 0; - } - return grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0); - } - else - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); -} - -static grub_err_t -grub_bsd_load (int argc, char *argv[]) -{ - grub_file_t file; - grub_elf_t elf; - - grub_dl_ref (my_mod); - - grub_loader_unset (); - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); - goto fail; - } - - file = grub_gzfile_open (argv[0], 1); - if (!file) - goto fail; - - elf = grub_elf_file (file); - if (elf) - { - is_elf_kernel = 1; - grub_bsd_load_elf (elf); - grub_elf_close (elf); - } - else - { - is_elf_kernel = 0; - grub_errno = 0; - grub_bsd_load_aout (file); - grub_file_close (file); - } - -fail: - - if (grub_errno != GRUB_ERR_NONE) - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_uint32_t -grub_bsd_parse_flags (const struct grub_arg_list *state, - const grub_uint32_t * flags) -{ - grub_uint32_t result = 0; - unsigned i; - - for (i = 0; flags[i]; i++) - if (state[i].set) - result |= flags[i]; - - return result; -} - -static grub_err_t -grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[]) -{ - kernel_type = KERNEL_TYPE_FREEBSD; - bootflags = grub_bsd_parse_flags (cmd->state, freebsd_flags); - - if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) - { - kern_end = ALIGN_PAGE (kern_end); - if (is_elf_kernel) - { - grub_err_t err; - grub_uint64_t data = 0; - grub_file_t file; - int len = is_64bit ? 8 : 4; - - err = grub_freebsd_add_meta_module (argv[0], is_64bit - ? FREEBSD_MODTYPE_KERNEL64 - : FREEBSD_MODTYPE_KERNEL, - argc - 1, argv + 1, - kern_start, - kern_end - kern_start); - if (err) - return err; - - file = grub_gzfile_open (argv[0], 1); - if (! file) - return grub_errno; - - if (is_64bit) - err = grub_freebsd_load_elf_meta64 (file, &kern_end); - else - err = grub_freebsd_load_elf_meta32 (file, &kern_end); - if (err) - return err; - - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_HOWTO, &data, 4); - if (err) - return err; - - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_ENVP, &data, len); - if (err) - return err; - - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_KERNEND, &data, len); - if (err) - return err; - - kern_end_mdofs = mod_buf_len - len; - - err = grub_freebsd_add_mmap (); - if (err) - return err; - } - grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1); - } - - return grub_errno; -} - -static grub_err_t -grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[]) -{ - grub_uint32_t bootdev; - - kernel_type = KERNEL_TYPE_OPENBSD; - bootflags = grub_bsd_parse_flags (cmd->state, openbsd_flags); - - if (cmd->state[OPENBSD_ROOT_ARG].set) - { - const char *arg = cmd->state[OPENBSD_ROOT_ARG].arg; - int unit, part; - if (*(arg++) != 'w' || *(arg++) != 'd') - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only device specifications of form " - "wd are supported"); - - unit = grub_strtoul (arg, (char **) &arg, 10); - if (! (arg && *arg >= 'a' && *arg <= 'z')) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only device specifications of form " - "wd are supported"); - - part = *arg - 'a'; - - bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) + - (part << OPENBSD_B_PARTSHIFT)); - } - else - bootdev = 0; - - if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) - { - grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1); - openbsd_root = bootdev; - } - - return grub_errno; -} - -static grub_err_t -grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[]) -{ - kernel_type = KERNEL_TYPE_NETBSD; - bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags); - - if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) - { - grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1); - if (cmd->state[NETBSD_ROOT_ARG].set) - netbsd_root = grub_strdup (cmd->state[NETBSD_ROOT_ARG].arg); - } - - return grub_errno; -} - -static grub_err_t -grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - char *buf = 0, *curr, *next; - int len; - - if (kernel_type == KERNEL_TYPE_NONE) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you need to load the kernel first"); - - if (kernel_type != KERNEL_TYPE_FREEBSD) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only FreeBSD supports environment"); - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename"); - goto fail; - } - - file = grub_gzfile_open (argv[0], 1); - if ((!file) || (!file->size)) - goto fail; - - len = file->size; - buf = grub_malloc (len + 1); - if (!buf) - goto fail; - - if (grub_file_read (file, buf, len) != len) - goto fail; - - buf[len] = 0; - - next = buf; - while (next) - { - char *p; - - curr = next; - next = grub_strchr (curr, '\n'); - if (next) - { - - p = next - 1; - while (p > curr) - { - if ((*p != '\r') && (*p != ' ') && (*p != '\t')) - break; - p--; - } - - if ((p > curr) && (*p == '"')) - p--; - - *(p + 1) = 0; - next++; - } - - if (*curr == '#') - continue; - - p = grub_strchr (curr, '='); - if (!p) - continue; - - *(p++) = 0; - - if (*curr) - { - char *name; - - if (*p == '"') - p++; - - name = grub_xasprintf ("kFreeBSD.%s", curr); - if (!name) - goto fail; - if (grub_env_set (name, p)) - { - grub_free (name); - goto fail; - } - grub_free (name); - } - } - -fail: - grub_free (buf); - - if (file) - grub_file_close (file); - - return grub_errno; -} - -static grub_err_t -grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - grub_err_t err; - int modargc; - char **modargv; - char *type; - - if (kernel_type == KERNEL_TYPE_NONE) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you need to load the kernel first"); - - if (kernel_type != KERNEL_TYPE_FREEBSD) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only FreeBSD supports module"); - - if (!is_elf_kernel) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only ELF kernel supports module"); - - /* List the current modules if no parameter. */ - if (!argc) - { - grub_freebsd_list_modules (); - return 0; - } - - file = grub_gzfile_open (argv[0], 1); - if ((!file) || (!file->size)) - goto fail; - - if (kern_end + file->size > grub_os_area_addr + grub_os_area_size) - { - grub_error (GRUB_ERR_OUT_OF_RANGE, "not enough memory for the module"); - goto fail; - } - - grub_file_read (file, (void *) kern_end, file->size); - if (grub_errno) - goto fail; - - modargc = argc - 1; - modargv = argv + 1; - - if (modargc && (! grub_memcmp (modargv[0], "type=", 5))) - { - type = &modargv[0][5]; - modargc--; - modargv++; - } - else - type = FREEBSD_MODTYPE_RAW; - - err = grub_freebsd_add_meta_module (argv[0], type, modargc, modargv, - kern_end, file->size); - if (err) - goto fail; - - kern_end = ALIGN_PAGE (kern_end + file->size); - -fail: - if (file) - grub_file_close (file); - - return grub_errno; -} - -static grub_err_t -grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - grub_err_t err; - - if (kernel_type == KERNEL_TYPE_NONE) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you need to load the kernel first"); - - if (kernel_type != KERNEL_TYPE_FREEBSD) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only FreeBSD supports module"); - - if (! is_elf_kernel) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "only ELF kernel supports module"); - - /* List the current modules if no parameter. */ - if (! argc) - { - grub_freebsd_list_modules (); - return 0; - } - - file = grub_gzfile_open (argv[0], 1); - if (!file) - return grub_errno; - if (!file->size) - { - grub_file_close (file); - return grub_errno; - } - - if (is_64bit) - err = grub_freebsd_load_elfmodule_obj64 (file, argc, argv, &kern_end); - else - err = grub_freebsd_load_elfmodule32 (file, argc, argv, &kern_end); - grub_file_close (file); - - return err; -} - - -static grub_extcmd_t cmd_freebsd, cmd_openbsd, cmd_netbsd; -static grub_command_t cmd_freebsd_loadenv, cmd_freebsd_module; -static grub_command_t cmd_freebsd_module_elf; - -GRUB_MOD_INIT (bsd) -{ - cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, - GRUB_COMMAND_FLAG_BOTH, - N_("FILE"), N_("Load kernel of FreeBSD."), - freebsd_opts); - cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, - GRUB_COMMAND_FLAG_BOTH, - N_("FILE"), N_("Load kernel of OpenBSD."), - openbsd_opts); - cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, - GRUB_COMMAND_FLAG_BOTH, - N_("FILE"), N_("Load kernel of NetBSD."), - netbsd_opts); - cmd_freebsd_loadenv = - grub_register_command ("kfreebsd_loadenv", grub_cmd_freebsd_loadenv, - 0, N_("Load FreeBSD env.")); - cmd_freebsd_module = - grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module, - 0, N_("Load FreeBSD kernel module.")); - cmd_freebsd_module_elf = - grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf, - 0, N_("Load FreeBSD kernel module (ELF).")); - - my_mod = mod; -} - -GRUB_MOD_FINI (bsd) -{ - grub_unregister_extcmd (cmd_freebsd); - grub_unregister_extcmd (cmd_openbsd); - grub_unregister_extcmd (cmd_netbsd); - - grub_unregister_command (cmd_freebsd_loadenv); - grub_unregister_command (cmd_freebsd_module); - grub_unregister_command (cmd_freebsd_module_elf); - - if (mod_buf) - { - grub_free (mod_buf); - mod_buf = 0; - mod_buf_max = 0; - } -} diff --git a/loader/i386/bsdXX.c b/loader/i386/bsdXX.c deleted file mode 100644 index cd5ba85dc..000000000 --- a/loader/i386/bsdXX.c +++ /dev/null @@ -1,329 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define ALIGN_PAGE(a) ALIGN_UP (a, 4096) - -static inline grub_err_t -load (grub_file_t file, void *where, grub_off_t off, grub_size_t size) -{ - if (PTR_TO_UINT32 (where) + size > grub_os_area_addr + grub_os_area_size) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "not enough memory for the module"); - if (grub_file_seek (file, off) == (grub_off_t) -1) - return grub_errno; - if (grub_file_read (file, where, size) - != (grub_ssize_t) size) - { - if (grub_errno) - return grub_errno; - else - return grub_error (GRUB_ERR_BAD_OS, "file is truncated"); - } - return GRUB_ERR_NONE; -} - -static inline grub_err_t -read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr) -{ - if (grub_file_seek (file, 0) == (grub_off_t) -1) - return grub_errno; - - if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e)) - { - if (grub_errno) - return grub_errno; - else - return grub_error (GRUB_ERR_BAD_OS, "file is too short"); - } - - if (e->e_ident[EI_MAG0] != ELFMAG0 - || e->e_ident[EI_MAG1] != ELFMAG1 - || e->e_ident[EI_MAG2] != ELFMAG2 - || e->e_ident[EI_MAG3] != ELFMAG3 - || e->e_ident[EI_VERSION] != EV_CURRENT - || e->e_version != EV_CURRENT) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic"); - - if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS)) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch dependent ELF magic"); - - *shdr = grub_malloc (e->e_shnum * e->e_shentsize); - if (! *shdr) - return grub_errno; - - if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1) - return grub_errno; - - if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize) - != e->e_shnum * e->e_shentsize) - { - if (grub_errno) - return grub_errno; - else - return grub_error (GRUB_ERR_BAD_OS, "file is truncated"); - } - - return GRUB_ERR_NONE; -} - -/* On i386 FreeBSD uses "elf module" approarch for 32-bit variant - and "elf obj module" for 64-bit variant. However it may differ on other - platforms. So I keep both versions. */ -#if OBJSYM -grub_err_t -SUFFIX (grub_freebsd_load_elfmodule_obj) (grub_file_t file, int argc, - char *argv[], grub_addr_t *kern_end) -{ - Elf_Ehdr e; - Elf_Shdr *s; - char *shdr = 0; - grub_addr_t curload, module; - grub_err_t err; - - err = read_headers (file, &e, &shdr); - if (err) - return err; - - curload = module = ALIGN_PAGE (*kern_end); - - for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr - + e.e_shnum * e.e_shentsize); - s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) - { - if (s->sh_size == 0) - continue; - - if (s->sh_addralign) - curload = ALIGN_UP (curload, s->sh_addralign); - s->sh_addr = curload; - - grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", - (unsigned) curload, (int) s->sh_size, - (int) s->sh_addralign); - - switch (s->sh_type) - { - default: - case SHT_PROGBITS: - err = load (file, UINT_TO_PTR (curload), s->sh_offset, s->sh_size); - if (err) - return err; - break; - case SHT_NOBITS: - if (curload + s->sh_size > grub_os_area_addr + grub_os_area_size) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "not enough memory for the module"); - grub_memset (UINT_TO_PTR (curload), 0, s->sh_size); - break; - } - curload += s->sh_size; - } - - *kern_end = ALIGN_PAGE (curload); - - err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ, - argc - 1, argv + 1, module, - curload - module); - if (! err) - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA - | FREEBSD_MODINFOMD_ELFHDR, - &e, sizeof (e)); - if (! err) - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA - | FREEBSD_MODINFOMD_SHDR, - shdr, e.e_shnum * e.e_shentsize); - - return err; -} - -#else - -grub_err_t -SUFFIX (grub_freebsd_load_elfmodule) (grub_file_t file, int argc, char *argv[], - grub_addr_t *kern_end) -{ - Elf_Ehdr e; - Elf_Shdr *s; - char *shdr = 0; - grub_addr_t curload, module; - grub_err_t err; - - err = read_headers (file, &e, &shdr); - if (err) - return err; - - curload = module = ALIGN_PAGE (*kern_end); - - for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr - + e.e_shnum * e.e_shentsize); - s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) - { - if (s->sh_size == 0) - continue; - - if (! (s->sh_flags & SHF_ALLOC)) - continue; - - grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n", - (unsigned) curload, (int) s->sh_size, - (int) s->sh_addralign); - - switch (s->sh_type) - { - default: - case SHT_PROGBITS: - err = load (file, UINT_TO_PTR (module + s->sh_addr), - s->sh_offset, s->sh_size); - if (err) - return err; - break; - case SHT_NOBITS: - if (module + s->sh_addr + s->sh_size - > grub_os_area_addr + grub_os_area_size) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "not enough memory for the module"); - grub_memset (UINT_TO_PTR (module + s->sh_addr), 0, s->sh_size); - break; - } - if (curload < module + s->sh_addr + s->sh_size) - curload = module + s->sh_addr + s->sh_size; - } - - load (file, UINT_TO_PTR (module), 0, sizeof (e)); - if (curload < module + sizeof (e)) - curload = module + sizeof (e); - - load (file, UINT_TO_PTR (curload), e.e_shoff, - e.e_shnum * e.e_shentsize); - e.e_shoff = curload - module; - curload += e.e_shnum * e.e_shentsize; - - load (file, UINT_TO_PTR (curload), e.e_phoff, - e.e_phnum * e.e_phentsize); - e.e_phoff = curload - module; - curload += e.e_phnum * e.e_phentsize; - - *kern_end = curload; - - grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, - argc - 1, argv + 1, module, - curload - module); - return SUFFIX (grub_freebsd_load_elf_meta) (file, kern_end); -} - -#endif - -grub_err_t -SUFFIX (grub_freebsd_load_elf_meta) (grub_file_t file, grub_addr_t *kern_end) -{ - grub_err_t err; - Elf_Ehdr e; - Elf_Shdr *s; - char *shdr = 0; - unsigned symoff, stroff, symsize, strsize; - grub_addr_t curload; - grub_freebsd_addr_t symstart, symend, symentsize, dynamic; - Elf_Sym *sym; - const char *str; - unsigned i; - - err = read_headers (file, &e, &shdr); - if (err) - return err; - - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_ELFHDR, &e, - sizeof (e)); - if (err) - return err; - - for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr - + e.e_shnum * e.e_shentsize); - s = (Elf_Shdr *) ((char *) s + e.e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; - if (s >= (Elf_Shdr *) ((char *) shdr - + e.e_shnum * e.e_shentsize)) - return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); - symoff = s->sh_offset; - symsize = s->sh_size; - symentsize = s->sh_entsize; - s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link); - stroff = s->sh_offset; - strsize = s->sh_size; - - if (*kern_end + 4 * sizeof (grub_freebsd_addr_t) + symsize + strsize - > grub_os_area_addr + grub_os_area_size) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "not enough memory for kernel symbols"); - - symstart = curload = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); - *((grub_freebsd_addr_t *) UINT_TO_PTR (curload)) = symsize; - curload += sizeof (grub_freebsd_addr_t); - if (grub_file_seek (file, symoff) == (grub_off_t) -1) - return grub_errno; - sym = (Elf_Sym *) UINT_TO_PTR (curload); - if (grub_file_read (file, UINT_TO_PTR (curload), symsize) != - (grub_ssize_t) symsize) - { - if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); - return grub_errno; - } - curload += symsize; - - *((grub_freebsd_addr_t *) UINT_TO_PTR (curload)) = strsize; - curload += sizeof (grub_freebsd_addr_t); - if (grub_file_seek (file, stroff) == (grub_off_t) -1) - return grub_errno; - str = (char *) UINT_TO_PTR (curload); - if (grub_file_read (file, UINT_TO_PTR (curload), strsize) - != (grub_ssize_t) strsize) - { - if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); - return grub_errno; - } - curload += strsize; - curload = ALIGN_UP (curload, sizeof (grub_freebsd_addr_t)); - symend = curload; - - for (i = 0; - i * symentsize < symsize; - i++, sym = (Elf_Sym *) ((char *) sym + symentsize)) - { - const char *name = str + sym->st_name; - if (grub_strcmp (name, "_DYNAMIC") == 0) - break; - } - - if (i * symentsize < symsize) - { - dynamic = sym->st_value; - grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic); - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_DYNAMIC, &dynamic, - sizeof (dynamic)); - if (err) - return err; - } - - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_SSYM, &symstart, - sizeof (symstart)); - if (err) - return err; - - err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | - FREEBSD_MODINFOMD_ESYM, &symend, - sizeof (symend)); - if (err) - return err; - *kern_end = ALIGN_PAGE (curload); - - return GRUB_ERR_NONE; -} diff --git a/loader/i386/bsd_helper.S b/loader/i386/bsd_helper.S deleted file mode 100644 index 25aee3a80..000000000 --- a/loader/i386/bsd_helper.S +++ /dev/null @@ -1,45 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,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 - * 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 - - .p2align 2 - - - .code32 - -/* - * Use cdecl calling convention for *BSD kernels. - */ - -FUNCTION(grub_unix_real_boot) - - /* Interrupts should be disabled. */ - cli - - /* Discard `grub_unix_real_boot' return address. */ - popl %eax - - /* Fetch `entry' address ... */ - popl %eax - - /* - * ... and put our return address in its place. The kernel will - * ignore it, but it expects %esp to point to it. - */ - call *%eax diff --git a/loader/i386/bsd_trampoline.S b/loader/i386/bsd_trampoline.S deleted file mode 100644 index a568fff4d..000000000 --- a/loader/i386/bsd_trampoline.S +++ /dev/null @@ -1,124 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (c) 2003 Peter Wemm - * 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 . - */ - -/* Based on the code from FreeBSD originally distributed under the - following terms: */ - -/*- - * Copyright (c) 2003 Peter Wemm - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 AUTHOR 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 AUTHOR 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. - * - * $FreeBSD$ - */ - - -#define MSR_EFER 0xc0000080 -#define EFER_LME 0x00000100 -#define CR4_PAE 0x00000020 -#define CR4_PSE 0x00000010 -#define CR0_PG 0x80000000 - -#include - - .p2align 2 - - .code32 - - -VARIABLE(grub_bsd64_trampoline_start) - - /* Discard `grub_unix_real_boot' return address. */ - popl %eax - - /* entry */ - popl %edi - - /* entry_hi */ - popl %esi - - cli - - /* Turn on EFER.LME. */ - movl $MSR_EFER, %ecx - rdmsr - orl $EFER_LME, %eax - wrmsr - - /* Turn on PAE. */ - movl %cr4, %eax - orl $(CR4_PAE | CR4_PSE), %eax - movl %eax, %cr4 - - /* Set %cr3 for PT4. */ - popl %eax - movl %eax, %cr3 - - /* Push a dummy return address. */ - pushl %eax - - /* Turn on paging (implicitly sets EFER.LMA). */ - movl %cr0, %eax - orl $CR0_PG, %eax - movl %eax, %cr0 - - /* Now we're in compatibility mode. set %cs for long mode. */ - /* lgdt */ - .byte 0x0f - .byte 0x01 - .byte 0x15 -VARIABLE (grub_bsd64_trampoline_gdt) - .long 0x0 - - /* ljmp */ - .byte 0xea -VARIABLE (grub_bsd64_trampoline_selfjump) - .long 0x0 - .word 0x08 - - .code64 - -bsd64_longmode: - /* We're still running V=P, jump to entry point. */ - movl %esi, %eax - salq $32, %rax - orq %rdi, %rax - pushq %rax - ret -VARIABLE(grub_bsd64_trampoline_end) diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c deleted file mode 100644 index d37feb983..000000000 --- a/loader/i386/efi/linux.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GRUB_LINUX_CL_OFFSET 0x1000 -#define GRUB_LINUX_CL_END_OFFSET 0x2000 - -#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ - ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) - -static grub_dl_t my_mod; - -static grub_size_t linux_mem_size; -static int loaded; -static void *real_mode_mem; -static void *prot_mode_mem; -static void *initrd_mem; -static grub_efi_uintn_t real_mode_pages; -static grub_efi_uintn_t prot_mode_pages; -static grub_efi_uintn_t initrd_pages; -static void *mmap_buf; - -static grub_uint8_t gdt[] __attribute__ ((aligned(16))) = - { - /* NULL. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Reserved. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Code segment. */ - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, - /* Data segment. */ - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 - }; - -struct gdt_descriptor -{ - grub_uint16_t limit; - void *base; -} __attribute__ ((packed)); - -static struct gdt_descriptor gdt_desc = - { - sizeof (gdt) - 1, - gdt - }; - -struct idt_descriptor -{ - grub_uint16_t limit; - void *base; -} __attribute__ ((packed)); - -static struct idt_descriptor idt_desc = - { - 0, - 0 - }; - -static inline grub_size_t -page_align (grub_size_t size) -{ - return (size + (1 << 12) - 1) & (~((1 << 12) - 1)); -} - -/* Find the optimal number of pages for the memory map. Is it better to - move this code to efi/mm.c? */ -static grub_efi_uintn_t -find_mmap_size (void) -{ - static grub_efi_uintn_t mmap_size = 0; - - if (mmap_size != 0) - return mmap_size; - - mmap_size = (1 << 12); - while (1) - { - int ret; - grub_efi_memory_descriptor_t *mmap; - grub_efi_uintn_t desc_size; - - mmap = grub_malloc (mmap_size); - if (! mmap) - return 0; - - ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); - grub_free (mmap); - - if (ret < 0) - grub_fatal ("cannot get memory map"); - else if (ret > 0) - break; - - mmap_size += (1 << 12); - } - - /* Increase the size a bit for safety, because GRUB allocates more on - later, and EFI itself may allocate more. */ - mmap_size += (1 << 12); - - return page_align (mmap_size); -} - -static void -free_pages (void) -{ - if (real_mode_mem) - { - grub_efi_free_pages ((grub_addr_t) real_mode_mem, real_mode_pages); - real_mode_mem = 0; - } - - if (prot_mode_mem) - { - grub_efi_free_pages ((grub_addr_t) prot_mode_mem, prot_mode_pages); - prot_mode_mem = 0; - } - - if (initrd_mem) - { - grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); - initrd_mem = 0; - } -} - -/* Allocate pages for the real mode code and the protected mode code - for linux as well as a memory map buffer. */ -static int -allocate_pages (grub_size_t prot_size) -{ - grub_efi_uintn_t desc_size; - grub_efi_memory_descriptor_t *mmap, *mmap_end; - grub_efi_uintn_t mmap_size, tmp_mmap_size; - grub_efi_memory_descriptor_t *desc; - grub_size_t real_size; - - /* Make sure that each size is aligned to a page boundary. */ - real_size = GRUB_LINUX_CL_END_OFFSET; - prot_size = page_align (prot_size); - mmap_size = find_mmap_size (); - - grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n", - (unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size); - - /* Calculate the number of pages; Combine the real mode code with - the memory map buffer for simplicity. */ - real_mode_pages = ((real_size + mmap_size) >> 12); - prot_mode_pages = (prot_size >> 12); - - /* Initialize the memory pointers with NULL for convenience. */ - real_mode_mem = 0; - prot_mode_mem = 0; - - /* Read the memory map temporarily, to find free space. */ - mmap = grub_malloc (mmap_size); - if (! mmap) - return 0; - - tmp_mmap_size = mmap_size; - if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0) - grub_fatal ("cannot get memory map"); - - mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size); - - /* First, find free pages for the real mode code - and the memory map buffer. */ - for (desc = mmap; - desc < mmap_end; - desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) - { - /* Probably it is better to put the real mode code in the traditional - space for safety. */ - if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY - && desc->physical_start <= 0x90000 - && desc->num_pages >= real_mode_pages) - { - grub_efi_physical_address_t physical_end; - grub_efi_physical_address_t addr; - - physical_end = desc->physical_start + (desc->num_pages << 12); - if (physical_end > 0x90000) - physical_end = 0x90000; - - grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n", - (unsigned) desc->physical_start, - (unsigned) physical_end); - addr = physical_end - real_size - mmap_size; - if (addr < 0x10000) - continue; - - grub_dprintf ("linux", "trying to allocate %u pages at %lx\n", - (unsigned) real_mode_pages, (unsigned long) addr); - real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages); - if (! real_mode_mem) - grub_fatal ("cannot allocate pages"); - - desc->num_pages -= real_mode_pages; - break; - } - } - - if (! real_mode_mem) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); - goto fail; - } - - mmap_buf = (void *) ((char *) real_mode_mem + real_size); - - /* Next, find free pages for the protected mode code. */ - /* XXX what happens if anything is using this address? */ - prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages + 1); - if (! prot_mode_mem) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, - "cannot allocate protected mode pages"); - goto fail; - } - - grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, " - "prot_mode_mem = %lx, prot_mode_pages = %x\n", - (unsigned long) real_mode_mem, (unsigned) real_mode_pages, - (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages); - - grub_free (mmap); - return 1; - - fail: - grub_free (mmap); - free_pages (); - return 0; -} - -static void -grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num, - grub_uint64_t start, grub_uint64_t size, - grub_uint32_t type) -{ - int n = *e820_num; - - if (n >= GRUB_E820_MAX_ENTRY) - grub_fatal ("Too many e820 memory map entries"); - - if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) && - (e820_map[n - 1].type == type)) - e820_map[n - 1].size += size; - else - { - e820_map[n].addr = start; - e820_map[n].size = size; - e820_map[n].type = type; - (*e820_num)++; - } -} - -static grub_err_t -grub_linux_setup_video (struct linux_kernel_params *params) -{ - struct grub_video_mode_info mode_info; - void *framebuffer; - grub_err_t err; - - err = grub_video_get_info_and_fini (&mode_info, &framebuffer); - - if (err) - return err; - - params->lfb_width = mode_info.width; - params->lfb_height = mode_info.height; - params->lfb_depth = mode_info.bpp; - params->lfb_line_len = mode_info.pitch; - - params->lfb_base = (grub_size_t) framebuffer; - params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, - 65536); - - params->red_mask_size = mode_info.red_mask_size; - params->red_field_pos = mode_info.red_field_pos; - params->green_mask_size = mode_info.green_mask_size; - params->green_field_pos = mode_info.green_field_pos; - params->blue_mask_size = mode_info.blue_mask_size; - params->blue_field_pos = mode_info.blue_field_pos; - params->reserved_mask_size = mode_info.reserved_mask_size; - params->reserved_field_pos = mode_info.reserved_field_pos; - - params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; - -#ifdef GRUB_MACHINE_PCBIOS - /* VESA packed modes may come with zeroed mask sizes, which need - to be set here according to DAC Palette width. If we don't, - this results in Linux displaying a black screen. */ - if (mode_info.bpp <= 8) - { - struct grub_vbe_info_block controller_info; - int status; - int width = 8; - - status = grub_vbe_bios_get_controller_info (&controller_info); - - if (status == GRUB_VBE_STATUS_OK && - (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH)) - status = grub_vbe_bios_set_dac_palette_width (&width); - - if (status != GRUB_VBE_STATUS_OK) - /* 6 is default after mode reset. */ - width = 6; - - params->red_mask_size = params->green_mask_size - = params->blue_mask_size = width; - params->reserved_mask_size = 0; - } -#endif - - return 0; -} - -#ifdef __x86_64__ -extern grub_uint8_t grub_linux_trampoline_start[]; -extern grub_uint8_t grub_linux_trampoline_end[]; -#endif - -static grub_err_t -grub_linux_boot (void) -{ - struct linux_kernel_params *params; - grub_efi_uintn_t mmap_size; - grub_efi_uintn_t map_key; - grub_efi_uintn_t desc_size; - grub_efi_uint32_t desc_version; - int e820_num; - const char *modevar; - char *tmp; - grub_err_t err; - - params = real_mode_mem; - - grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n", - (unsigned) params->code32_start, - (unsigned long) &(idt_desc.limit), - (unsigned long) &(gdt_desc.limit)); - grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n", - (unsigned) idt_desc.limit, (unsigned long) idt_desc.base, - (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base); - - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) - { - switch (type) - { - case GRUB_MACHINE_MEMORY_AVAILABLE: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_RAM); - break; - -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_ACPI); - break; -#endif - -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_NVS); - break; -#endif - -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_EXEC_CODE); - break; -#endif - - default: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_RESERVED); - } - return 0; - } - - e820_num = 0; - grub_mmap_iterate (hook); - params->mmap_size = e820_num; - - grub_dprintf ("linux", "Trampoline at %p. code32=%x, real_mode_mem=%p\n", - ((char *) prot_mode_mem + (prot_mode_pages << 12)), - (unsigned) params->code32_start, real_mode_mem); - - modevar = grub_env_get ("gfxpayload"); - - /* Now all graphical modes are acceptable. - May change in future if we have modes without framebuffer. */ - if (modevar && *modevar != 0) - { - tmp = grub_xasprintf ("%s;auto", modevar); - if (! tmp) - return grub_errno; - err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); - grub_free (tmp); - } - else - err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); - - if (!err) - err = grub_linux_setup_video (params); - - if (err) - { - grub_print_error (); - grub_printf ("Booting however\n"); - grub_errno = GRUB_ERR_NONE; - } - - mmap_size = find_mmap_size (); - if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, - &desc_size, &desc_version) <= 0) - grub_fatal ("cannot get memory map"); - - if (! grub_efi_exit_boot_services (map_key)) - grub_fatal ("cannot exit boot services"); - - /* Note that no boot services are available from here. */ - - /* Pass EFI parameters. */ - if (grub_le_to_cpu16 (params->version) >= 0x0206) - { - params->v0206.efi_mem_desc_size = desc_size; - params->v0206.efi_mem_desc_version = desc_version; - params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf; - params->v0206.efi_mmap_size = mmap_size; -#ifdef __x86_64__ - params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32); -#endif - } - else if (grub_le_to_cpu16 (params->version) >= 0x0204) - { - params->v0204.efi_mem_desc_size = desc_size; - params->v0204.efi_mem_desc_version = desc_version; - params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf; - params->v0204.efi_mmap_size = mmap_size; - } - -#ifdef __x86_64__ - - grub_memcpy ((char *) prot_mode_mem + (prot_mode_pages << 12), - grub_linux_trampoline_start, - grub_linux_trampoline_end - grub_linux_trampoline_start); - - ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem - + (prot_mode_pages << 12))) - (params->code32_start, real_mode_mem); - -#else - - /* Hardware interrupts are not safe any longer. */ - asm volatile ("cli" : : ); - - /* Load the IDT and the GDT for the bootstrap. */ - asm volatile ("lidt %0" : : "m" (idt_desc)); - asm volatile ("lgdt %0" : : "m" (gdt_desc)); - - /* Pass parameters. */ - asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start)); - asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem)); - - asm volatile ("xorl %%ebx, %%ebx" : : ); - - /* Enter Linux. */ - asm volatile ("jmp *%%ecx" : : ); - -#endif - - /* Never reach here. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_linux_unload (void) -{ - free_pages (); - grub_dl_unref (my_mod); - loaded = 0; - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - struct linux_kernel_header lh; - struct linux_kernel_params *params; - grub_uint8_t setup_sects; - grub_size_t real_size, prot_size; - grub_ssize_t len; - int i; - char *dest; - - grub_dl_ref (my_mod); - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); - goto fail; - } - - file = grub_file_open (argv[0]); - if (! file) - goto fail; - - if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) - { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); - goto fail; - } - - if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) - { - grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); - goto fail; - } - - if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) - { - grub_error (GRUB_ERR_BAD_OS, "too many setup sectors"); - goto fail; - } - - /* EFI support is quite new, so reject old versions. */ - if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) - || grub_le_to_cpu16 (lh.version) < 0x0203) - { - grub_error (GRUB_ERR_BAD_OS, "too old version"); - goto fail; - } - - /* I'm not sure how to support zImage on EFI. */ - if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL)) - { - grub_error (GRUB_ERR_BAD_OS, "zImage is not supported"); - goto fail; - } - - setup_sects = lh.setup_sects; - - /* If SETUP_SECTS is not set, set it to the default (4). */ - if (! setup_sects) - setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS; - - real_size = setup_sects << GRUB_DISK_SECTOR_BITS; - prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; - - if (! allocate_pages (prot_size)) - goto fail; - - params = (struct linux_kernel_params *) real_mode_mem; - grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET); - grub_memcpy (¶ms->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1); - - params->ps_mouse = params->padding10 = 0; - - len = 0x400 - sizeof (lh); - if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len) - { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; - } - - params->type_of_loader = (LINUX_LOADER_ID_GRUB << 4); - - params->cl_magic = GRUB_LINUX_CL_MAGIC; - params->cl_offset = 0x1000; - params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000; - params->ramdisk_image = 0; - params->ramdisk_size = 0; - - params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET; - params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP; - - /* These are not needed to be precise, because Linux uses these values - only to raise an error when the decompression code cannot find good - space. */ - params->ext_mem = ((32 * 0x100000) >> 10); - params->alt_mem = ((32 * 0x100000) >> 10); - - { - grub_term_output_t term; - int found = 0; - FOR_ACTIVE_TERM_OUTPUTS(term) - if (grub_strcmp (term->name, "vga_text") == 0 - || grub_strcmp (term->name, "console") == 0) - { - grub_uint16_t pos = grub_term_getxy (term); - params->video_cursor_x = pos >> 8; - params->video_cursor_y = pos & 0xff; - params->video_width = grub_term_width (term); - params->video_height = grub_term_height (term); - found = 1; - break; - } - if (!found) - { - params->video_cursor_x = 0; - params->video_cursor_y = 0; - params->video_width = 80; - params->video_height = 25; - } - } - params->video_page = 0; /* ??? */ - params->video_mode = grub_efi_system_table->con_out->mode->mode; - params->video_ega_bx = 0; - params->have_vga = 0; - params->font_size = 16; /* XXX */ - - if (grub_le_to_cpu16 (params->version) >= 0x0206) - { - params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE; - params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table; -#ifdef __x86_64__ - params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32); -#endif - } - else if (grub_le_to_cpu16 (params->version) >= 0x0204) - { - params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204; - params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table; - } - -#if 0 - /* The structure is zeroed already. */ - - /* No VBE on EFI. */ - params->lfb_width = 0; - params->lfb_height = 0; - params->lfb_depth = 0; - params->lfb_base = 0; - params->lfb_size = 0; - params->lfb_line_len = 0; - params->red_mask_size = 0; - params->red_field_pos = 0; - params->green_mask_size = 0; - params->green_field_pos = 0; - params->blue_mask_size = 0; - params->blue_field_pos = 0; - params->reserved_mask_size = 0; - params->reserved_field_pos = 0; - params->vesapm_segment = 0; - params->vesapm_offset = 0; - params->lfb_pages = 0; - params->vesa_attrib = 0; - - /* No APM on EFI. */ - params->apm_version = 0; - params->apm_code_segment = 0; - params->apm_entry = 0; - params->apm_16bit_code_segment = 0; - params->apm_data_segment = 0; - params->apm_flags = 0; - params->apm_code_len = 0; - params->apm_data_len = 0; - - /* XXX is there any way to use SpeedStep on EFI? */ - params->ist_signature = 0; - params->ist_command = 0; - params->ist_event = 0; - params->ist_perf_level = 0; - - /* Let the kernel probe the information. */ - grub_memset (params->hd0_drive_info, 0, sizeof (params->hd0_drive_info)); - grub_memset (params->hd1_drive_info, 0, sizeof (params->hd1_drive_info)); - - /* No MCA on EFI. */ - params->rom_config_len = 0; - - /* No need to fake the BIOS's memory map. */ - params->mmap_size = 0; - - /* Let the kernel probe the information. */ - params->ps_mouse = 0; - - /* Clear padding for future compatibility. */ - grub_memset (params->padding1, 0, sizeof (params->padding1)); - grub_memset (params->padding2, 0, sizeof (params->padding2)); - grub_memset (params->padding3, 0, sizeof (params->padding3)); - grub_memset (params->padding4, 0, sizeof (params->padding4)); - grub_memset (params->padding5, 0, sizeof (params->padding5)); - grub_memset (params->padding6, 0, sizeof (params->padding6)); - grub_memset (params->padding7, 0, sizeof (params->padding7)); - grub_memset (params->padding8, 0, sizeof (params->padding8)); - grub_memset (params->padding9, 0, sizeof (params->padding9)); - -#endif - - /* The other EFI parameters are filled when booting. */ - - grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); - - /* XXX there is no way to know if the kernel really supports EFI. */ - grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n", - (unsigned) real_size, (unsigned) prot_size); - - /* Detect explicitly specified memory size, if any. */ - linux_mem_size = 0; - for (i = 1; i < argc; i++) - if (grub_memcmp (argv[i], "mem=", 4) == 0) - { - char *val = argv[i] + 4; - - linux_mem_size = grub_strtoul (val, &val, 0); - - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - linux_mem_size = 0; - } - else - { - int shift = 0; - - switch (grub_tolower (val[0])) - { - case 'g': - shift += 10; - case 'm': - shift += 10; - case 'k': - shift += 10; - default: - break; - } - - /* Check an overflow. */ - if (linux_mem_size > (~0UL >> shift)) - linux_mem_size = 0; - else - linux_mem_size <<= shift; - } - } - else if (grub_memcmp (argv[i], "video=efifb", 11) == 0) - { - if (params->have_vga) - params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; - } - - /* Specify the boot file. */ - dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET, - "BOOT_IMAGE="); - dest = grub_stpcpy (dest, argv[0]); - - /* Copy kernel parameters. */ - for (i = 1; - i < argc - && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem - + GRUB_LINUX_CL_END_OFFSET); - i++) - { - *dest++ = ' '; - dest = grub_stpcpy (dest, argv[i]); - } - - len = prot_size; - if (grub_file_read (file, (void *) GRUB_LINUX_BZIMAGE_ADDR, len) != len) - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - - if (grub_errno == GRUB_ERR_NONE) - { - grub_loader_set (grub_linux_boot, grub_linux_unload, 0); - loaded = 1; - } - - fail: - - if (file) - grub_file_close (file); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_dl_unref (my_mod); - loaded = 0; - } - - return grub_errno; -} - -static grub_err_t -grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - grub_ssize_t size; - grub_addr_t addr_min, addr_max; - grub_addr_t addr; - grub_efi_uintn_t mmap_size; - grub_efi_memory_descriptor_t *desc; - grub_efi_uintn_t desc_size; - struct linux_kernel_header *lh; - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); - goto fail; - } - - if (! loaded) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first"); - goto fail; - } - - file = grub_file_open (argv[0]); - if (! file) - goto fail; - - size = grub_file_size (file); - initrd_pages = (page_align (size) >> 12); - - lh = (struct linux_kernel_header *) real_mode_mem; - - addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10); - if (linux_mem_size != 0 && linux_mem_size < addr_max) - addr_max = linux_mem_size; - - /* Linux 2.3.xx has a bug in the memory range check, so avoid - the last page. - Linux 2.2.xx has a bug in the memory range check, which is - worse than that of Linux 2.3.xx, so avoid the last 64kb. */ - addr_max -= 0x10000; - - /* Usually, the compression ratio is about 50%. */ - addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12) - + page_align (size); - - /* Find the highest address to put the initrd. */ - mmap_size = find_mmap_size (); - if (grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0) - grub_fatal ("cannot get memory map"); - - addr = 0; - for (desc = mmap_buf; - desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); - desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) - { - if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY - && desc->num_pages >= initrd_pages) - { - grub_efi_physical_address_t physical_end; - - physical_end = desc->physical_start + (desc->num_pages << 12); - if (physical_end > addr_max) - physical_end = addr_max; - - if (physical_end < page_align (size)) - continue; - - physical_end -= page_align (size); - - if ((physical_end >= addr_min) && - (physical_end >= desc->physical_start) && - (physical_end > addr)) - addr = physical_end; - } - } - - if (addr == 0) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free pages available"); - goto fail; - } - - initrd_mem = grub_efi_allocate_pages (addr, initrd_pages); - if (! initrd_mem) - grub_fatal ("cannot allocate pages"); - - if (grub_file_read (file, initrd_mem, size) != size) - { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; - } - - grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n", - (unsigned) addr, (unsigned) size); - - lh->ramdisk_image = addr; - lh->ramdisk_size = size; - lh->root_dev = 0x0100; /* XXX */ - - fail: - if (file) - grub_file_close (file); - - return grub_errno; -} - -static grub_command_t cmd_linux, cmd_initrd; - -GRUB_MOD_INIT(linux) -{ - cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, N_("Load Linux.")); - cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, N_("Load initrd.")); - my_mod = mod; -} - -GRUB_MOD_FINI(linux) -{ - grub_unregister_command (cmd_linux); - grub_unregister_command (cmd_initrd); -} diff --git a/loader/i386/ieee1275/linux.c b/loader/i386/ieee1275/linux.c deleted file mode 100644 index 9f7556ffa..000000000 --- a/loader/i386/ieee1275/linux.c +++ /dev/null @@ -1,311 +0,0 @@ -/* linux.c - boot Linux zImage or bzImage */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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 -#include -#include -#include -#include -#include -#include -#include - -#define GRUB_OFW_LINUX_PARAMS_ADDR 0x90000 -#define GRUB_OFW_LINUX_KERNEL_ADDR 0x100000 -#define GRUB_OFW_LINUX_INITRD_ADDR 0x800000 - -#define GRUB_OFW_LINUX_CL_OFFSET 0x1e00 -#define GRUB_OFW_LINUX_CL_LENGTH 0x100 - -static grub_dl_t my_mod; - -static grub_size_t kernel_size; -static char *kernel_addr, *kernel_cmdline; -static grub_size_t initrd_size; - -static grub_err_t -grub_linux_unload (void) -{ - grub_free (kernel_cmdline); - grub_free (kernel_addr); - kernel_cmdline = 0; - kernel_addr = 0; - initrd_size = 0; - - grub_dl_unref (my_mod); - - return GRUB_ERR_NONE; -} - -/* -static int -grub_ieee1275_debug (void) -{ - struct enter_args - { - struct grub_ieee1275_common_hdr common; - } - args; - - INIT_IEEE1275_COMMON (&args.common, "enter", 0, 0); - - if (IEEE1275_CALL_ENTRY_FN (&args) == -1) - return -1; - - return 0; -} -*/ - -static grub_err_t -grub_linux_boot (void) -{ - struct linux_kernel_params *params; - struct linux_kernel_header *lh; - char *prot_code; - char *bootpath; - grub_ssize_t len; - - bootpath = grub_env_get ("root"); - if (bootpath) - grub_ieee1275_set_property (grub_ieee1275_chosen, - "bootpath", bootpath, - grub_strlen (bootpath) + 1, - &len); - - params = (struct linux_kernel_params *) GRUB_OFW_LINUX_PARAMS_ADDR; - lh = (struct linux_kernel_header *) params; - - grub_memset ((char *) params, 0, GRUB_OFW_LINUX_CL_OFFSET); - - params->alt_mem = grub_mmap_get_upper () >> 10; - params->ext_mem = params->alt_mem; - - lh->cmd_line_ptr = (char *) - (GRUB_OFW_LINUX_PARAMS_ADDR + GRUB_OFW_LINUX_CL_OFFSET); - - params->cl_magic = GRUB_LINUX_CL_MAGIC; - params->cl_offset = GRUB_OFW_LINUX_CL_OFFSET; - - { - grub_term_output_t term; - int found = 0; - FOR_ACTIVE_TERM_OUTPUTS(term) - if (grub_strcmp (term->name, "ofconsole") == 0) - { - grub_uint16_t pos = grub_term_getxy (term); - params->video_cursor_x = pos >> 8; - params->video_cursor_y = pos & 0xff; - params->video_width = grub_term_width (term); - params->video_height = grub_term_height (term); - found = 1; - break; - } - if (!found) - { - params->video_cursor_x = 0; - params->video_cursor_y = 0; - params->video_width = 80; - params->video_height = 25; - } - } - - params->font_size = 16; - - params->ofw_signature = GRUB_LINUX_OFW_SIGNATURE; - params->ofw_num_items = 1; - params->ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn; - params->ofw_idt = 0; - - if (initrd_size) - { - lh->type_of_loader = 1; - lh->ramdisk_image = GRUB_OFW_LINUX_INITRD_ADDR; - lh->ramdisk_size = initrd_size; - } - - if (kernel_cmdline) - grub_strcpy (lh->cmd_line_ptr, kernel_cmdline); - - prot_code = (char *) GRUB_OFW_LINUX_KERNEL_ADDR; - grub_memcpy (prot_code, kernel_addr, kernel_size); - - asm volatile ("movl %0, %%esi" : : "m" (params)); - asm volatile ("movl %%esi, %%esp" : : ); - asm volatile ("movl %0, %%ecx" : : "m" (prot_code)); - asm volatile ("xorl %%ebx, %%ebx" : : ); - asm volatile ("jmp *%%ecx" : : ); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - struct linux_kernel_header lh; - grub_uint8_t setup_sects; - grub_size_t real_size, prot_size; - int i; - char *dest; - - grub_dl_ref (my_mod); - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); - goto fail; - } - - file = grub_file_open (argv[0]); - if (! file) - goto fail; - - if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) - { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); - goto fail; - } - - if ((lh.boot_flag != grub_cpu_to_le16 (0xaa55)) || - (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE))) - { - grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); - goto fail; - } - - setup_sects = lh.setup_sects; - if (! setup_sects) - setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS; - - real_size = setup_sects << GRUB_DISK_SECTOR_BITS; - prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; - - grub_dprintf ("linux", "Linux-%s, setup=0x%x, size=0x%x\n", - "bzImage", real_size, prot_size); - - grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); - if (grub_errno) - goto fail; - - kernel_cmdline = grub_malloc (GRUB_OFW_LINUX_CL_LENGTH); - if (! kernel_cmdline) - goto fail; - - dest = kernel_cmdline; - for (i = 1; - i < argc - && dest + grub_strlen (argv[i]) + 1 < (kernel_cmdline - + GRUB_OFW_LINUX_CL_LENGTH); - i++) - { - *dest++ = ' '; - dest = grub_stpcpy (dest, argv[i]); - } - - kernel_addr = grub_malloc (prot_size); - if (! kernel_addr) - goto fail; - - kernel_size = prot_size; - if (grub_file_read (file, kernel_addr, prot_size) != (int) prot_size) - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - - if (grub_errno == GRUB_ERR_NONE) - grub_loader_set (grub_linux_boot, grub_linux_unload, 1); - -fail: - - if (file) - grub_file_close (file); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_free (kernel_cmdline); - grub_free (kernel_addr); - kernel_cmdline = 0; - kernel_addr = 0; - - grub_dl_unref (my_mod); - } - - return grub_errno; -} - -static grub_err_t -grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); - goto fail; - } - - if (! kernel_addr) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first"); - goto fail; - } - - file = grub_file_open (argv[0]); - if (! file) - goto fail; - - initrd_size = grub_file_size (file); - if (grub_file_read (file, (void *) GRUB_OFW_LINUX_INITRD_ADDR, - initrd_size) != (int) initrd_size) - { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; - } - -fail: - if (file) - grub_file_close (file); - - return grub_errno; -} - -static grub_command_t cmd_linux, cmd_initrd; - -GRUB_MOD_INIT(linux) -{ - cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, N_("Load Linux.")); - cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, N_("Load initrd.")); - my_mod = mod; -} - -GRUB_MOD_FINI(linux) -{ - grub_unregister_command (cmd_linux); - grub_unregister_command (cmd_initrd); -} diff --git a/loader/i386/linux_trampoline.S b/loader/i386/linux_trampoline.S deleted file mode 100644 index 4acea7b11..000000000 --- a/loader/i386/linux_trampoline.S +++ /dev/null @@ -1,129 +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 - - - .p2align 4 /* force 16-byte alignment */ -VARIABLE(grub_linux_trampoline_start) - cli - /* %rdi contains protected memory start and %rsi - contains real memory start. */ - - mov %rsi, %rbx - - call base -base: - pop %rsi - -#ifdef APPLE_CC - lea (cont1 - base) (%esi, 1), %rax - mov %eax, (jump_vector - base) (%esi, 1) - - lea (gdt - base) (%esi, 1), %rax - mov %rax, (gdtaddr - base) (%esi, 1) - - /* Switch to compatibility mode. */ - - lidt (idtdesc - base) (%esi, 1) - lgdt (gdtdesc - base) (%esi, 1) - - /* Update %cs. Thanks to David Miller for pointing this mistake out. */ - ljmp *(jump_vector - base) (%esi, 1) -#else - lea (cont1 - base) (%rsi, 1), %rax - mov %eax, (jump_vector - base) (%rsi, 1) - - lea (gdt - base) (%rsi, 1), %rax - mov %rax, (gdtaddr - base) (%rsi, 1) - - /* Switch to compatibility mode. */ - - lidt (idtdesc - base) (%rsi, 1) - lgdt (gdtdesc - base) (%rsi, 1) - - /* Update %cs. Thanks to David Miller for pointing this mistake out. */ - ljmp *(jump_vector - base) (%rsi, 1) -#endif - -cont1: - .code32 - - /* Update other registers. */ - mov $0x18, %eax - mov %eax, %ds - mov %eax, %es - mov %eax, %fs - mov %eax, %gs - mov %eax, %ss - - /* Disable paging. */ - mov %cr0, %eax - and $0x7fffffff, %eax - mov %eax, %cr0 - - /* Disable amd64. */ - mov $0xc0000080, %ecx - rdmsr - and $0xfffffeff, %eax - wrmsr - - /* Turn off PAE. */ - movl %cr4, %eax - and $0xffffffcf, %eax - mov %eax, %cr4 - - jmp cont2 -cont2: - .code32 - - mov %ebx, %esi - - jmp *%edi - - /* GDT. */ - .p2align 4 -gdt: - /* NULL. */ - .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* Reserved. */ - .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* Code segment. */ - .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 - - /* Data segment. */ - .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 - -gdtdesc: - .word 31 -gdtaddr: - .quad gdt - -idtdesc: - .word 0 -idtaddr: - .quad 0 - - .p2align 4 -jump_vector: - /* Jump location. Is filled by the code */ - .long 0 - .long 0x10 -VARIABLE(grub_linux_trampoline_end) diff --git a/m4/00gnulib.m4 b/m4/00gnulib.m4 new file mode 100644 index 000000000..301469b31 --- /dev/null +++ b/m4/00gnulib.m4 @@ -0,0 +1,30 @@ +# 00gnulib.m4 serial 2 +dnl Copyright (C) 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This file must be named something that sorts before all other +dnl gnulib-provided .m4 files. It is needed until such time as we can +dnl assume Autoconf 2.64, with its improved AC_DEFUN_ONCE semantics. + +# AC_DEFUN_ONCE([NAME], VALUE) +# ---------------------------- +# Define NAME to expand to VALUE on the first use (whether by direct +# expansion, or by AC_REQUIRE), and to nothing on all subsequent uses. +# Avoid bugs in AC_REQUIRE in Autoconf 2.63 and earlier. This +# definition is slower than the version in Autoconf 2.64, because it +# can only use interfaces that existed since 2.59; but it achieves the +# same effect. Quoting is necessary to avoid confusing Automake. +m4_version_prereq([2.63.263], [], +[m4_define([AC][_DEFUN_ONCE], + [AC][_DEFUN([$1], + [AC_REQUIRE([_gl_DEFUN_ONCE([$1])], + [m4_indir([_gl_DEFUN_ONCE([$1])])])])]dnl +[AC][_DEFUN([_gl_DEFUN_ONCE([$1])], [$2])])]) + +# gl_00GNULIB +# ----------- +# Witness macro that this file has been included. Needed to force +# Automake to include this file prior to all other gnulib .m4 files. +AC_DEFUN([gl_00GNULIB]) diff --git a/m4/alloca.m4 b/m4/alloca.m4 new file mode 100644 index 000000000..f3ee34380 --- /dev/null +++ b/m4/alloca.m4 @@ -0,0 +1,47 @@ +# alloca.m4 serial 9 +dnl Copyright (C) 2002-2004, 2006-2007, 2009-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_ALLOCA], +[ + dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57. + AC_REQUIRE([AC_PROG_CPP]) + AC_REQUIRE([AC_PROG_EGREP]) + + AC_REQUIRE([AC_FUNC_ALLOCA]) + if test $ac_cv_func_alloca_works = no; then + gl_PREREQ_ALLOCA + fi + + # Define an additional variable used in the Makefile substitution. + if test $ac_cv_working_alloca_h = yes; then + AC_CACHE_CHECK([for alloca as a compiler built-in], [gl_cv_rpl_alloca], [ + AC_EGREP_CPP([Need own alloca], [ +#if defined __GNUC__ || defined _AIX || defined _MSC_VER + Need own alloca +#endif + ], [gl_cv_rpl_alloca=yes], [gl_cv_rpl_alloca=no]) + ]) + if test $gl_cv_rpl_alloca = yes; then + dnl OK, alloca can be implemented through a compiler built-in. + AC_DEFINE([HAVE_ALLOCA], [1], + [Define to 1 if you have 'alloca' after including , + a header that may be supplied by this distribution.]) + ALLOCA_H=alloca.h + else + dnl alloca exists as a library function, i.e. it is slow and probably + dnl a memory leak. Don't define HAVE_ALLOCA in this case. + ALLOCA_H= + fi + else + ALLOCA_H=alloca.h + fi + AC_SUBST([ALLOCA_H]) +]) + +# Prerequisites of lib/alloca.c. +# STACK_DIRECTION is already handled by AC_FUNC_ALLOCA. +AC_DEFUN([gl_PREREQ_ALLOCA], [:]) diff --git a/m4/argp.m4 b/m4/argp.m4 new file mode 100644 index 000000000..d3ca5bacc --- /dev/null +++ b/m4/argp.m4 @@ -0,0 +1,65 @@ +# argp.m4 serial 11 +dnl Copyright (C) 2003-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_ARGP], +[ + AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + dnl argp-parse.c depends on GNU getopt internals, therefore use GNU getopt + dnl always. + gl_REPLACE_GETOPT + dnl Note: gl_REPLACE_GETOPT does AC_LIBOBJ([getopt]), AC_LIBOBJ([getopt1]). + + AC_CHECK_DECL([program_invocation_name], + [AC_DEFINE([HAVE_DECL_PROGRAM_INVOCATION_NAME], [1], + [Define if program_invocation_name is declared])], + [AC_DEFINE([GNULIB_PROGRAM_INVOCATION_NAME], [1], + [Define to 1 to add extern declaration of program_invocation_name to argp.h])], + [#include ]) + AC_CHECK_DECL([program_invocation_short_name], + [AC_DEFINE([HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME], [1], + [Define if program_invocation_short_name is declared])], + [AC_DEFINE([GNULIB_PROGRAM_INVOCATION_SHORT_NAME], [1], + [Define to 1 to add extern declaration of program_invocation_short_name to argp.h])], + [#include ]) + + # Check if program_invocation_name and program_invocation_short_name + # are defined elsewhere. It is improbable that only one of them will + # be defined and other not, I prefer to stay on the safe side and to + # test each one separately. + AC_MSG_CHECKING([whether program_invocation_name is defined]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[program_invocation_name = "test";]])], + [AC_DEFINE([HAVE_PROGRAM_INVOCATION_NAME], [1], + [Define if program_invocation_name is defined]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + + AC_MSG_CHECKING([whether program_invocation_short_name is defined]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[program_invocation_short_name = "test";]])], + [AC_DEFINE([HAVE_PROGRAM_INVOCATION_SHORT_NAME], [1], + [Define if program_invocation_short_name is defined]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + + AC_CHECK_DECLS_ONCE([clearerr_unlocked]) + AC_CHECK_DECLS_ONCE([feof_unlocked]) + AC_CHECK_DECLS_ONCE([ferror_unlocked]) + AC_CHECK_DECLS_ONCE([fflush_unlocked]) + AC_CHECK_DECLS_ONCE([fgets_unlocked]) + AC_CHECK_DECLS_ONCE([fputc_unlocked]) + AC_CHECK_DECLS_ONCE([fputs_unlocked]) + AC_CHECK_DECLS_ONCE([fread_unlocked]) + AC_CHECK_DECLS_ONCE([fwrite_unlocked]) + AC_CHECK_DECLS_ONCE([getc_unlocked]) + AC_CHECK_DECLS_ONCE([getchar_unlocked]) + AC_CHECK_DECLS_ONCE([putc_unlocked]) + AC_CHECK_DECLS_ONCE([putchar_unlocked]) + AC_CHECK_FUNCS_ONCE([flockfile funlockfile]) + AC_CHECK_HEADERS_ONCE([features.h linewrap.h]) +]) diff --git a/m4/asm-underscore.m4 b/m4/asm-underscore.m4 new file mode 100644 index 000000000..1736cc432 --- /dev/null +++ b/m4/asm-underscore.m4 @@ -0,0 +1,48 @@ +# asm-underscore.m4 serial 1 +dnl Copyright (C) 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. Based on as-underscore.m4 in GNU clisp. + +# gl_ASM_SYMBOL_PREFIX +# Tests for the prefix of C symbols at the assembly language level and the +# linker level. This prefix is either an underscore or empty. Defines the +# C macro USER_LABEL_PREFIX to this prefix, and sets ASM_SYMBOL_PREFIX to +# a stringified variant of this prefix. + +AC_DEFUN([gl_ASM_SYMBOL_PREFIX], +[ + dnl We don't use GCC's __USER_LABEL_PREFIX__ here, because + dnl 1. It works only for GCC. + dnl 2. It is incorrectly defined on some platforms, in some GCC versions. + AC_CACHE_CHECK( + [whether C symbols are prefixed with underscore at the linker level], + [gl_cv_prog_as_underscore], + [cat > conftest.c </dev/null 2>&1 + if grep _foo conftest.s >/dev/null ; then + gl_cv_prog_as_underscore=yes + else + gl_cv_prog_as_underscore=no + fi + rm -f conftest* + ]) + if test $gl_cv_prog_as_underscore = yes; then + USER_LABEL_PREFIX=_ + else + USER_LABEL_PREFIX= + fi + AC_DEFINE_UNQUOTED([USER_LABEL_PREFIX], [$USER_LABEL_PREFIX], + [Define to the prefix of C symbols at the assembler and linker level, + either an underscore or empty.]) + ASM_SYMBOL_PREFIX='"'${USER_LABEL_PREFIX}'"' + AC_SUBST([ASM_SYMBOL_PREFIX]) +]) diff --git a/m4/btowc.m4 b/m4/btowc.m4 new file mode 100644 index 000000000..b16b1f020 --- /dev/null +++ b/m4/btowc.m4 @@ -0,0 +1,109 @@ +# btowc.m4 serial 7 +dnl Copyright (C) 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_BTOWC], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + + dnl Check whether is usable at all, first. Otherwise the test + dnl program below may lead to an endless loop. See + dnl . + AC_REQUIRE([gl_WCHAR_H_INLINE_OK]) + + AC_CHECK_FUNCS_ONCE([btowc]) + if test $ac_cv_func_btowc = no; then + HAVE_BTOWC=0 + else + + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_FR]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Cygwin 1.7.2 btowc('\0') is WEOF, not 0. + AC_CACHE_CHECK([whether btowc(0) is correct], + [gl_cv_func_btowc_nul], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +int main () +{ + if (btowc ('\0') != 0) + return 1; + return 0; +}]])], + [gl_cv_func_btowc_nul=yes], + [gl_cv_func_btowc_nul=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess no on Cygwin. + cygwin*) gl_cv_func_btowc_nul="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_btowc_nul="guessing yes" ;; + esac +changequote([,])dnl + ]) + ]) + + dnl IRIX 6.5 btowc(EOF) is 0xFF, not WEOF. + AC_CACHE_CHECK([whether btowc(EOF) is correct], + [gl_cv_func_btowc_eof], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on IRIX. + irix*) gl_cv_func_btowc_eof="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_btowc_eof="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_FR != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +#include +int main () +{ + if (setlocale (LC_ALL, "$LOCALE_FR") != NULL) + { + if (btowc (EOF) != WEOF) + return 1; + } + return 0; +}]])], + [gl_cv_func_btowc_eof=yes], + [gl_cv_func_btowc_eof=no], + [:]) + fi + ]) + + case "$gl_cv_func_btowc_nul" in + *yes) ;; + *) REPLACE_BTOWC=1 ;; + esac + case "$gl_cv_func_btowc_eof" in + *yes) ;; + *) REPLACE_BTOWC=1 ;; + esac + fi + if test $HAVE_BTOWC = 0 || test $REPLACE_BTOWC = 1; then + gl_REPLACE_WCHAR_H + AC_LIBOBJ([btowc]) + gl_PREREQ_BTOWC + fi +]) + +# Prerequisites of lib/btowc.c. +AC_DEFUN([gl_PREREQ_BTOWC], [ + : +]) diff --git a/m4/codeset.m4 b/m4/codeset.m4 new file mode 100644 index 000000000..f722b2e86 --- /dev/null +++ b/m4/codeset.m4 @@ -0,0 +1,23 @@ +# codeset.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], [am_cv_langinfo_codeset], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[char* cs = nl_langinfo(CODESET); return !cs;]])], + [am_cv_langinfo_codeset=yes], + [am_cv_langinfo_codeset=no]) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE([HAVE_LANGINFO_CODESET], [1], + [Define if you have and nl_langinfo(CODESET).]) + fi +]) diff --git a/m4/dirname.m4 b/m4/dirname.m4 new file mode 100644 index 000000000..576b5bead --- /dev/null +++ b/m4/dirname.m4 @@ -0,0 +1,26 @@ +#serial 8 -*- autoconf -*- +dnl Copyright (C) 2002-2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_DIRNAME], +[ + AC_REQUIRE([gl_DIRNAME_LGPL]) + AC_LIBOBJ([basename]) + AC_LIBOBJ([dirname]) +]) + +AC_DEFUN([gl_DIRNAME_LGPL], +[ + AC_LIBOBJ([basename-lgpl]) + AC_LIBOBJ([dirname-lgpl]) + AC_LIBOBJ([stripslash]) + + dnl Prerequisites of lib/dirname.h. + AC_REQUIRE([gl_AC_DOS]) + AC_REQUIRE([gl_DOUBLE_SLASH_ROOT]) + + dnl No prerequisites of lib/basename-lgpl.c, lib/dirname-lgpl.c, + dnl lib/stripslash.c. +]) diff --git a/m4/dos.m4 b/m4/dos.m4 new file mode 100644 index 000000000..5660542be --- /dev/null +++ b/m4/dos.m4 @@ -0,0 +1,71 @@ +#serial 11 -*- autoconf -*- + +# Define some macros required for proper operation of code in lib/*.c +# on MSDOS/Windows systems. + +# Copyright (C) 2000-2001, 2004-2006, 2009-2010 Free Software Foundation, Inc. +# 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. + +# From Jim Meyering. + +AC_DEFUN([gl_AC_DOS], + [ + AC_CACHE_CHECK([whether system is Windows or MSDOS], [ac_cv_win_or_dos], + [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[ +#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __CYGWIN__ +neither MSDOS nor Windows +#endif]])], + [ac_cv_win_or_dos=yes], + [ac_cv_win_or_dos=no]) + ]) + + if test x"$ac_cv_win_or_dos" = xyes; then + ac_fs_accepts_drive_letter_prefix=1 + ac_fs_backslash_is_file_name_separator=1 + AC_CACHE_CHECK([whether drive letter can start relative path], + [ac_cv_drive_letter_can_be_relative], + [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[ +#if defined __CYGWIN__ +drive letters are always absolute +#endif]])], + [ac_cv_drive_letter_can_be_relative=yes], + [ac_cv_drive_letter_can_be_relative=no]) + ]) + if test x"$ac_cv_drive_letter_can_be_relative" = xyes; then + ac_fs_drive_letter_can_be_relative=1 + else + ac_fs_drive_letter_can_be_relative=0 + fi + else + ac_fs_accepts_drive_letter_prefix=0 + ac_fs_backslash_is_file_name_separator=0 + ac_fs_drive_letter_can_be_relative=0 + fi + + AC_DEFINE_UNQUOTED([FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX], + $ac_fs_accepts_drive_letter_prefix, + [Define on systems for which file names may have a so-called + `drive letter' prefix, define this to compute the length of that + prefix, including the colon.]) + + AH_VERBATIM(ISSLASH, + [#if FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#else +# define ISSLASH(C) ((C) == '/') +#endif]) + + AC_DEFINE_UNQUOTED([FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR], + $ac_fs_backslash_is_file_name_separator, + [Define if the backslash character may also serve as a file name + component separator.]) + + AC_DEFINE_UNQUOTED([FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE], + $ac_fs_drive_letter_can_be_relative, + [Define if a drive letter prefix denotes a relative path if it is + not followed by a file name component separator.]) + ]) diff --git a/m4/double-slash-root.m4 b/m4/double-slash-root.m4 new file mode 100644 index 000000000..66a79c0f2 --- /dev/null +++ b/m4/double-slash-root.m4 @@ -0,0 +1,38 @@ +# double-slash-root.m4 serial 4 -*- Autoconf -*- +dnl Copyright (C) 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_DOUBLE_SLASH_ROOT], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CACHE_CHECK([whether // is distinct from /], [gl_cv_double_slash_root], + [ if test x"$cross_compiling" = xyes ; then + # When cross-compiling, there is no way to tell whether // is special + # short of a list of hosts. However, the only known hosts to date + # that have a distinct // are Apollo DomainOS (too old to port to), + # Cygwin, and z/OS. If anyone knows of another system for which // has + # special semantics and is distinct from /, please report it to + # . + case $host in + *-cygwin | i370-ibm-openedition) + gl_cv_double_slash_root=yes ;; + *) + # Be optimistic and assume that / and // are the same when we + # don't know. + gl_cv_double_slash_root='unknown, assuming no' ;; + esac + else + set x `ls -di / // 2>/dev/null` + if test "$[2]" = "$[4]" && wc //dev/null >/dev/null 2>&1; then + gl_cv_double_slash_root=no + else + gl_cv_double_slash_root=yes + fi + fi]) + if test "$gl_cv_double_slash_root" = yes; then + AC_DEFINE([DOUBLE_SLASH_IS_DISTINCT_ROOT], [1], + [Define to 1 if // is a file system root distinct from /.]) + fi +]) diff --git a/m4/errno_h.m4 b/m4/errno_h.m4 new file mode 100644 index 000000000..d02a03936 --- /dev/null +++ b/m4/errno_h.m4 @@ -0,0 +1,115 @@ +# errno_h.m4 serial 6 +dnl Copyright (C) 2004, 2006, 2008, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN_ONCE([gl_HEADER_ERRNO_H], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([for complete errno.h], [gl_cv_header_errno_h_complete], [ + AC_EGREP_CPP([booboo],[ +#include +#if !defined ENOMSG +booboo +#endif +#if !defined EIDRM +booboo +#endif +#if !defined ENOLINK +booboo +#endif +#if !defined EPROTO +booboo +#endif +#if !defined EMULTIHOP +booboo +#endif +#if !defined EBADMSG +booboo +#endif +#if !defined EOVERFLOW +booboo +#endif +#if !defined ENOTSUP +booboo +#endif +#if !defined ESTALE +booboo +#endif +#if !defined ECANCELED +booboo +#endif + ], + [gl_cv_header_errno_h_complete=no], + [gl_cv_header_errno_h_complete=yes]) + ]) + if test $gl_cv_header_errno_h_complete = yes; then + ERRNO_H='' + else + gl_CHECK_NEXT_HEADERS([errno.h]) + ERRNO_H='errno.h' + fi + AC_SUBST([ERRNO_H]) + gl_REPLACE_ERRNO_VALUE([EMULTIHOP]) + gl_REPLACE_ERRNO_VALUE([ENOLINK]) + gl_REPLACE_ERRNO_VALUE([EOVERFLOW]) +]) + +# Assuming $1 = EOVERFLOW. +# The EOVERFLOW errno value ought to be defined in , according to +# POSIX. But some systems (like OpenBSD 4.0 or AIX 3) don't define it, and +# some systems (like OSF/1) define it when _XOPEN_SOURCE_EXTENDED is defined. +# Check for the value of EOVERFLOW. +# Set the variables EOVERFLOW_HIDDEN and EOVERFLOW_VALUE. +AC_DEFUN([gl_REPLACE_ERRNO_VALUE], +[ + if test -n "$ERRNO_H"; then + AC_CACHE_CHECK([for ]$1[ value], [gl_cv_header_errno_h_]$1, [ + AC_EGREP_CPP([yes],[ +#include +#ifdef ]$1[ +yes +#endif + ], + [gl_cv_header_errno_h_]$1[=yes], + [gl_cv_header_errno_h_]$1[=no]) + if test $gl_cv_header_errno_h_]$1[ = no; then + AC_EGREP_CPP([yes],[ +#define _XOPEN_SOURCE_EXTENDED 1 +#include +#ifdef ]$1[ +yes +#endif + ], [gl_cv_header_errno_h_]$1[=hidden]) + if test $gl_cv_header_errno_h_]$1[ = hidden; then + dnl The macro exists but is hidden. + dnl Define it to the same value. + AC_COMPUTE_INT([gl_cv_header_errno_h_]$1, $1, [ +#define _XOPEN_SOURCE_EXTENDED 1 +#include +/* The following two lines are a workaround against an autoconf-2.52 bug. */ +#include +#include +]) + fi + fi + ]) + case $gl_cv_header_errno_h_]$1[ in + yes | no) + ]$1[_HIDDEN=0; ]$1[_VALUE= + ;; + *) + ]$1[_HIDDEN=1; ]$1[_VALUE="$gl_cv_header_errno_h_]$1[" + ;; + esac + AC_SUBST($1[_HIDDEN]) + AC_SUBST($1[_VALUE]) + fi +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) diff --git a/m4/error.m4 b/m4/error.m4 new file mode 100644 index 000000000..dd5a197b6 --- /dev/null +++ b/m4/error.m4 @@ -0,0 +1,39 @@ +#serial 13 + +# Copyright (C) 1996-1998, 2001-2004, 2009-2010 Free Software Foundation, Inc. +# +# 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. + +AC_DEFUN([gl_ERROR], +[ + AC_FUNC_ERROR_AT_LINE + dnl Note: AC_FUNC_ERROR_AT_LINE does AC_LIBSOURCES([error.h, error.c]). + gl_PREREQ_ERROR +]) + +# Redefine AC_FUNC_ERROR_AT_LINE, because it is no longer maintained in +# Autoconf. +AC_DEFUN([AC_FUNC_ERROR_AT_LINE], +[ + AC_LIBSOURCES([error.h, error.c])dnl + AC_CACHE_CHECK([for error_at_line], [ac_cv_lib_error_at_line], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[error_at_line (0, 0, "", 0, "an error occurred");]])], + [ac_cv_lib_error_at_line=yes], + [ac_cv_lib_error_at_line=no])]) + if test $ac_cv_lib_error_at_line = no; then + AC_LIBOBJ([error]) + fi +]) + +# Prerequisites of lib/error.c. +AC_DEFUN([gl_PREREQ_ERROR], +[ + AC_REQUIRE([AC_FUNC_STRERROR_R]) + AC_REQUIRE([AC_C_INLINE]) + : +]) diff --git a/m4/extensions.m4 b/m4/extensions.m4 new file mode 100644 index 000000000..7d9458a8d --- /dev/null +++ b/m4/extensions.m4 @@ -0,0 +1,118 @@ +# serial 9 -*- Autoconf -*- +# Enable extensions on systems that normally disable them. + +# Copyright (C) 2003, 2006-2010 Free Software Foundation, Inc. +# 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. + +# This definition of AC_USE_SYSTEM_EXTENSIONS is stolen from CVS +# Autoconf. Perhaps we can remove this once we can assume Autoconf +# 2.62 or later everywhere, but since CVS Autoconf mutates rapidly +# enough in this area it's likely we'll need to redefine +# AC_USE_SYSTEM_EXTENSIONS for quite some time. + +# If autoconf reports a warning +# warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS +# or warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS +# the fix is +# 1) to ensure that AC_USE_SYSTEM_EXTENSIONS is never directly invoked +# but always AC_REQUIREd, +# 2) to ensure that for each occurrence of +# AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) +# or +# AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) +# the corresponding gnulib module description has 'extensions' among +# its dependencies. This will ensure that the gl_USE_SYSTEM_EXTENSIONS +# invocation occurs in gl_EARLY, not in gl_INIT. + +# AC_USE_SYSTEM_EXTENSIONS +# ------------------------ +# Enable extensions on systems that normally disable them, +# typically due to standards-conformance issues. +# Remember that #undef in AH_VERBATIM gets replaced with #define by +# AC_DEFINE. The goal here is to define all known feature-enabling +# macros, then, if reports of conflicts are made, disable macros that +# cause problems on some platforms (such as __EXTENSIONS__). +AC_DEFUN_ONCE([AC_USE_SYSTEM_EXTENSIONS], +[AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl +AC_BEFORE([$0], [AC_RUN_IFELSE])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + + AC_CHECK_HEADER([minix/config.h], [MINIX=yes], [MINIX=]) + if test "$MINIX" = yes; then + AC_DEFINE([_POSIX_SOURCE], [1], + [Define to 1 if you need to in order for `stat' and other + things to work.]) + AC_DEFINE([_POSIX_1_SOURCE], [2], + [Define to 2 if the system does not provide POSIX.1 features + except with this defined.]) + AC_DEFINE([_MINIX], [1], + [Define to 1 if on MINIX.]) + fi + + dnl HP-UX 11.11 defines mbstate_t only if _XOPEN_SOURCE is defined to 500, + dnl regardless of whether the flags -Ae or _D_HPUX_SOURCE=1 are already + dnl provided. + case "$host_os" in + hpux*) + AC_DEFINE([_XOPEN_SOURCE], [500], + [Define to 500 only on HP-UX.]) + ;; + esac + + AH_VERBATIM([__EXTENSIONS__], +[/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +]) + AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__], + [ac_cv_safe_to_define___extensions__], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ +# define __EXTENSIONS__ 1 + ]AC_INCLUDES_DEFAULT])], + [ac_cv_safe_to_define___extensions__=yes], + [ac_cv_safe_to_define___extensions__=no])]) + test $ac_cv_safe_to_define___extensions__ = yes && + AC_DEFINE([__EXTENSIONS__]) + AC_DEFINE([_ALL_SOURCE]) + AC_DEFINE([_GNU_SOURCE]) + AC_DEFINE([_POSIX_PTHREAD_SEMANTICS]) + AC_DEFINE([_TANDEM_SOURCE]) +])# AC_USE_SYSTEM_EXTENSIONS + +# gl_USE_SYSTEM_EXTENSIONS +# ------------------------ +# Enable extensions on systems that normally disable them, +# typically due to standards-conformance issues. +AC_DEFUN_ONCE([gl_USE_SYSTEM_EXTENSIONS], +[ + dnl Require this macro before AC_USE_SYSTEM_EXTENSIONS. + dnl gnulib does not need it. But if it gets required by third-party macros + dnl after AC_USE_SYSTEM_EXTENSIONS is required, autoconf 2.62..2.63 emit a + dnl warning: "AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS". + dnl Note: We can do this only for one of the macros AC_AIX, AC_GNU_SOURCE, + dnl AC_MINIX. If people still use AC_AIX or AC_MINIX, they are out of luck. + AC_REQUIRE([AC_GNU_SOURCE]) + + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) +]) diff --git a/m4/fcntl-o.m4 b/m4/fcntl-o.m4 new file mode 100644 index 000000000..1adacc8ab --- /dev/null +++ b/m4/fcntl-o.m4 @@ -0,0 +1,85 @@ +# fcntl-o.m4 serial 2 +dnl Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Paul Eggert. + +# Test whether the flags O_NOATIME and O_NOFOLLOW actually work. +# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise. +# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise. +AC_DEFUN([gl_FCNTL_O_FLAGS], +[ + dnl Persuade glibc to define O_NOATIME and O_NOFOLLOW. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + #ifndef O_NOATIME + #define O_NOATIME 0 + #endif + #ifndef O_NOFOLLOW + #define O_NOFOLLOW 0 + #endif + static int const constants[] = + { + O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, + O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY + }; + ]], + [[ + int status = !constants; + { + static char const sym[] = "conftest.sym"; + if (symlink (".", sym) != 0 + || close (open (sym, O_RDONLY | O_NOFOLLOW)) == 0) + status |= 32; + unlink (sym); + } + { + static char const file[] = "confdefs.h"; + int fd = open (file, O_RDONLY | O_NOATIME); + char c; + struct stat st0, st1; + if (fd < 0 + || fstat (fd, &st0) != 0 + || sleep (1) != 0 + || read (fd, &c, 1) != 1 + || close (fd) != 0 + || stat (file, &st1) != 0 + || st0.st_atime != st1.st_atime) + status |= 64; + } + return status;]])], + [gl_cv_header_working_fcntl_h=yes], + [case $? in #( + 32) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #( + 64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #( + 96) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #( + *) gl_cv_header_working_fcntl_h='no';; + esac], + [gl_cv_header_working_fcntl_h=cross-compiling])]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOATIME* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val], + [Define to 1 if O_NOATIME works.]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val], + [Define to 1 if O_NOFOLLOW works.]) +]) diff --git a/m4/float_h.m4 b/m4/float_h.m4 new file mode 100644 index 000000000..f6099db40 --- /dev/null +++ b/m4/float_h.m4 @@ -0,0 +1,19 @@ +# float_h.m4 serial 4 +dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FLOAT_H], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + FLOAT_H= + case "$host_os" in + beos* | openbsd* | mirbsd*) + FLOAT_H=float.h + gl_CHECK_NEXT_HEADERS([float.h]) + ;; + esac + AC_SUBST([FLOAT_H]) +]) diff --git a/m4/fnmatch.m4 b/m4/fnmatch.m4 new file mode 100644 index 000000000..212ead572 --- /dev/null +++ b/m4/fnmatch.m4 @@ -0,0 +1,121 @@ +# Check for fnmatch - serial 4. + +# Copyright (C) 2000-2007, 2009-2010 Free Software Foundation, Inc. +# 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. + +# Autoconf defines AC_FUNC_FNMATCH, but that is obsolescent. +# New applications should use the macros below instead. + +# Request a POSIX compliant fnmatch function. +AC_DEFUN([gl_FUNC_FNMATCH_POSIX], +[ + m4_divert_text([DEFAULTS], [gl_fnmatch_required=POSIX]) + + dnl Persuade glibc to declare FNM_CASEFOLD etc. + dnl This is only needed if gl_fnmatch_required = GNU. It would be possible + dnl to avoid this dependency for gl_FUNC_FNMATCH_POSIX by putting + dnl gl_FUNC_FNMATCH_GNU into a separate .m4 file. + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + FNMATCH_H= + gl_fnmatch_required_lowercase=`echo $gl_fnmatch_required | tr 'A-Z' 'a-z'` + gl_fnmatch_cache_var="gl_cv_func_fnmatch_${gl_fnmatch_required_lowercase}" + AC_CACHE_CHECK([for working $gl_fnmatch_required fnmatch], + [$gl_fnmatch_cache_var], + [dnl Some versions of Solaris, SCO, and the GNU C Library + dnl have a broken or incompatible fnmatch. + dnl So we run a test program. If we are cross-compiling, take no chance. + dnl Thanks to John Oleynick, François Pinard, and Paul Eggert for this + dnl test. + if test $gl_fnmatch_required = GNU; then + gl_fnmatch_gnu_start= + gl_fnmatch_gnu_end= + else + gl_fnmatch_gnu_start='#if 0' + gl_fnmatch_gnu_end='#endif' + fi + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + static int + y (char const *pattern, char const *string, int flags) + { + return fnmatch (pattern, string, flags) == 0; + } + static int + n (char const *pattern, char const *string, int flags) + { + return fnmatch (pattern, string, flags) == FNM_NOMATCH; + } + ]], + [[char const *Apat = 'A' < '\\\\' ? "[A-\\\\\\\\]" : "[\\\\\\\\-A]"; + char const *apat = 'a' < '\\\\' ? "[a-\\\\\\\\]" : "[\\\\\\\\-a]"; + static char const A_1[] = { 'A' - 1, 0 }; + static char const A01[] = { 'A' + 1, 0 }; + static char const a_1[] = { 'a' - 1, 0 }; + static char const a01[] = { 'a' + 1, 0 }; + static char const bs_1[] = { '\\\\' - 1, 0 }; + static char const bs01[] = { '\\\\' + 1, 0 }; + return + !(n ("a*", "", 0) + && y ("a*", "abc", 0) + && n ("d*/*1", "d/s/1", FNM_PATHNAME) + && y ("a\\\\bc", "abc", 0) + && n ("a\\\\bc", "abc", FNM_NOESCAPE) + && y ("*x", ".x", 0) + && n ("*x", ".x", FNM_PERIOD) + && y (Apat, "\\\\", 0) && y (Apat, "A", 0) + && y (apat, "\\\\", 0) && y (apat, "a", 0) + && n (Apat, A_1, 0) == ('A' < '\\\\') + && n (apat, a_1, 0) == ('a' < '\\\\') + && y (Apat, A01, 0) == ('A' < '\\\\') + && y (apat, a01, 0) == ('a' < '\\\\') + && y (Apat, bs_1, 0) == ('A' < '\\\\') + && y (apat, bs_1, 0) == ('a' < '\\\\') + && n (Apat, bs01, 0) == ('A' < '\\\\') + && n (apat, bs01, 0) == ('a' < '\\\\') + $gl_fnmatch_gnu_start + && y ("xxXX", "xXxX", FNM_CASEFOLD) + && y ("a++(x|yy)b", "a+xyyyyxb", FNM_EXTMATCH) + && n ("d*/*1", "d/s/1", FNM_FILE_NAME) + && y ("*", "x", FNM_FILE_NAME | FNM_LEADING_DIR) + && y ("x*", "x/y/z", FNM_FILE_NAME | FNM_LEADING_DIR) + && y ("*c*", "c/x", FNM_FILE_NAME | FNM_LEADING_DIR) + $gl_fnmatch_gnu_end + ); + ]])], + [eval "$gl_fnmatch_cache_var=yes"], + [eval "$gl_fnmatch_cache_var=no"], + [eval "$gl_fnmatch_cache_var=\"guessing no\""]) + ]) + eval "gl_fnmatch_result=\"\$$gl_fnmatch_cache_var\"" + if test "$gl_fnmatch_result" = yes; then + dnl Not strictly necessary. Only to avoid spurious leftover files if people + dnl don't do "make distclean". + rm -f "$gl_source_base/fnmatch.h" + else + FNMATCH_H=fnmatch.h + AC_LIBOBJ([fnmatch]) + dnl We must choose a different name for our function, since on ELF systems + dnl a broken fnmatch() in libc.so would override our fnmatch() if it is + dnl compiled into a shared library. + AC_DEFINE_UNQUOTED([fnmatch], [${gl_fnmatch_required_lowercase}_fnmatch], + [Define to a replacement function name for fnmatch().]) + dnl Prerequisites of lib/fnmatch.c. + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + AC_CHECK_DECLS([isblank], [], [], [#include ]) + AC_CHECK_FUNCS_ONCE([btowc isblank iswctype mbsrtowcs mempcpy wmemchr wmemcpy wmempcpy]) + AC_CHECK_HEADERS_ONCE([wctype.h]) + fi + AC_SUBST([FNMATCH_H]) +]) + +# Request a POSIX compliant fnmatch function with GNU extensions. +AC_DEFUN([gl_FUNC_FNMATCH_GNU], +[ + m4_divert_text([INIT_PREPARE], [gl_fnmatch_required=GNU]) + + AC_REQUIRE([gl_FUNC_FNMATCH_POSIX]) +]) diff --git a/m4/getdelim.m4 b/m4/getdelim.m4 new file mode 100644 index 000000000..4beb1501c --- /dev/null +++ b/m4/getdelim.m4 @@ -0,0 +1,90 @@ +# getdelim.m4 serial 6 + +dnl Copyright (C) 2005-2007, 2009-2010 Free Software Foundation, Inc. +dnl +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_PREREQ([2.59]) + +AC_DEFUN([gl_FUNC_GETDELIM], +[ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + + dnl Persuade glibc to declare getdelim(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_DECLS_ONCE([getdelim]) + + AC_CHECK_FUNCS_ONCE([getdelim]) + if test $ac_cv_func_getdelim = yes; then + dnl Found it in some library. Verify that it works. + AC_CACHE_CHECK([for working getdelim function], [gl_cv_func_working_getdelim], + [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +# include +# include +# include + int main () + { + FILE *in = fopen ("./conftest.data", "r"); + if (!in) + return 1; + { + /* Test result for a NULL buffer and a zero size. + Based on a test program from Karl Heuer. */ + char *line = NULL; + size_t siz = 0; + int len = getdelim (&line, &siz, '\n', in); + if (!(len == 4 && line && strcmp (line, "foo\n") == 0)) + return 1; + } + { + /* Test result for a NULL buffer and a non-zero size. + This crashes on FreeBSD 8.0. */ + char *line = NULL; + size_t siz = (size_t)(~0) / 4; + if (getdelim (&line, &siz, '\n', in) == -1) + return 1; + } + return 0; + } + ]])], [gl_cv_func_working_getdelim=yes] dnl The library version works. + , [gl_cv_func_working_getdelim=no] dnl The library version does NOT work. + , dnl We're cross compiling. Assume it works on glibc2 systems. + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + [gl_cv_func_working_getdelim=yes], + [gl_cv_func_working_getdelim=no])] + )]) + else + gl_cv_func_working_getdelim=no + fi + + if test $ac_cv_have_decl_getdelim = no; then + HAVE_DECL_GETDELIM=0 + fi + + if test $gl_cv_func_working_getdelim = no; then + if test $ac_cv_func_getdelim = yes; then + REPLACE_GETDELIM=1 + fi + AC_LIBOBJ([getdelim]) + gl_PREREQ_GETDELIM + fi +]) + +# Prerequisites of lib/getdelim.c. +AC_DEFUN([gl_PREREQ_GETDELIM], +[ + AC_CHECK_FUNCS([flockfile funlockfile]) + AC_CHECK_DECLS([getc_unlocked]) +]) diff --git a/m4/getline.m4 b/m4/getline.m4 new file mode 100644 index 000000000..83005600d --- /dev/null +++ b/m4/getline.m4 @@ -0,0 +1,97 @@ +# getline.m4 serial 21 + +dnl Copyright (C) 1998-2003, 2005-2007, 2009-2010 Free Software Foundation, +dnl Inc. +dnl +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_PREREQ([2.59]) + +dnl See if there's a working, system-supplied version of the getline function. +dnl We can't just do AC_REPLACE_FUNCS([getline]) because some systems +dnl have a function by that name in -linet that doesn't have anything +dnl to do with the function we need. +AC_DEFUN([gl_FUNC_GETLINE], +[ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + + dnl Persuade glibc to declare getline(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_DECLS_ONCE([getline]) + + gl_getline_needs_run_time_check=no + AC_CHECK_FUNC([getline], + [dnl Found it in some library. Verify that it works. + gl_getline_needs_run_time_check=yes], + [am_cv_func_working_getline=no]) + if test $gl_getline_needs_run_time_check = yes; then + AC_CACHE_CHECK([for working getline function], [am_cv_func_working_getline], + [echo fooNbarN | tr -d '\012' | tr N '\012' > conftest.data + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +# include +# include +# include + int main () + { + FILE *in = fopen ("./conftest.data", "r"); + if (!in) + return 1; + { + /* Test result for a NULL buffer and a zero size. + Based on a test program from Karl Heuer. */ + char *line = NULL; + size_t siz = 0; + int len = getline (&line, &siz, in); + if (!(len == 4 && line && strcmp (line, "foo\n") == 0)) + return 1; + } + { + /* Test result for a NULL buffer and a non-zero size. + This crashes on FreeBSD 8.0. */ + char *line = NULL; + size_t siz = (size_t)(~0) / 4; + if (getline (&line, &siz, in) == -1) + return 1; + } + return 0; + } + ]])], [am_cv_func_working_getline=yes] dnl The library version works. + , [am_cv_func_working_getline=no] dnl The library version does NOT work. + , dnl We're cross compiling. Assume it works on glibc2 systems. + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + [am_cv_func_working_getline=yes], + [am_cv_func_working_getline=no])] + )]) + fi + + if test $ac_cv_have_decl_getline = no; then + HAVE_DECL_GETLINE=0 + fi + + if test $am_cv_func_working_getline = no; then + dnl Set REPLACE_GETLINE always: Even if we have not found the broken + dnl getline function among $LIBS, it may exist in libinet and the + dnl executable may be linked with -linet. + REPLACE_GETLINE=1 + AC_LIBOBJ([getline]) + + gl_PREREQ_GETLINE + fi +]) + +# Prerequisites of lib/getline.c. +AC_DEFUN([gl_PREREQ_GETLINE], +[ + gl_FUNC_GETDELIM +]) diff --git a/m4/getopt.m4 b/m4/getopt.m4 new file mode 100644 index 000000000..d05e9d914 --- /dev/null +++ b/m4/getopt.m4 @@ -0,0 +1,318 @@ +# getopt.m4 serial 31 +dnl Copyright (C) 2002-2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Request a POSIX compliant getopt function. +AC_DEFUN([gl_FUNC_GETOPT_POSIX], +[ + m4_divert_text([DEFAULTS], [gl_getopt_required=POSIX]) + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + gl_GETOPT_IFELSE([ + gl_REPLACE_GETOPT + ], + []) +]) + +# Request a POSIX compliant getopt function with GNU extensions (such as +# options with optional arguments) and the functions getopt_long, +# getopt_long_only. +AC_DEFUN([gl_FUNC_GETOPT_GNU], +[ + m4_divert_text([INIT_PREPARE], [gl_getopt_required=GNU]) + + AC_REQUIRE([gl_FUNC_GETOPT_POSIX]) +]) + +# Request the gnulib implementation of the getopt functions unconditionally. +# argp.m4 uses this. +AC_DEFUN([gl_REPLACE_GETOPT], +[ + dnl Arrange for getopt.h to be created. + gl_GETOPT_SUBSTITUTE_HEADER + dnl Arrange for unistd.h to include getopt.h. + GNULIB_UNISTD_H_GETOPT=1 + dnl Arrange to compile the getopt implementation. + AC_LIBOBJ([getopt]) + AC_LIBOBJ([getopt1]) + gl_PREREQ_GETOPT +]) + +# emacs' configure.in uses this. +AC_DEFUN([gl_GETOPT_IFELSE], +[ + AC_REQUIRE([gl_GETOPT_CHECK_HEADERS]) + AS_IF([test -n "$gl_replace_getopt"], [$1], [$2]) +]) + +# Determine whether to replace the entire getopt facility. +AC_DEFUN([gl_GETOPT_CHECK_HEADERS], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_REQUIRE([AC_PROG_AWK]) dnl for awk that supports ENVIRON + + dnl Persuade Solaris to declare optarg, optind, opterr, optopt. + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + gl_CHECK_NEXT_HEADERS([getopt.h]) + AC_CHECK_HEADERS_ONCE([getopt.h]) + if test $ac_cv_header_getopt_h = yes; then + HAVE_GETOPT_H=1 + else + HAVE_GETOPT_H=0 + fi + AC_SUBST([HAVE_GETOPT_H]) + + gl_replace_getopt= + + dnl Test whether is available. + if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then + AC_CHECK_HEADERS([getopt.h], [], [gl_replace_getopt=yes]) + fi + + dnl Test whether the function getopt_long is available. + if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then + AC_CHECK_FUNCS([getopt_long_only], [], [gl_replace_getopt=yes]) + fi + + dnl BSD getopt_long uses an incompatible method to reset option processing. + dnl Existence of the variable, in and of itself, is not a reason to replace + dnl getopt, but knowledge of the variable is needed to determine how to + dnl reset and whether a reset reparses the environment. + dnl Solaris supports neither optreset nor optind=0, but keeps no state that + dnl needs a reset beyond setting optind=1; detect Solaris by getopt_clip. + if test -z "$gl_replace_getopt"; then + AC_CHECK_DECLS([optreset], [], + [AC_CHECK_DECLS([getopt_clip], [], [], + [[#include ]]) + ], + [[#include ]]) + fi + + dnl mingw's getopt (in libmingwex.a) does weird things when the options + dnl strings starts with '+' and it's not the first call. Some internal state + dnl is left over from earlier calls, and neither setting optind = 0 nor + dnl setting optreset = 1 get rid of this internal state. + dnl POSIX is silent on optind vs. optreset, so we allow either behavior. + dnl POSIX 2008 does not specify leading '+' behavior, but see + dnl http://austingroupbugs.net/view.php?id=191 for a recommendation on + dnl the next version of POSIX. For now, we only guarantee leading '+' + dnl behavior with getopt-gnu. + if test -z "$gl_replace_getopt"; then + AC_CACHE_CHECK([whether getopt is POSIX compatible], + [gl_cv_func_getopt_posix], + [ + dnl This test fails on mingw and succeeds on many other platforms. + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include + +#if !HAVE_DECL_OPTRESET && !HAVE_DECL_GETOPT_CLIP +# define OPTIND_MIN 0 +#else +# define OPTIND_MIN 1 +#endif + +int +main () +{ + { + int argc = 0; + char *argv[10]; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-a"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = OPTIND_MIN; + opterr = 0; + + c = getopt (argc, argv, "ab"); + if (!(c == 'a')) + return 1; + c = getopt (argc, argv, "ab"); + if (!(c == -1)) + return 2; + if (!(optind == 2)) + return 3; + } + /* Some internal state exists at this point. */ + { + int argc = 0; + char *argv[10]; + int c; + + argv[argc++] = "program"; + argv[argc++] = "donald"; + argv[argc++] = "-p"; + argv[argc++] = "billy"; + argv[argc++] = "duck"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = OPTIND_MIN; + opterr = 0; + + c = getopt (argc, argv, "+abp:q:"); + if (!(c == -1)) + return 4; + if (!(strcmp (argv[0], "program") == 0)) + return 5; + if (!(strcmp (argv[1], "donald") == 0)) + return 6; + if (!(strcmp (argv[2], "-p") == 0)) + return 7; + if (!(strcmp (argv[3], "billy") == 0)) + return 8; + if (!(strcmp (argv[4], "duck") == 0)) + return 9; + if (!(strcmp (argv[5], "-a") == 0)) + return 10; + if (!(strcmp (argv[6], "bar") == 0)) + return 11; + if (!(optind == 1)) + return 12; + } + /* Detect MacOS 10.5, AIX 7.1 bug. */ + { + char *argv[3] = { "program", "-ab", NULL }; + optind = OPTIND_MIN; + opterr = 0; + if (getopt (2, argv, "ab:") != 'a') + return 13; + if (getopt (2, argv, "ab:") != '?') + return 14; + if (optopt != 'b') + return 15; + if (optind != 2) + return 16; + } + + return 0; +} +]])], + [gl_cv_func_getopt_posix=yes], [gl_cv_func_getopt_posix=no], + [case "$host_os" in + mingw*) gl_cv_func_getopt_posix="guessing no";; + darwin* | aix*) gl_cv_func_getopt_posix="guessing no";; + *) gl_cv_func_getopt_posix="guessing yes";; + esac + ]) + ]) + case "$gl_cv_func_getopt_posix" in + *no) gl_replace_getopt=yes ;; + esac + fi + + if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then + AC_CACHE_CHECK([for working GNU getopt function], [gl_cv_func_getopt_gnu], + [# Even with POSIXLY_CORRECT, the GNU extension of leading '-' in the + # optstring is necessary for programs like m4 that have POSIX-mandated + # semantics for supporting options interspersed with files. + # Also, since getopt_long is a GNU extension, we require optind=0. + # Bash ties 'set -o posix' to a non-exported POSIXLY_CORRECT; + # so take care to revert to the correct (non-)export state. +dnl GNU Coding Standards currently allow awk but not env; besides, env +dnl is ambiguous with environment values that contain newlines. + gl_awk_probe='BEGIN { if ("POSIXLY_CORRECT" in ENVIRON) print "x" }' + case ${POSIXLY_CORRECT+x}`$AWK "$gl_awk_probe" + #include + #include + ]], [[ + /* This code succeeds on glibc 2.8, OpenBSD 4.0, Cygwin, mingw, + and fails on MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5, + OSF/1 5.1, Solaris 10. */ + { + char *myargv[3]; + myargv[0] = "conftest"; + myargv[1] = "-+"; + myargv[2] = 0; + opterr = 0; + if (getopt (2, myargv, "+a") != '?') + return 1; + } + /* This code succeeds on glibc 2.8, mingw, + and fails on MacOS X 10.5, OpenBSD 4.0, AIX 5.2, HP-UX 11, + IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x. */ + { + char *argv[] = { "program", "-p", "foo", "bar", NULL }; + + optind = 1; + if (getopt (4, argv, "p::") != 'p') + return 2; + if (optarg != NULL) + return 3; + if (getopt (4, argv, "p::") != -1) + return 4; + if (optind != 2) + return 5; + } + /* This code succeeds on glibc 2.8 and fails on Cygwin 1.7.0. */ + { + char *argv[] = { "program", "foo", "-p", NULL }; + optind = 0; + if (getopt (3, argv, "-p") != 1) + return 6; + if (getopt (3, argv, "-p") != 'p') + return 7; + } + /* This code fails on glibc 2.11. */ + { + char *argv[] = { "program", "-b", "-a", NULL }; + optind = opterr = 0; + if (getopt (3, argv, "+:a:b") != 'b') + return 8; + if (getopt (3, argv, "+:a:b") != ':') + return 9; + } + return 0; + ]])], + [gl_cv_func_getopt_gnu=yes], + [gl_cv_func_getopt_gnu=no], + [dnl Cross compiling. Guess based on host and declarations. + case $host_os:$ac_cv_have_decl_optreset in + *-gnu*:* | mingw*:*) gl_cv_func_getopt_gnu=no;; + *:yes) gl_cv_func_getopt_gnu=no;; + *) gl_cv_func_getopt_gnu=yes;; + esac + ]) + case $gl_had_POSIXLY_CORRECT in + exported) ;; + yes) AS_UNSET([POSIXLY_CORRECT]); POSIXLY_CORRECT=1 ;; + *) AS_UNSET([POSIXLY_CORRECT]) ;; + esac + ]) + if test "$gl_cv_func_getopt_gnu" = "no"; then + gl_replace_getopt=yes + fi + fi +]) + +# emacs' configure.in uses this. +AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER], +[ + GETOPT_H=getopt.h + AC_DEFINE([__GETOPT_PREFIX], [[rpl_]], + [Define to rpl_ if the getopt replacement functions and variables + should be used.]) + AC_SUBST([GETOPT_H]) +]) + +# Prerequisites of lib/getopt*. +# emacs' configure.in uses this. +AC_DEFUN([gl_PREREQ_GETOPT], +[ + AC_CHECK_DECLS_ONCE([getenv]) +]) diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 000000000..979c52c19 --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,401 @@ +# gettext.m4 serial 64 (gettext-0.18.2) +dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006, 2008-2010. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value `$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH([included-gettext], + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE([ENABLE_NLS], [1], + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE([HAVE_GETTEXT], [1], + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE([HAVE_DCGETTEXT], [1], + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST([DATADIRNAME]) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST([INSTOBJEXT]) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST([GENCAT]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST([INTLOBJS]) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST([INTLLIBS]) + + dnl Make all documented variables known to autoconf. + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/m4/glibc2.m4 b/m4/glibc2.m4 new file mode 100644 index 000000000..f148c12c4 --- /dev/null +++ b/m4/glibc2.m4 @@ -0,0 +1,30 @@ +# glibc2.m4 serial 2 +dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2 or newer], + [ac_cv_gnu_library_2], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2=yes], + [ac_cv_gnu_library_2=no]) + ] + ) + AC_SUBST([GLIBC2]) + GLIBC2="$ac_cv_gnu_library_2" + ] +) diff --git a/m4/glibc21.m4 b/m4/glibc21.m4 new file mode 100644 index 000000000..68ada9d4d --- /dev/null +++ b/m4/glibc21.m4 @@ -0,0 +1,30 @@ +# glibc21.m4 serial 4 +dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2.1 or newer], + [ac_cv_gnu_library_2_1], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2_1=yes], + [ac_cv_gnu_library_2_1=no]) + ] + ) + AC_SUBST([GLIBC21]) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 new file mode 100644 index 000000000..3c094bc19 --- /dev/null +++ b/m4/gnulib-cache.m4 @@ -0,0 +1,42 @@ +# 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. +# +# This file represents the specification of how gnulib-tool is used. +# It acts as a cache: It is written and read by gnulib-tool. +# In projects that use version control, this file is meant to be put under +# version control, like the configure.ac and various Makefile.am files. + + +# Specification in the form of a command-line invocation: +# 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 + +# Specification in the form of a few gnulib-tool.m4 macro invocations: +gl_LOCAL_DIR([]) +gl_MODULES([ + argp + error + fnmatch + getdelim + getline + gettext + progname + regex +]) +gl_AVOID([]) +gl_SOURCE_BASE([grub-core/gnulib]) +gl_M4_BASE([m4]) +gl_PO_BASE([]) +gl_DOC_BASE([doc]) +gl_TESTS_BASE([tests]) +gl_LIB([libgnu]) +gl_MAKEFILE_NAME([]) +gl_MACRO_PREFIX([gl]) +gl_PO_DOMAIN([]) +gl_VC_FILES([false]) diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 new file mode 100644 index 000000000..4c7ac30d0 --- /dev/null +++ b/m4/gnulib-common.m4 @@ -0,0 +1,201 @@ +# gnulib-common.m4 serial 20 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# gl_COMMON +# is expanded unconditionally through gnulib-tool magic. +AC_DEFUN([gl_COMMON], [ + dnl Use AC_REQUIRE here, so that the code is expanded once only. + AC_REQUIRE([gl_00GNULIB]) + AC_REQUIRE([gl_COMMON_BODY]) +]) +AC_DEFUN([gl_COMMON_BODY], [ + AH_VERBATIM([isoc99_inline], +[/* Work around a bug in Apple GCC 4.0.1 build 5465: In C99 mode, it supports + the ISO C 99 semantics of 'extern inline' (unlike the GNU C semantics of + earlier versions), but does not display it by setting __GNUC_STDC_INLINE__. + __APPLE__ && __MACH__ test for MacOS X. + __APPLE_CC__ tests for the Apple compiler and its version. + __STDC_VERSION__ tests for the C99 mode. */ +#if defined __APPLE__ && defined __MACH__ && __APPLE_CC__ >= 5465 && !defined __cplusplus && __STDC_VERSION__ >= 199901L && !defined __GNUC_STDC_INLINE__ +# define __GNUC_STDC_INLINE__ 1 +#endif]) + AH_VERBATIM([unused_parameter], +[/* Define as a marker that can be attached to declarations that might not + be used. This helps to reduce warnings, such as from + GCC -Wunused-parameter. */ +#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_UNUSED __attribute__ ((__unused__)) +#else +# define _GL_UNUSED +#endif +/* The name _UNUSED_PARAMETER_ is an earlier spelling, although the name + is a misnomer outside of parameter lists. */ +#define _UNUSED_PARAMETER_ _GL_UNUSED +]) + dnl Preparation for running test programs: + dnl Tell glibc to write diagnostics from -D_FORTIFY_SOURCE=2 to stderr, not + dnl to /dev/tty, so they can be redirected to log files. Such diagnostics + dnl arise e.g., in the macros gl_PRINTF_DIRECTIVE_N, gl_SNPRINTF_DIRECTIVE_N. + LIBC_FATAL_STDERR_=1 + export LIBC_FATAL_STDERR_ +]) + +# gl_MODULE_INDICATOR_CONDITION +# expands to a C preprocessor expression that evaluates to 1 or 0, depending +# whether a gnulib module that has been requested shall be considered present +# or not. +AC_DEFUN([gl_MODULE_INDICATOR_CONDITION], [1]) + +# gl_MODULE_INDICATOR_SET_VARIABLE([modulename]) +# sets the shell variable that indicates the presence of the given module to +# a C preprocessor expression that will evaluate to 1. +AC_DEFUN([gl_MODULE_INDICATOR_SET_VARIABLE], +[ + GNULIB_[]m4_translit([[$1]], + [abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=gl_MODULE_INDICATOR_CONDITION +]) + +# gl_MODULE_INDICATOR([modulename]) +# defines a C macro indicating the presence of the given module +# in a location where it can be used. +# | Value | Value | +# | in lib/ | in tests/ | +# --------------------------------------------+---------+-----------+ +# Module present among main modules: | 1 | 1 | +# --------------------------------------------+---------+-----------+ +# Module present among tests-related modules: | 0 | 1 | +# --------------------------------------------+---------+-----------+ +# Module not present at all: | 0 | 0 | +# --------------------------------------------+---------+-----------+ +AC_DEFUN([gl_MODULE_INDICATOR], +[ + AC_DEFINE_UNQUOTED([GNULIB_]m4_translit([[$1]], + [abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___]), + [gl_MODULE_INDICATOR_CONDITION], + [Define to a C preprocessor expression that evaluates to 1 or 0, + depending whether the gnulib module $1 shall be considered present.]) +]) + +# gl_MODULE_INDICATOR_FOR_TESTS([modulename]) +# defines a C macro indicating the presence of the given module +# in lib or tests. This is useful to determine whether the module +# should be tested. +# | Value | Value | +# | in lib/ | in tests/ | +# --------------------------------------------+---------+-----------+ +# Module present among main modules: | 1 | 1 | +# --------------------------------------------+---------+-----------+ +# Module present among tests-related modules: | 1 | 1 | +# --------------------------------------------+---------+-----------+ +# Module not present at all: | 0 | 0 | +# --------------------------------------------+---------+-----------+ +AC_DEFUN([gl_MODULE_INDICATOR_FOR_TESTS], +[ + AC_DEFINE([GNULIB_TEST_]m4_translit([[$1]], + [abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___]), [1], + [Define to 1 when the gnulib module $1 should be tested.]) +]) + +# m4_foreach_w +# is a backport of autoconf-2.59c's m4_foreach_w. +# Remove this macro when we can assume autoconf >= 2.60. +m4_ifndef([m4_foreach_w], + [m4_define([m4_foreach_w], + [m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])])]) + +# AS_VAR_IF(VAR, VALUE, [IF-MATCH], [IF-NOT-MATCH]) +# ---------------------------------------------------- +# Backport of autoconf-2.63b's macro. +# Remove this macro when we can assume autoconf >= 2.64. +m4_ifndef([AS_VAR_IF], +[m4_define([AS_VAR_IF], +[AS_IF([test x"AS_VAR_GET([$1])" = x""$2], [$3], [$4])])]) + +# AC_PROG_MKDIR_P +# is a backport of autoconf-2.60's AC_PROG_MKDIR_P, with a fix +# for interoperability with automake-1.9.6 from autoconf-2.62. +# Remove this macro when we can assume autoconf >= 2.62 or +# autoconf >= 2.60 && automake >= 1.10. +m4_ifdef([AC_PROG_MKDIR_P], [ + dnl For automake-1.9.6 && autoconf < 2.62: Ensure MKDIR_P is AC_SUBSTed. + m4_define([AC_PROG_MKDIR_P], + m4_defn([AC_PROG_MKDIR_P])[ + AC_SUBST([MKDIR_P])])], [ + dnl For autoconf < 2.60: Backport of AC_PROG_MKDIR_P. + AC_DEFUN_ONCE([AC_PROG_MKDIR_P], + [AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + MKDIR_P='$(mkdir_p)' + AC_SUBST([MKDIR_P])])]) + +# AC_C_RESTRICT +# This definition overrides the AC_C_RESTRICT macro from autoconf 2.60..2.61, +# so that mixed use of GNU C and GNU C++ and mixed use of Sun C and Sun C++ +# works. +# This definition can be removed once autoconf >= 2.62 can be assumed. +m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.62]),[-1],[ +AC_DEFUN([AC_C_RESTRICT], +[AC_CACHE_CHECK([for C/C++ restrict keyword], [ac_cv_c_restrict], + [ac_cv_c_restrict=no + # The order here caters to the fact that C++ does not require restrict. + for ac_kw in __restrict __restrict__ _Restrict restrict; do + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[typedef int * int_ptr; + int foo (int_ptr $ac_kw ip) { + return ip[0]; + }]], + [[int s[1]; + int * $ac_kw t = s; + t[0] = 0; + return foo(t)]])], + [ac_cv_c_restrict=$ac_kw]) + test "$ac_cv_c_restrict" != no && break + done + ]) + AH_VERBATIM([restrict], +[/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#undef restrict +/* Work around a bug in Sun C++: it does not support _Restrict, even + though the corresponding Sun C compiler does, which causes + "#define restrict _Restrict" in the previous line. Perhaps some future + version of Sun C++ will work with _Restrict; if so, it'll probably + define __RESTRICT, just as Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +#endif]) + case $ac_cv_c_restrict in + restrict) ;; + no) AC_DEFINE([restrict], []) ;; + *) AC_DEFINE_UNQUOTED([restrict], [$ac_cv_c_restrict]) ;; + esac +]) +]) + +# gl_BIGENDIAN +# is like AC_C_BIGENDIAN, except that it can be AC_REQUIREd. +# Note that AC_REQUIRE([AC_C_BIGENDIAN]) does not work reliably because some +# macros invoke AC_C_BIGENDIAN with arguments. +AC_DEFUN([gl_BIGENDIAN], +[ + AC_C_BIGENDIAN +]) + +# gl_CACHE_VAL_SILENT(cache-id, command-to-set-it) +# is like AC_CACHE_VAL(cache-id, command-to-set-it), except that it does not +# output a spurious "(cached)" mark in the midst of other configure output. +# This macro should be used instead of AC_CACHE_VAL when it is not surrounded +# by an AC_MSG_CHECKING/AC_MSG_RESULT pair. +AC_DEFUN([gl_CACHE_VAL_SILENT], +[ + saved_as_echo_n="$as_echo_n" + as_echo_n=':' + AC_CACHE_VAL([$1], [$2]) + as_echo_n="$saved_as_echo_n" +]) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 new file mode 100644 index 000000000..d3490c932 --- /dev/null +++ b/m4/gnulib-comp.m4 @@ -0,0 +1,601 @@ +# DO NOT EDIT! GENERATED AUTOMATICALLY! +# 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. +# +# This file represents the compiled summary of the specification in +# gnulib-cache.m4. It lists the computed macro invocations that need +# to be invoked from configure.ac. +# In projects that use version control, this file can be treated like +# other built files. + + +# This macro should be invoked from ./configure.ac, in the section +# "Checks for programs", right after AC_PROG_CC, and certainly before +# any checks for libraries, header files, types and library functions. +AC_DEFUN([gl_EARLY], +[ + m4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace + m4_pattern_allow([^gl_ES$])dnl a valid locale name + m4_pattern_allow([^gl_LIBOBJS$])dnl a variable + m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable + AC_REQUIRE([AC_PROG_RANLIB]) + # Code from module alloca: + # Code from module alloca-opt: + # Code from module arg-nonnull: + # Code from module argp: + # Code from module btowc: + # Code from module c++defs: + # Code from module configmake: + # Code from module dirname-lgpl: + # Code from module double-slash-root: + # Code from module errno: + # Code from module error: + # Code from module extensions: + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + # Code from module float: + # Code from module fnmatch: + # Code from module getdelim: + # Code from module getline: + # Code from module getopt-gnu: + # Code from module getopt-posix: + # Code from module gettext: + # Code from module gettext-h: + # Code from module havelib: + # Code from module include_next: + # Code from module intprops: + # Code from module langinfo: + # Code from module localcharset: + # Code from module malloc-gnu: + # Code from module malloc-posix: + # Code from module mbrtowc: + # Code from module mbsinit: + # Code from module mbsrtowcs: + # Code from module memchr: + # Code from module mempcpy: + # Code from module multiarch: + # Code from module nl_langinfo: + # Code from module progname: + # Code from module rawmemchr: + # Code from module realloc-posix: + # Code from module regex: + # Code from module size_max: + # Code from module sleep: + # Code from module ssize_t: + # Code from module stdbool: + # Code from module stddef: + # Code from module stdint: + # Code from module stdio: + # Code from module stdlib: + # Code from module strcase: + # Code from module strchrnul: + # Code from module streq: + # Code from module strerror: + # Code from module string: + # Code from module strings: + # Code from module strndup: + # Code from module strnlen: + # Code from module strnlen1: + # Code from module sys_wait: + # Code from module sysexits: + # Code from module unistd: + # Code from module vasnprintf: + # Code from module verify: + # Code from module vsnprintf: + # Code from module warn-on-use: + # Code from module wchar: + # Code from module wcrtomb: + # Code from module wctype: + # Code from module xsize: +]) + +# This macro should be invoked from ./configure.ac, in the section +# "Check for header files, types and library functions". +AC_DEFUN([gl_INIT], +[ + AM_CONDITIONAL([GL_COND_LIBTOOL], [false]) + gl_cond_libtool=false + gl_libdeps= + gl_ltlibdeps= + gl_m4_base='m4' + m4_pushdef([AC_LIBOBJ], m4_defn([gl_LIBOBJ])) + m4_pushdef([AC_REPLACE_FUNCS], m4_defn([gl_REPLACE_FUNCS])) + m4_pushdef([AC_LIBSOURCES], m4_defn([gl_LIBSOURCES])) + m4_pushdef([gl_LIBSOURCES_LIST], []) + m4_pushdef([gl_LIBSOURCES_DIR], []) + gl_COMMON + gl_source_base='grub-core/gnulib' + # Code from module alloca: + # Code from module alloca-opt: + gl_FUNC_ALLOCA + # Code from module arg-nonnull: + # Code from module argp: + gl_ARGP + m4_ifdef([AM_XGETTEXT_OPTION], + [AM_][XGETTEXT_OPTION([--flag=argp_error:2:c-format]) + AM_][XGETTEXT_OPTION([--flag=argp_failure:4:c-format])]) + # Code from module btowc: + gl_FUNC_BTOWC + gl_WCHAR_MODULE_INDICATOR([btowc]) + # Code from module c++defs: + # Code from module configmake: + # Code from module dirname-lgpl: + gl_DIRNAME_LGPL + # Code from module double-slash-root: + gl_DOUBLE_SLASH_ROOT + # Code from module errno: + gl_HEADER_ERRNO_H + # Code from module error: + gl_ERROR + m4_ifdef([AM_XGETTEXT_OPTION], + [AM_][XGETTEXT_OPTION([--flag=error:3:c-format]) + AM_][XGETTEXT_OPTION([--flag=error_at_line:5:c-format])]) + # Code from module extensions: + # Code from module float: + gl_FLOAT_H + # Code from module fnmatch: + gl_FUNC_FNMATCH_POSIX + # Code from module getdelim: + gl_FUNC_GETDELIM + gl_STDIO_MODULE_INDICATOR([getdelim]) + # Code from module getline: + gl_FUNC_GETLINE + gl_STDIO_MODULE_INDICATOR([getline]) + # Code from module getopt-gnu: + gl_FUNC_GETOPT_GNU + gl_MODULE_INDICATOR_FOR_TESTS([getopt-gnu]) + # Code from module getopt-posix: + gl_FUNC_GETOPT_POSIX + # Code from module gettext: + dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac. + AM_GNU_GETTEXT_VERSION([0.18.1]) + # Code from module gettext-h: + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + # Code from module havelib: + # Code from module include_next: + # Code from module intprops: + # Code from module langinfo: + gl_LANGINFO_H + # Code from module localcharset: + gl_LOCALCHARSET + LOCALCHARSET_TESTS_ENVIRONMENT="CHARSETALIASDIR=\"\$(top_builddir)/$gl_source_base\"" + AC_SUBST([LOCALCHARSET_TESTS_ENVIRONMENT]) + # Code from module malloc-gnu: + gl_FUNC_MALLOC_GNU + gl_MODULE_INDICATOR([malloc-gnu]) + # Code from module malloc-posix: + gl_FUNC_MALLOC_POSIX + gl_STDLIB_MODULE_INDICATOR([malloc-posix]) + # Code from module mbrtowc: + gl_FUNC_MBRTOWC + gl_WCHAR_MODULE_INDICATOR([mbrtowc]) + # Code from module mbsinit: + gl_FUNC_MBSINIT + gl_WCHAR_MODULE_INDICATOR([mbsinit]) + # Code from module mbsrtowcs: + gl_FUNC_MBSRTOWCS + gl_WCHAR_MODULE_INDICATOR([mbsrtowcs]) + # Code from module memchr: + gl_FUNC_MEMCHR + gl_STRING_MODULE_INDICATOR([memchr]) + # Code from module mempcpy: + gl_FUNC_MEMPCPY + gl_STRING_MODULE_INDICATOR([mempcpy]) + # Code from module multiarch: + gl_MULTIARCH + # Code from module nl_langinfo: + gl_FUNC_NL_LANGINFO + gl_LANGINFO_MODULE_INDICATOR([nl_langinfo]) + # Code from module progname: + AC_CHECK_DECLS([program_invocation_name], [], [], [#include ]) + AC_CHECK_DECLS([program_invocation_short_name], [], [], [#include ]) + # Code from module rawmemchr: + gl_FUNC_RAWMEMCHR + gl_STRING_MODULE_INDICATOR([rawmemchr]) + # Code from module realloc-posix: + gl_FUNC_REALLOC_POSIX + gl_STDLIB_MODULE_INDICATOR([realloc-posix]) + # Code from module regex: + gl_REGEX + # Code from module size_max: + gl_SIZE_MAX + # Code from module sleep: + gl_FUNC_SLEEP + gl_UNISTD_MODULE_INDICATOR([sleep]) + # Code from module ssize_t: + gt_TYPE_SSIZE_T + # Code from module stdbool: + AM_STDBOOL_H + # Code from module stddef: + gl_STDDEF_H + # Code from module stdint: + gl_STDINT_H + # Code from module stdio: + gl_STDIO_H + # Code from module stdlib: + gl_STDLIB_H + # Code from module strcase: + gl_STRCASE + # Code from module strchrnul: + gl_FUNC_STRCHRNUL + gl_STRING_MODULE_INDICATOR([strchrnul]) + # Code from module streq: + # Code from module strerror: + gl_FUNC_STRERROR + gl_STRING_MODULE_INDICATOR([strerror]) + # Code from module string: + gl_HEADER_STRING_H + # Code from module strings: + gl_HEADER_STRINGS_H + # Code from module strndup: + gl_FUNC_STRNDUP + gl_STRING_MODULE_INDICATOR([strndup]) + # Code from module strnlen: + gl_FUNC_STRNLEN + gl_STRING_MODULE_INDICATOR([strnlen]) + # Code from module strnlen1: + # Code from module sys_wait: + gl_SYS_WAIT_H + AC_PROG_MKDIR_P + # Code from module sysexits: + gl_SYSEXITS + # Code from module unistd: + gl_UNISTD_H + # Code from module vasnprintf: + gl_FUNC_VASNPRINTF + # Code from module verify: + # Code from module vsnprintf: + gl_FUNC_VSNPRINTF + gl_STDIO_MODULE_INDICATOR([vsnprintf]) + # Code from module warn-on-use: + # Code from module wchar: + gl_WCHAR_H + # Code from module wcrtomb: + gl_FUNC_WCRTOMB + gl_WCHAR_MODULE_INDICATOR([wcrtomb]) + # Code from module wctype: + gl_WCTYPE_H + # Code from module xsize: + gl_XSIZE + # End of code from modules + m4_ifval(gl_LIBSOURCES_LIST, [ + m4_syscmd([test ! -d ]m4_defn([gl_LIBSOURCES_DIR])[ || + for gl_file in ]gl_LIBSOURCES_LIST[ ; do + if test ! -r ]m4_defn([gl_LIBSOURCES_DIR])[/$gl_file ; then + echo "missing file ]m4_defn([gl_LIBSOURCES_DIR])[/$gl_file" >&2 + exit 1 + fi + done])dnl + m4_if(m4_sysval, [0], [], + [AC_FATAL([expected source file, required through AC_LIBSOURCES, not found])]) + ]) + m4_popdef([gl_LIBSOURCES_DIR]) + m4_popdef([gl_LIBSOURCES_LIST]) + m4_popdef([AC_LIBSOURCES]) + m4_popdef([AC_REPLACE_FUNCS]) + m4_popdef([AC_LIBOBJ]) + AC_CONFIG_COMMANDS_PRE([ + gl_libobjs= + gl_ltlibobjs= + if test -n "$gl_LIBOBJS"; then + # Remove the extension. + sed_drop_objext='s/\.o$//;s/\.obj$//' + for i in `for i in $gl_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do + gl_libobjs="$gl_libobjs $i.$ac_objext" + gl_ltlibobjs="$gl_ltlibobjs $i.lo" + done + fi + AC_SUBST([gl_LIBOBJS], [$gl_libobjs]) + AC_SUBST([gl_LTLIBOBJS], [$gl_ltlibobjs]) + ]) + gltests_libdeps= + gltests_ltlibdeps= + m4_pushdef([AC_LIBOBJ], m4_defn([gltests_LIBOBJ])) + m4_pushdef([AC_REPLACE_FUNCS], m4_defn([gltests_REPLACE_FUNCS])) + m4_pushdef([AC_LIBSOURCES], m4_defn([gltests_LIBSOURCES])) + m4_pushdef([gltests_LIBSOURCES_LIST], []) + m4_pushdef([gltests_LIBSOURCES_DIR], []) + gl_COMMON + gl_source_base='tests' +changequote(,)dnl + gltests_WITNESS=IN_`echo "${PACKAGE-$PACKAGE_TARNAME}" | LC_ALL=C tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | LC_ALL=C sed -e 's/[^A-Z0-9_]/_/g'`_GNULIB_TESTS +changequote([, ])dnl + AC_SUBST([gltests_WITNESS]) + gl_module_indicator_condition=$gltests_WITNESS + m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [$gl_module_indicator_condition]) + m4_popdef([gl_MODULE_INDICATOR_CONDITION]) + m4_ifval(gltests_LIBSOURCES_LIST, [ + m4_syscmd([test ! -d ]m4_defn([gltests_LIBSOURCES_DIR])[ || + for gl_file in ]gltests_LIBSOURCES_LIST[ ; do + if test ! -r ]m4_defn([gltests_LIBSOURCES_DIR])[/$gl_file ; then + echo "missing file ]m4_defn([gltests_LIBSOURCES_DIR])[/$gl_file" >&2 + exit 1 + fi + done])dnl + m4_if(m4_sysval, [0], [], + [AC_FATAL([expected source file, required through AC_LIBSOURCES, not found])]) + ]) + m4_popdef([gltests_LIBSOURCES_DIR]) + m4_popdef([gltests_LIBSOURCES_LIST]) + m4_popdef([AC_LIBSOURCES]) + m4_popdef([AC_REPLACE_FUNCS]) + m4_popdef([AC_LIBOBJ]) + AC_CONFIG_COMMANDS_PRE([ + gltests_libobjs= + gltests_ltlibobjs= + if test -n "$gltests_LIBOBJS"; then + # Remove the extension. + sed_drop_objext='s/\.o$//;s/\.obj$//' + for i in `for i in $gltests_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do + gltests_libobjs="$gltests_libobjs $i.$ac_objext" + gltests_ltlibobjs="$gltests_ltlibobjs $i.lo" + done + fi + AC_SUBST([gltests_LIBOBJS], [$gltests_libobjs]) + AC_SUBST([gltests_LTLIBOBJS], [$gltests_ltlibobjs]) + ]) + LIBGNU_LIBDEPS="$gl_libdeps" + AC_SUBST([LIBGNU_LIBDEPS]) + LIBGNU_LTLIBDEPS="$gl_ltlibdeps" + AC_SUBST([LIBGNU_LTLIBDEPS]) +]) + +# Like AC_LIBOBJ, except that the module name goes +# into gl_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gl_LIBOBJ], [ + AS_LITERAL_IF([$1], [gl_LIBSOURCES([$1.c])])dnl + gl_LIBOBJS="$gl_LIBOBJS $1.$ac_objext" +]) + +# Like AC_REPLACE_FUNCS, except that the module name goes +# into gl_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gl_REPLACE_FUNCS], [ + m4_foreach_w([gl_NAME], [$1], [AC_LIBSOURCES(gl_NAME[.c])])dnl + AC_CHECK_FUNCS([$1], , [gl_LIBOBJ($ac_func)]) +]) + +# Like AC_LIBSOURCES, except the directory where the source file is +# expected is derived from the gnulib-tool parameterization, +# and alloca is special cased (for the alloca-opt module). +# We could also entirely rely on EXTRA_lib..._SOURCES. +AC_DEFUN([gl_LIBSOURCES], [ + m4_foreach([_gl_NAME], [$1], [ + m4_if(_gl_NAME, [alloca.c], [], [ + m4_define([gl_LIBSOURCES_DIR], [grub-core/gnulib]) + m4_append([gl_LIBSOURCES_LIST], _gl_NAME, [ ]) + ]) + ]) +]) + +# Like AC_LIBOBJ, except that the module name goes +# into gltests_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gltests_LIBOBJ], [ + AS_LITERAL_IF([$1], [gltests_LIBSOURCES([$1.c])])dnl + gltests_LIBOBJS="$gltests_LIBOBJS $1.$ac_objext" +]) + +# Like AC_REPLACE_FUNCS, except that the module name goes +# into gltests_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gltests_REPLACE_FUNCS], [ + m4_foreach_w([gl_NAME], [$1], [AC_LIBSOURCES(gl_NAME[.c])])dnl + AC_CHECK_FUNCS([$1], , [gltests_LIBOBJ($ac_func)]) +]) + +# Like AC_LIBSOURCES, except the directory where the source file is +# expected is derived from the gnulib-tool parameterization, +# and alloca is special cased (for the alloca-opt module). +# We could also entirely rely on EXTRA_lib..._SOURCES. +AC_DEFUN([gltests_LIBSOURCES], [ + m4_foreach([_gl_NAME], [$1], [ + m4_if(_gl_NAME, [alloca.c], [], [ + m4_define([gltests_LIBSOURCES_DIR], [tests]) + m4_append([gltests_LIBSOURCES_LIST], _gl_NAME, [ ]) + ]) + ]) +]) + +# This macro records the list of files which have been installed by +# gnulib-tool and may be removed by future gnulib-tool invocations. +AC_DEFUN([gl_FILE_LIST], [ + build-aux/arg-nonnull.h + build-aux/c++defs.h + build-aux/config.rpath + build-aux/warn-on-use.h + lib/alloca.c + lib/alloca.in.h + lib/argp-ba.c + lib/argp-eexst.c + lib/argp-fmtstream.c + lib/argp-fmtstream.h + lib/argp-fs-xinl.c + lib/argp-help.c + lib/argp-namefrob.h + lib/argp-parse.c + lib/argp-pin.c + lib/argp-pv.c + lib/argp-pvh.c + lib/argp-xinl.c + lib/argp.h + lib/asnprintf.c + lib/basename-lgpl.c + lib/btowc.c + lib/config.charset + lib/dirname-lgpl.c + lib/dirname.h + lib/errno.in.h + lib/error.c + lib/error.h + lib/float+.h + lib/float.in.h + lib/fnmatch.c + lib/fnmatch.in.h + lib/fnmatch_loop.c + lib/getdelim.c + lib/getline.c + lib/getopt.c + lib/getopt.in.h + lib/getopt1.c + lib/getopt_int.h + lib/gettext.h + lib/intprops.h + lib/langinfo.in.h + lib/localcharset.c + lib/localcharset.h + lib/malloc.c + lib/mbrtowc.c + lib/mbsinit.c + lib/mbsrtowcs-state.c + lib/mbsrtowcs.c + lib/memchr.c + lib/memchr.valgrind + lib/mempcpy.c + lib/nl_langinfo.c + lib/printf-args.c + lib/printf-args.h + lib/printf-parse.c + lib/printf-parse.h + lib/progname.c + lib/progname.h + lib/rawmemchr.c + lib/rawmemchr.valgrind + lib/realloc.c + lib/ref-add.sin + lib/ref-del.sin + lib/regcomp.c + lib/regex.c + lib/regex.h + lib/regex_internal.c + lib/regex_internal.h + lib/regexec.c + lib/size_max.h + lib/sleep.c + lib/stdbool.in.h + lib/stddef.in.h + lib/stdint.in.h + lib/stdio-write.c + lib/stdio.in.h + lib/stdlib.in.h + lib/strcasecmp.c + lib/strchrnul.c + lib/strchrnul.valgrind + lib/streq.h + lib/strerror.c + lib/string.in.h + lib/strings.in.h + lib/stripslash.c + lib/strncasecmp.c + lib/strndup.c + lib/strnlen.c + lib/strnlen1.c + lib/strnlen1.h + lib/sys_wait.in.h + lib/sysexits.in.h + lib/unistd.in.h + lib/vasnprintf.c + lib/vasnprintf.h + lib/verify.h + lib/vsnprintf.c + lib/wchar.in.h + lib/wcrtomb.c + lib/wctype.in.h + lib/xsize.h + m4/00gnulib.m4 + m4/alloca.m4 + m4/argp.m4 + m4/asm-underscore.m4 + m4/btowc.m4 + m4/codeset.m4 + m4/dirname.m4 + m4/dos.m4 + m4/double-slash-root.m4 + m4/errno_h.m4 + m4/error.m4 + m4/extensions.m4 + m4/fcntl-o.m4 + m4/float_h.m4 + m4/fnmatch.m4 + m4/getdelim.m4 + m4/getline.m4 + m4/getopt.m4 + m4/gettext.m4 + m4/glibc2.m4 + m4/glibc21.m4 + m4/gnulib-common.m4 + m4/iconv.m4 + m4/include_next.m4 + m4/intdiv0.m4 + m4/intl.m4 + m4/intldir.m4 + m4/intlmacosx.m4 + m4/intmax.m4 + m4/intmax_t.m4 + m4/inttypes-pri.m4 + m4/inttypes_h.m4 + m4/langinfo_h.m4 + m4/lcmessage.m4 + m4/lib-ld.m4 + m4/lib-link.m4 + m4/lib-prefix.m4 + m4/localcharset.m4 + m4/locale-fr.m4 + m4/locale-ja.m4 + m4/locale-zh.m4 + m4/lock.m4 + m4/longlong.m4 + m4/malloc.m4 + m4/mbrtowc.m4 + m4/mbsinit.m4 + m4/mbsrtowcs.m4 + m4/mbstate_t.m4 + m4/memchr.m4 + m4/mempcpy.m4 + m4/mmap-anon.m4 + m4/multiarch.m4 + m4/nl_langinfo.m4 + m4/nls.m4 + m4/po.m4 + m4/printf-posix.m4 + m4/printf.m4 + m4/progtest.m4 + m4/rawmemchr.m4 + m4/realloc.m4 + m4/regex.m4 + m4/size_max.m4 + m4/sleep.m4 + m4/ssize_t.m4 + m4/stdbool.m4 + m4/stddef_h.m4 + m4/stdint.m4 + m4/stdint_h.m4 + m4/stdio_h.m4 + m4/stdlib_h.m4 + m4/strcase.m4 + m4/strchrnul.m4 + m4/strerror.m4 + m4/string_h.m4 + m4/strings_h.m4 + m4/strndup.m4 + m4/strnlen.m4 + m4/sys_wait_h.m4 + m4/sysexits.m4 + m4/threadlib.m4 + m4/uintmax_t.m4 + m4/unistd_h.m4 + m4/vasnprintf.m4 + m4/visibility.m4 + m4/vsnprintf.m4 + m4/warn-on-use.m4 + m4/wchar_h.m4 + m4/wchar_t.m4 + m4/wcrtomb.m4 + m4/wctype_h.m4 + m4/wint_t.m4 + m4/xsize.m4 +]) diff --git a/m4/gnulib-tool.m4 b/m4/gnulib-tool.m4 new file mode 100644 index 000000000..69e7733b9 --- /dev/null +++ b/m4/gnulib-tool.m4 @@ -0,0 +1,57 @@ +# gnulib-tool.m4 serial 2 +dnl Copyright (C) 2004-2005, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl The following macros need not be invoked explicitly. +dnl Invoking them does nothing except to declare default arguments +dnl for "gnulib-tool --import". + +dnl Usage: gl_LOCAL_DIR([DIR]) +AC_DEFUN([gl_LOCAL_DIR], []) + +dnl Usage: gl_MODULES([module1 module2 ...]) +AC_DEFUN([gl_MODULES], []) + +dnl Usage: gl_AVOID([module1 module2 ...]) +AC_DEFUN([gl_AVOID], []) + +dnl Usage: gl_SOURCE_BASE([DIR]) +AC_DEFUN([gl_SOURCE_BASE], []) + +dnl Usage: gl_M4_BASE([DIR]) +AC_DEFUN([gl_M4_BASE], []) + +dnl Usage: gl_PO_BASE([DIR]) +AC_DEFUN([gl_PO_BASE], []) + +dnl Usage: gl_DOC_BASE([DIR]) +AC_DEFUN([gl_DOC_BASE], []) + +dnl Usage: gl_TESTS_BASE([DIR]) +AC_DEFUN([gl_TESTS_BASE], []) + +dnl Usage: gl_WITH_TESTS +AC_DEFUN([gl_WITH_TESTS], []) + +dnl Usage: gl_LIB([LIBNAME]) +AC_DEFUN([gl_LIB], []) + +dnl Usage: gl_LGPL or gl_LGPL([VERSION]) +AC_DEFUN([gl_LGPL], []) + +dnl Usage: gl_MAKEFILE_NAME([FILENAME]) +AC_DEFUN([gl_MAKEFILE_NAME], []) + +dnl Usage: gl_LIBTOOL +AC_DEFUN([gl_LIBTOOL], []) + +dnl Usage: gl_MACRO_PREFIX([PREFIX]) +AC_DEFUN([gl_MACRO_PREFIX], []) + +dnl Usage: gl_PO_DOMAIN([DOMAIN]) +AC_DEFUN([gl_PO_DOMAIN], []) + +dnl Usage: gl_VC_FILES([BOOLEAN]) +AC_DEFUN([gl_VC_FILES], []) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 000000000..425145c0a --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,256 @@ +# iconv.m4 serial 15 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +int main () +{ + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + return 1; + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + return 1; + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + return 1; + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + return 1; + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + return 1; + return 0; +}]])], + [am_cv_func_iconv_works=yes], + [am_cv_func_iconv_works=no], + [ +changequote(,)dnl + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +changequote([,])dnl + ]) + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + fi +]) diff --git a/m4/include_next.m4 b/m4/include_next.m4 new file mode 100644 index 000000000..51a719b0a --- /dev/null +++ b/m4/include_next.m4 @@ -0,0 +1,192 @@ +# include_next.m4 serial 15 +dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert and Derek Price. + +dnl Sets INCLUDE_NEXT and PRAGMA_SYSTEM_HEADER. +dnl +dnl INCLUDE_NEXT expands to 'include_next' if the compiler supports it, or to +dnl 'include' otherwise. +dnl +dnl INCLUDE_NEXT_AS_FIRST_DIRECTIVE expands to 'include_next' if the compiler +dnl supports it in the special case that it is the first include directive in +dnl the given file, or to 'include' otherwise. +dnl +dnl PRAGMA_SYSTEM_HEADER can be used in files that contain #include_next, +dnl so as to avoid GCC warnings when the gcc option -pedantic is used. +dnl '#pragma GCC system_header' has the same effect as if the file was found +dnl through the include search path specified with '-isystem' options (as +dnl opposed to the search path specified with '-I' options). Namely, gcc +dnl does not warn about some things, and on some systems (Solaris and Interix) +dnl __STDC__ evaluates to 0 instead of to 1. The latter is an undesired side +dnl effect; we are therefore careful to use 'defined __STDC__' or '1' instead +dnl of plain '__STDC__'. + +AC_DEFUN([gl_INCLUDE_NEXT], +[ + AC_LANG_PREPROC_REQUIRE() + AC_CACHE_CHECK([whether the preprocessor supports include_next], + [gl_cv_have_include_next], + [rm -rf conftestd1a conftestd1b conftestd2 + mkdir conftestd1a conftestd1b conftestd2 + dnl IBM C 9.0, 10.1 (original versions, prior to the 2009-01 updates) on + dnl AIX 6.1 support include_next when used as first preprocessor directive + dnl in a file, but not when preceded by another include directive. Check + dnl for this bug by including . + dnl Additionally, with this same compiler, include_next is a no-op when + dnl used in a header file that was included by specifying its absolute + dnl file name. Despite these two bugs, include_next is used in the + dnl compiler's . By virtue of the second bug, we need to use + dnl include_next as well in this case. + cat < conftestd1a/conftest.h +#define DEFINED_IN_CONFTESTD1 +#include_next +#ifdef DEFINED_IN_CONFTESTD2 +int foo; +#else +#error "include_next doesn't work" +#endif +EOF + cat < conftestd1b/conftest.h +#define DEFINED_IN_CONFTESTD1 +#include +#include_next +#ifdef DEFINED_IN_CONFTESTD2 +int foo; +#else +#error "include_next doesn't work" +#endif +EOF + cat < conftestd2/conftest.h +#ifndef DEFINED_IN_CONFTESTD1 +#error "include_next test doesn't work" +#endif +#define DEFINED_IN_CONFTESTD2 +EOF + gl_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1b -Iconftestd2" +dnl We intentionally avoid using AC_LANG_SOURCE here. + AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include ]], + [gl_cv_have_include_next=yes], + [CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1a -Iconftestd2" + AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include ]], + [gl_cv_have_include_next=buggy], + [gl_cv_have_include_next=no]) + ]) + CPPFLAGS="$gl_save_CPPFLAGS" + rm -rf conftestd1a conftestd1b conftestd2 + ]) + PRAGMA_SYSTEM_HEADER= + if test $gl_cv_have_include_next = yes; then + INCLUDE_NEXT=include_next + INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include_next + if test -n "$GCC"; then + PRAGMA_SYSTEM_HEADER='#pragma GCC system_header' + fi + else + if test $gl_cv_have_include_next = buggy; then + INCLUDE_NEXT=include + INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include_next + else + INCLUDE_NEXT=include + INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include + fi + fi + AC_SUBST([INCLUDE_NEXT]) + AC_SUBST([INCLUDE_NEXT_AS_FIRST_DIRECTIVE]) + AC_SUBST([PRAGMA_SYSTEM_HEADER]) +]) + +# gl_CHECK_NEXT_HEADERS(HEADER1 HEADER2 ...) +# ------------------------------------------ +# For each arg foo.h, if #include_next works, define NEXT_FOO_H to be +# ''; otherwise define it to be +# '"///usr/include/foo.h"', or whatever other absolute file name is suitable. +# Also, if #include_next works as first preprocessing directive in a file, +# define NEXT_AS_FIRST_DIRECTIVE_FOO_H to be ''; otherwise define it to +# be +# '"///usr/include/foo.h"', or whatever other absolute file name is suitable. +# That way, a header file with the following line: +# #@INCLUDE_NEXT@ @NEXT_FOO_H@ +# or +# #@INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ @NEXT_AS_FIRST_DIRECTIVE_FOO_H@ +# behaves (after sed substitution) as if it contained +# #include_next +# even if the compiler does not support include_next. +# The three "///" are to pacify Sun C 5.8, which otherwise would say +# "warning: #include of /usr/include/... may be non-portable". +# Use `""', not `<>', so that the /// cannot be confused with a C99 comment. +# Note: This macro assumes that the header file is not empty after +# preprocessing, i.e. it does not only define preprocessor macros but also +# provides some type/enum definitions or function/variable declarations. +AC_DEFUN([gl_CHECK_NEXT_HEADERS], +[ + AC_REQUIRE([gl_INCLUDE_NEXT]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CHECK_HEADERS_ONCE([$1]) + + m4_foreach_w([gl_HEADER_NAME], [$1], + [AS_VAR_PUSHDEF([gl_next_header], + [gl_cv_next_]m4_defn([gl_HEADER_NAME])) + if test $gl_cv_have_include_next = yes; then + AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) + else + AC_CACHE_CHECK( + [absolute name of <]m4_defn([gl_HEADER_NAME])[>], + m4_defn([gl_next_header]), + [AS_VAR_PUSHDEF([gl_header_exists], + [ac_cv_header_]m4_defn([gl_HEADER_NAME])) + if test AS_VAR_GET(gl_header_exists) = yes; then + AC_LANG_CONFTEST( + [AC_LANG_SOURCE( + [[#include <]]m4_dquote(m4_defn([gl_HEADER_NAME]))[[>]] + )]) + dnl AIX "xlc -E" and "cc -E" omit #line directives for header files + dnl that contain only a #include of other header files and no + dnl non-comment tokens of their own. This leads to a failure to + dnl detect the absolute name of , , + dnl and others. The workaround is to force preservation of comments + dnl through option -C. This ensures all necessary #line directives + dnl are present. GCC supports option -C as well. + case "$host_os" in + aix*) gl_absname_cpp="$ac_cpp -C" ;; + *) gl_absname_cpp="$ac_cpp" ;; + esac + dnl eval is necessary to expand gl_absname_cpp. + dnl Ultrix and Pyramid sh refuse to redirect output of eval, + dnl so use subshell. + AS_VAR_SET([gl_next_header], + ['"'`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + sed -n '\#/]m4_defn([gl_HEADER_NAME])[#{ + s#.*"\(.*/]m4_defn([gl_HEADER_NAME])[\)".*#\1# + s#^/[^/]#//&# + p + q + }'`'"']) + else + AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) + fi + AS_VAR_POPDEF([gl_header_exists])]) + fi + AC_SUBST( + AS_TR_CPP([NEXT_]m4_defn([gl_HEADER_NAME])), + [AS_VAR_GET([gl_next_header])]) + if test $gl_cv_have_include_next = yes || test $gl_cv_have_include_next = buggy; then + # INCLUDE_NEXT_AS_FIRST_DIRECTIVE='include_next' + gl_next_as_first_directive='<'gl_HEADER_NAME'>' + else + # INCLUDE_NEXT_AS_FIRST_DIRECTIVE='include' + gl_next_as_first_directive=AS_VAR_GET([gl_next_header]) + fi + AC_SUBST( + AS_TR_CPP([NEXT_AS_FIRST_DIRECTIVE_]m4_defn([gl_HEADER_NAME])), + [$gl_next_as_first_directive]) + AS_VAR_POPDEF([gl_next_header])]) +]) + +# Autoconf 2.68 added warnings for our use of AC_COMPILE_IFELSE; +# this fallback is safe for all earlier autoconf versions. +m4_define_default([AC_LANG_DEFINES_PROVIDED]) diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4 new file mode 100644 index 000000000..9b27ff1b7 --- /dev/null +++ b/m4/intdiv0.m4 @@ -0,0 +1,87 @@ +# intdiv0.m4 serial 4 (gettext-0.18.2) +dnl Copyright (C) 2002, 2007-2008, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + gt_cv_int_divbyzero_sigfpe= +changequote(,)dnl + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On MacOS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac +changequote([,])dnl + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +]])], + [gt_cv_int_divbyzero_sigfpe=yes], + [gt_cv_int_divbyzero_sigfpe=no], + [ + # Guess based on the CPU. +changequote(,)dnl + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac +changequote([,])dnl + ]) + fi + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value], + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/m4/intl.m4 b/m4/intl.m4 new file mode 100644 index 000000000..d84bc4a9b --- /dev/null +++ b/m4/intl.m4 @@ -0,0 +1,300 @@ +# intl.m4 serial 17b +dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2009. + +AC_PREREQ([2.53]) + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + + dnl Support for automake's --enable-silent-rules. + case "$enable_silent_rules" in + yes) INTL_DEFAULT_VERBOSITY=0;; + no) INTL_DEFAULT_VERBOSITY=1;; + *) INTL_DEFAULT_VERBOSITY=1;; + esac + AC_SUBST([INTL_DEFAULT_VERBOSITY]) + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf newlocale putenv setenv setlocale \ + snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include ]) + gt_CHECK_DECL(_snwprintf, [#include ]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(getc_unlocked, [#include ]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_newlocale" = yes; then + HAVE_NEWLOCALE=1 + else + HAVE_NEWLOCALE=0 + fi + AC_SUBST([HAVE_NEWLOCALE]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl On mingw and Cygwin, we can activate special Makefile rules which add + dnl version information to the shared libraries and executables. + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + AC_SUBST([WOE32]) + if test $WOE32 = yes; then + dnl Check for a program that compiles Windows resource files. + AC_CHECK_TOOL([WINDRES], [windres]) + fi + + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() . + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init_func libintl_lock_init_func +#define glthread_lock_lock_func libintl_lock_lock_func +#define glthread_lock_unlock_func libintl_lock_unlock_func +#define glthread_lock_destroy_func libintl_lock_destroy_func +#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded +#define glthread_rwlock_init_func libintl_rwlock_init_func +#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded +#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func +#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded +#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func +#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded +#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func +#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded +#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func +#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded +#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func +#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded +#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func +#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded +#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func +#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded +#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func +#define glthread_once_func libintl_once_func +#define glthread_once_singlethreaded libintl_once_singlethreaded +#define glthread_once_multithreaded libintl_once_multithreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }]], + [[]])], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \ + argz_stringify argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL([feof_unlocked], [#include ]) + gt_CHECK_DECL([fgets_unlocked], [#include ]) + + AM_ICONV + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], [ac_cv_have_decl_$1], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[$2]], + [[ +#ifndef $1 + char *p = (char *) $1; +#endif + ]])], + [ac_cv_have_decl_$1=yes], + [ac_cv_have_decl_$1=no])]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) diff --git a/m4/intldir.m4 b/m4/intldir.m4 new file mode 100644 index 000000000..ebae76d36 --- /dev/null +++ b/m4/intldir.m4 @@ -0,0 +1,19 @@ +# intldir.m4 serial 2 (gettext-0.18) +dnl Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +AC_PREREQ([2.52]) + +dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory. +AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], []) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 000000000..f0f7c9872 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,56 @@ +# intlmacosx.m4 serial 4 (gettext-0.18.2) +dnl Copyright (C) 2004-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFPreferencesCopyAppValue(NULL, NULL)]])], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[CFLocaleCopyCurrent();]])], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/intmax.m4 b/m4/intmax.m4 new file mode 100644 index 000000000..2c0f2afe5 --- /dev/null +++ b/m4/intmax.m4 @@ -0,0 +1,36 @@ +# intmax.m4 serial 6 (gettext-0.18.2) +dnl Copyright (C) 2002-2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif + ]], + [[intmax_t x = -1; + return !x;]])], + [gt_cv_c_intmax_t=yes], + [gt_cv_c_intmax_t=no])]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE([HAVE_INTMAX_T], [1], + [Define if you have the 'intmax_t' type in or .]) + fi +]) diff --git a/m4/intmax_t.m4 b/m4/intmax_t.m4 new file mode 100644 index 000000000..493e4a932 --- /dev/null +++ b/m4/intmax_t.m4 @@ -0,0 +1,67 @@ +# intmax_t.m4 serial 8 +dnl Copyright (C) 1997-2004, 2006-2007, 2009-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ([2.53]) + +# Define intmax_t to 'long' or 'long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_INTMAX_T], +[ + dnl For simplicity, we assume that a header file defines 'intmax_t' if and + dnl only if it defines 'uintmax_t'. + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + test $ac_cv_type_long_long_int = yes \ + && ac_type='long long' \ + || ac_type='long' + AC_DEFINE_UNQUOTED([intmax_t], [$ac_type], + [Define to long or long long if and don't define.]) + else + AC_DEFINE([HAVE_INTMAX_T], [1], + [Define if you have the 'intmax_t' type in or .]) + fi +]) + +dnl An alternative would be to explicitly test for 'intmax_t'. + +AC_DEFUN([gt_AC_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif + ]], + [[intmax_t x = -1; return !x;]])], + [gt_cv_c_intmax_t=yes], + [gt_cv_c_intmax_t=no])]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE([HAVE_INTMAX_T], [1], + [Define if you have the 'intmax_t' type in or .]) + else + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + test $ac_cv_type_long_long_int = yes \ + && ac_type='long long' \ + || ac_type='long' + AC_DEFINE_UNQUOTED([intmax_t], [$ac_type], + [Define to long or long long if and don't define.]) + fi +]) diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4 new file mode 100644 index 000000000..ee96bcd97 --- /dev/null +++ b/m4/inttypes-pri.m4 @@ -0,0 +1,42 @@ +# inttypes-pri.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1997-2002, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.53]) + +# Define PRI_MACROS_BROKEN if exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_CHECK_HEADERS([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + [gt_cv_inttypes_pri_broken], + [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifdef PRId32 +char *p = PRId32; +#endif + ]], + [[]])], + [gt_cv_inttypes_pri_broken=no], + [gt_cv_inttypes_pri_broken=yes]) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1], + [Define if exists and defines unusable PRI* macros.]) + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + AC_SUBST([PRI_MACROS_BROKEN]) +]) diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4 new file mode 100644 index 000000000..9d8f92692 --- /dev/null +++ b/m4/inttypes_h.m4 @@ -0,0 +1,29 @@ +# inttypes_h.m4 serial 10 +dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[uintmax_t i = (uintmax_t) -1; return !i;]])], + [gl_cv_header_inttypes_h=yes], + [gl_cv_header_inttypes_h=no])]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1], + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/langinfo_h.m4 b/m4/langinfo_h.m4 new file mode 100644 index 000000000..adc445e85 --- /dev/null +++ b/m4/langinfo_h.m4 @@ -0,0 +1,105 @@ +# langinfo_h.m4 serial 7 +dnl Copyright (C) 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_LANGINFO_H], +[ + AC_REQUIRE([gl_LANGINFO_H_DEFAULTS]) + + dnl Persuade glibc-2.0.6 to define CODESET. + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + dnl is always overridden, because of GNULIB_POSIXCHECK. + gl_CHECK_NEXT_HEADERS([langinfo.h]) + + dnl Determine whether exists. It is missing on mingw and BeOS. + HAVE_LANGINFO_CODESET=0 + HAVE_LANGINFO_T_FMT_AMPM=0 + HAVE_LANGINFO_ERA=0 + HAVE_LANGINFO_YESEXPR=0 + AC_CHECK_HEADERS_ONCE([langinfo.h]) + if test $ac_cv_header_langinfo_h = yes; then + HAVE_LANGINFO_H=1 + dnl Determine what defines. CODESET and ERA etc. are missing + dnl on OpenBSD 3.8. T_FMT_AMPM and YESEXPR, NOEXPR are missing on IRIX 5.3. + AC_CACHE_CHECK([whether langinfo.h defines CODESET], + [gl_cv_header_langinfo_codeset], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include +int a = CODESET; +]])], + [gl_cv_header_langinfo_codeset=yes], + [gl_cv_header_langinfo_codeset=no]) + ]) + if test $gl_cv_header_langinfo_codeset = yes; then + HAVE_LANGINFO_CODESET=1 + fi + AC_CACHE_CHECK([whether langinfo.h defines T_FMT_AMPM], + [gl_cv_header_langinfo_t_fmt_ampm], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include +int a = T_FMT_AMPM; +]])], + [gl_cv_header_langinfo_t_fmt_ampm=yes], + [gl_cv_header_langinfo_t_fmt_ampm=no]) + ]) + if test $gl_cv_header_langinfo_t_fmt_ampm = yes; then + HAVE_LANGINFO_T_FMT_AMPM=1 + fi + AC_CACHE_CHECK([whether langinfo.h defines ERA], + [gl_cv_header_langinfo_era], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include +int a = ERA; +]])], + [gl_cv_header_langinfo_era=yes], + [gl_cv_header_langinfo_era=no]) + ]) + if test $gl_cv_header_langinfo_era = yes; then + HAVE_LANGINFO_ERA=1 + fi + AC_CACHE_CHECK([whether langinfo.h defines YESEXPR], + [gl_cv_header_langinfo_yesexpr], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include +int a = YESEXPR; +]])], + [gl_cv_header_langinfo_yesexpr=yes], + [gl_cv_header_langinfo_yesexpr=no]) + ]) + if test $gl_cv_header_langinfo_yesexpr = yes; then + HAVE_LANGINFO_YESEXPR=1 + fi + else + HAVE_LANGINFO_H=0 + fi + AC_SUBST([HAVE_LANGINFO_H]) + AC_SUBST([HAVE_LANGINFO_CODESET]) + AC_SUBST([HAVE_LANGINFO_T_FMT_AMPM]) + AC_SUBST([HAVE_LANGINFO_ERA]) + AC_SUBST([HAVE_LANGINFO_YESEXPR]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[#include + ]], [nl_langinfo]) +]) + +AC_DEFUN([gl_LANGINFO_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_LANGINFO_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_LANGINFO_H_DEFAULTS], +[ + GNULIB_NL_LANGINFO=0; AC_SUBST([GNULIB_NL_LANGINFO]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_NL_LANGINFO=1; AC_SUBST([HAVE_NL_LANGINFO]) + REPLACE_NL_LANGINFO=0; AC_SUBST([REPLACE_NL_LANGINFO]) +]) diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 000000000..232da73b6 --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,35 @@ +# lcmessage.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1995-2002, 2004-2005, 2008-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], [gt_cv_val_LC_MESSAGES], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[return LC_MESSAGES]])], + [gt_cv_val_LC_MESSAGES=yes], + [gt_cv_val_LC_MESSAGES=no])]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE([HAVE_LC_MESSAGES], [1], + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 000000000..294db72e1 --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,109 @@ +# lib-ld.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 1996-2003, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT([$LD]) +else + AC_MSG_RESULT([no]) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) diff --git a/m4/lib-link.m4 b/m4/lib-link.m4 new file mode 100644 index 000000000..2ea9d6d07 --- /dev/null +++ b/m4/lib-link.m4 @@ -0,0 +1,775 @@ +# lib-link.m4 serial 25 (gettext-0.18.2) +dnl Copyright (C) 2001-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.54]) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + popdef([NAME]) + popdef([Name]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message]) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. The missing-message +dnl defaults to 'no' and may contain additional hints for the user. +dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} +dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS, + dnl because these -l options might require -L options that are present in + dnl LIBS. -l options benefit only from the -L options listed before it. + dnl Otherwise, add it to the front of LIBS, because it may be a static + dnl library that depends on another static library that is present in LIBS. + dnl Static libraries benefit only from the static libraries listed after + dnl it. + case " $LIB[]NAME" in + *" -l"*) LIBS="$LIBS $LIB[]NAME" ;; + *) LIBS="$LIB[]NAME $LIBS" ;; + esac + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[$3]], [[$4]])], + [ac_cv_lib[]Name=yes], + [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])']) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + LIB[]NAME[]_PREFIX= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + popdef([NAME]) + popdef([Name]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl acl_libext, +dnl acl_shlibext, +dnl acl_hardcode_libdir_flag_spec, +dnl acl_hardcode_libdir_separator, +dnl acl_hardcode_direct, +dnl acl_hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 000000000..1601ceaef --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,224 @@ +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) diff --git a/m4/localcharset.m4 b/m4/localcharset.m4 new file mode 100644 index 000000000..ee2e801bd --- /dev/null +++ b/m4/localcharset.m4 @@ -0,0 +1,17 @@ +# localcharset.m4 serial 7 +dnl Copyright (C) 2002, 2004, 2006, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_LOCALCHARSET], +[ + dnl Prerequisites of lib/localcharset.c. + AC_REQUIRE([AM_LANGINFO_CODESET]) + AC_REQUIRE([gl_FCNTL_O_FLAGS]) + AC_CHECK_DECLS_ONCE([getc_unlocked]) + + dnl Prerequisites of the lib/Makefile.am snippet. + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([gl_GLIBC21]) +]) diff --git a/m4/locale-fr.m4 b/m4/locale-fr.m4 new file mode 100644 index 000000000..001f53906 --- /dev/null +++ b/m4/locale-fr.m4 @@ -0,0 +1,185 @@ +# locale-fr.m4 serial 11 +dnl Copyright (C) 2003, 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Determine the name of a french locale with traditional encoding. +AC_DEFUN([gt_LOCALE_FR], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AM_LANGINFO_CODESET]) + AC_CACHE_CHECK([for a traditional french locale], [gt_cv_locale_fr], [ + AC_LANG_CONFTEST([AC_LANG_SOURCE([ +changequote(,)dnl +#include +#include +#if HAVE_LANGINFO_CODESET +# include +#endif +#include +#include +struct tm t; +char buf[16]; +int main () { + /* Check whether the given locale name is recognized by the system. */ + if (setlocale (LC_ALL, "") == NULL) return 1; + /* Check whether nl_langinfo(CODESET) is nonempty and not "ASCII" or "646". + On MacOS X 10.3.5 (Darwin 7.5) in the fr_FR locale, nl_langinfo(CODESET) + is empty, and the behaviour of Tcl 8.4 in this locale is not useful. + On OpenBSD 4.0, when an unsupported locale is specified, setlocale() + succeeds but then nl_langinfo(CODESET) is "646". In this situation, + some unit tests fail. */ +#if HAVE_LANGINFO_CODESET + { + const char *cs = nl_langinfo (CODESET); + if (cs[0] == '\0' || strcmp (cs, "ASCII") == 0 || strcmp (cs, "646") == 0) + return 1; + } +#endif +#ifdef __CYGWIN__ + /* On Cygwin, avoid locale names without encoding suffix, because the + locale_charset() function relies on the encoding suffix. Note that + LC_ALL is set on the command line. */ + if (strchr (getenv ("LC_ALL"), '.') == NULL) return 1; +#endif + /* Check whether in the abbreviation of the second month, the second + character (should be U+00E9: LATIN SMALL LETTER E WITH ACUTE) is only + one byte long. This excludes the UTF-8 encoding. */ + t.tm_year = 1975 - 1900; t.tm_mon = 2 - 1; t.tm_mday = 4; + if (strftime (buf, sizeof (buf), "%b", &t) < 3 || buf[2] != 'v') return 1; + /* Check whether the decimal separator is a comma. + On NetBSD 3.0 in the fr_FR.ISO8859-1 locale, localeconv()->decimal_point + are nl_langinfo(RADIXCHAR) are both ".". */ + if (localeconv () ->decimal_point[0] != ',') return 1; + return 0; +} +changequote([,])dnl + ])]) + if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then + # Setting LC_ALL is not enough. Need to set LC_TIME to empty, because + # otherwise on MacOS X 10.3.5 the LC_TIME=C from the beginning of the + # configure script would override the LC_ALL setting. Likewise for + # LC_CTYPE, which is also set at the beginning of the configure script. + # Test for the usual locale name. + if (LC_ALL=fr_FR LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr=fr_FR + else + # Test for the locale name with explicit encoding suffix. + if (LC_ALL=fr_FR.ISO-8859-1 LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr=fr_FR.ISO-8859-1 + else + # Test for the AIX, OSF/1, FreeBSD, NetBSD, OpenBSD locale name. + if (LC_ALL=fr_FR.ISO8859-1 LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr=fr_FR.ISO8859-1 + else + # Test for the HP-UX locale name. + if (LC_ALL=fr_FR.iso88591 LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr=fr_FR.iso88591 + else + # Test for the Solaris 7 locale name. + if (LC_ALL=fr LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr=fr + else + # None found. + gt_cv_locale_fr=none + fi + fi + fi + fi + fi + fi + rm -fr conftest* + ]) + LOCALE_FR=$gt_cv_locale_fr + AC_SUBST([LOCALE_FR]) +]) + +dnl Determine the name of a french locale with UTF-8 encoding. +AC_DEFUN([gt_LOCALE_FR_UTF8], +[ + AC_REQUIRE([AM_LANGINFO_CODESET]) + AC_CACHE_CHECK([for a french Unicode locale], [gt_cv_locale_fr_utf8], [ + AC_LANG_CONFTEST([AC_LANG_SOURCE([ +changequote(,)dnl +#include +#include +#if HAVE_LANGINFO_CODESET +# include +#endif +#include +#include +struct tm t; +char buf[16]; +int main () { + /* On BeOS and Haiku, locales are not implemented in libc. Rather, libintl + imitates locale dependent behaviour by looking at the environment + variables, and all locales use the UTF-8 encoding. */ +#if !(defined __BEOS__ || defined __HAIKU__) + /* Check whether the given locale name is recognized by the system. */ + if (setlocale (LC_ALL, "") == NULL) return 1; + /* Check whether nl_langinfo(CODESET) is nonempty and not "ASCII" or "646". + On MacOS X 10.3.5 (Darwin 7.5) in the fr_FR locale, nl_langinfo(CODESET) + is empty, and the behaviour of Tcl 8.4 in this locale is not useful. + On OpenBSD 4.0, when an unsupported locale is specified, setlocale() + succeeds but then nl_langinfo(CODESET) is "646". In this situation, + some unit tests fail. */ +# if HAVE_LANGINFO_CODESET + { + const char *cs = nl_langinfo (CODESET); + if (cs[0] == '\0' || strcmp (cs, "ASCII") == 0 || strcmp (cs, "646") == 0) + return 1; + } +# endif +# ifdef __CYGWIN__ + /* On Cygwin, avoid locale names without encoding suffix, because the + locale_charset() function relies on the encoding suffix. Note that + LC_ALL is set on the command line. */ + if (strchr (getenv ("LC_ALL"), '.') == NULL) return 1; +# endif + /* Check whether in the abbreviation of the second month, the second + character (should be U+00E9: LATIN SMALL LETTER E WITH ACUTE) is + two bytes long, with UTF-8 encoding. */ + t.tm_year = 1975 - 1900; t.tm_mon = 2 - 1; t.tm_mday = 4; + if (strftime (buf, sizeof (buf), "%b", &t) < 4 + || buf[1] != (char) 0xc3 || buf[2] != (char) 0xa9 || buf[3] != 'v') + return 1; +#endif + /* Check whether the decimal separator is a comma. + On NetBSD 3.0 in the fr_FR.ISO8859-1 locale, localeconv()->decimal_point + are nl_langinfo(RADIXCHAR) are both ".". */ + if (localeconv () ->decimal_point[0] != ',') return 1; + return 0; +} +changequote([,])dnl + ])]) + if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then + # Setting LC_ALL is not enough. Need to set LC_TIME to empty, because + # otherwise on MacOS X 10.3.5 the LC_TIME=C from the beginning of the + # configure script would override the LC_ALL setting. Likewise for + # LC_CTYPE, which is also set at the beginning of the configure script. + # Test for the usual locale name. + if (LC_ALL=fr_FR LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr_utf8=fr_FR + else + # Test for the locale name with explicit encoding suffix. + if (LC_ALL=fr_FR.UTF-8 LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr_utf8=fr_FR.UTF-8 + else + # Test for the Solaris 7 locale name. + if (LC_ALL=fr.UTF-8 LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_fr_utf8=fr.UTF-8 + else + # None found. + gt_cv_locale_fr_utf8=none + fi + fi + fi + fi + rm -fr conftest* + ]) + LOCALE_FR_UTF8=$gt_cv_locale_fr_utf8 + AC_SUBST([LOCALE_FR_UTF8]) +]) diff --git a/m4/locale-ja.m4 b/m4/locale-ja.m4 new file mode 100644 index 000000000..0eedaf149 --- /dev/null +++ b/m4/locale-ja.m4 @@ -0,0 +1,107 @@ +# locale-ja.m4 serial 7 +dnl Copyright (C) 2003, 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Determine the name of a japanese locale with EUC-JP encoding. +AC_DEFUN([gt_LOCALE_JA], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AM_LANGINFO_CODESET]) + AC_CACHE_CHECK([for a traditional japanese locale], [gt_cv_locale_ja], [ + AC_LANG_CONFTEST([AC_LANG_SOURCE([ +changequote(,)dnl +#include +#include +#if HAVE_LANGINFO_CODESET +# include +#endif +#include +#include +struct tm t; +char buf[16]; +int main () +{ + const char *p; + /* Check whether the given locale name is recognized by the system. */ + if (setlocale (LC_ALL, "") == NULL) return 1; + /* Check whether nl_langinfo(CODESET) is nonempty and not "ASCII" or "646". + On MacOS X 10.3.5 (Darwin 7.5) in the fr_FR locale, nl_langinfo(CODESET) + is empty, and the behaviour of Tcl 8.4 in this locale is not useful. + On OpenBSD 4.0, when an unsupported locale is specified, setlocale() + succeeds but then nl_langinfo(CODESET) is "646". In this situation, + some unit tests fail. */ +#if HAVE_LANGINFO_CODESET + { + const char *cs = nl_langinfo (CODESET); + if (cs[0] == '\0' || strcmp (cs, "ASCII") == 0 || strcmp (cs, "646") == 0) + return 1; + } +#endif +#ifdef __CYGWIN__ + /* On Cygwin, avoid locale names without encoding suffix, because the + locale_charset() function relies on the encoding suffix. Note that + LC_ALL is set on the command line. */ + if (strchr (getenv ("LC_ALL"), '.') == NULL) return 1; +#endif + /* Check whether MB_CUR_MAX is > 1. This excludes the dysfunctional locales + on Cygwin 1.5.x. */ + if (MB_CUR_MAX == 1) + return 1; + /* Check whether in a month name, no byte in the range 0x80..0x9F occurs. + This excludes the UTF-8 encoding. */ + t.tm_year = 1975 - 1900; t.tm_mon = 2 - 1; t.tm_mday = 4; + if (strftime (buf, sizeof (buf), "%B", &t) < 2) return 1; + for (p = buf; *p != '\0'; p++) + if ((unsigned char) *p >= 0x80 && (unsigned char) *p < 0xa0) + return 1; + return 0; +} +changequote([,])dnl + ])]) + if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then + # Setting LC_ALL is not enough. Need to set LC_TIME to empty, because + # otherwise on MacOS X 10.3.5 the LC_TIME=C from the beginning of the + # configure script would override the LC_ALL setting. Likewise for + # LC_CTYPE, which is also set at the beginning of the configure script. + # Test for the AIX locale name. + if (LC_ALL=ja_JP LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_ja=ja_JP + else + # Test for the locale name with explicit encoding suffix. + if (LC_ALL=ja_JP.EUC-JP LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_ja=ja_JP.EUC-JP + else + # Test for the HP-UX, OSF/1, NetBSD locale name. + if (LC_ALL=ja_JP.eucJP LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_ja=ja_JP.eucJP + else + # Test for the IRIX, FreeBSD locale name. + if (LC_ALL=ja_JP.EUC LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_ja=ja_JP.EUC + else + # Test for the Solaris 7 locale name. + if (LC_ALL=ja LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_ja=ja + else + # Special test for NetBSD 1.6. + if test -f /usr/share/locale/ja_JP.eucJP/LC_CTYPE; then + gt_cv_locale_ja=ja_JP.eucJP + else + # None found. + gt_cv_locale_ja=none + fi + fi + fi + fi + fi + fi + fi + rm -fr conftest* + ]) + LOCALE_JA=$gt_cv_locale_ja + AC_SUBST([LOCALE_JA]) +]) diff --git a/m4/locale-zh.m4 b/m4/locale-zh.m4 new file mode 100644 index 000000000..777fd1418 --- /dev/null +++ b/m4/locale-zh.m4 @@ -0,0 +1,92 @@ +# locale-zh.m4 serial 6 +dnl Copyright (C) 2003, 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Determine the name of a chinese locale with GB18030 encoding. +AC_DEFUN([gt_LOCALE_ZH_CN], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AM_LANGINFO_CODESET]) + AC_CACHE_CHECK([for a transitional chinese locale], [gt_cv_locale_zh_CN], [ + AC_LANG_CONFTEST([AC_LANG_SOURCE([ +changequote(,)dnl +#include +#include +#include +#if HAVE_LANGINFO_CODESET +# include +#endif +#include +#include +struct tm t; +char buf[16]; +int main () +{ + const char *p; + /* Check whether the given locale name is recognized by the system. */ + if (setlocale (LC_ALL, "") == NULL) return 1; + /* Check whether nl_langinfo(CODESET) is nonempty and not "ASCII" or "646". + On MacOS X 10.3.5 (Darwin 7.5) in the fr_FR locale, nl_langinfo(CODESET) + is empty, and the behaviour of Tcl 8.4 in this locale is not useful. + On OpenBSD 4.0, when an unsupported locale is specified, setlocale() + succeeds but then nl_langinfo(CODESET) is "646". In this situation, + some unit tests fail. */ +#if HAVE_LANGINFO_CODESET + { + const char *cs = nl_langinfo (CODESET); + if (cs[0] == '\0' || strcmp (cs, "ASCII") == 0 || strcmp (cs, "646") == 0) + return 1; + } +#endif +#ifdef __CYGWIN__ + /* On Cygwin, avoid locale names without encoding suffix, because the + locale_charset() function relies on the encoding suffix. Note that + LC_ALL is set on the command line. */ + if (strchr (getenv ("LC_ALL"), '.') == NULL) return 1; +#endif + /* Check whether in a month name, no byte in the range 0x80..0x9F occurs. + This excludes the UTF-8 encoding. */ + t.tm_year = 1975 - 1900; t.tm_mon = 2 - 1; t.tm_mday = 4; + if (strftime (buf, sizeof (buf), "%B", &t) < 2) return 1; + for (p = buf; *p != '\0'; p++) + if ((unsigned char) *p >= 0x80 && (unsigned char) *p < 0xa0) + return 1; + /* Check whether a typical GB18030 multibyte sequence is recognized as a + single wide character. This excludes the GB2312 and GBK encodings. */ + if (mblen ("\203\062\332\066", 5) != 4) + return 1; + return 0; +} +changequote([,])dnl + ])]) + if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then + # Setting LC_ALL is not enough. Need to set LC_TIME to empty, because + # otherwise on MacOS X 10.3.5 the LC_TIME=C from the beginning of the + # configure script would override the LC_ALL setting. Likewise for + # LC_CTYPE, which is also set at the beginning of the configure script. + # Test for the locale name without encoding suffix. + if (LC_ALL=zh_CN LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_zh_CN=zh_CN + else + # Test for the locale name with explicit encoding suffix. + if (LC_ALL=zh_CN.GB18030 LC_TIME= LC_CTYPE= ./conftest; exit) 2>/dev/null; then + gt_cv_locale_zh_CN=zh_CN.GB18030 + else + # None found. + gt_cv_locale_zh_CN=none + fi + fi + else + # If there was a link error, due to mblen(), the system is so old that + # it certainly doesn't have a chinese locale. + gt_cv_locale_zh_CN=none + fi + rm -fr conftest* + ]) + LOCALE_ZH_CN=$gt_cv_locale_zh_CN + AC_SUBST([LOCALE_ZH_CN]) +]) diff --git a/m4/lock.m4 b/m4/lock.m4 new file mode 100644 index 000000000..f71c66459 --- /dev/null +++ b/m4/lock.m4 @@ -0,0 +1,41 @@ +# lock.m4 serial 11 (gettext-0.18.2) +dnl Copyright (C) 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_THREADLIB]) + if test "$gl_threads_api" = posix; then + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1], + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include ]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [[#include ]], + [[ +#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif + ]])], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], [1], + [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) + fi + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [ + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/m4/longlong.m4 b/m4/longlong.m4 new file mode 100644 index 000000000..cca3c1a90 --- /dev/null +++ b/m4/longlong.m4 @@ -0,0 +1,106 @@ +# longlong.m4 serial 14 +dnl Copyright (C) 1999-2007, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG_INT if 'long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'long long int' exists but is only 32 bits large +# (as on some very old compilers), HAVE_LONG_LONG_INT will not be +# defined. In this case you can treat 'long long int' like 'long int'. + +AC_DEFUN([AC_TYPE_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. + dnl If cross compiling, assume the bug isn't important, since + dnl nobody cross compiles for this platform as far as we know. + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[@%:@include + @%:@ifndef LLONG_MAX + @%:@ define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + @%:@ define LLONG_MAX (HALF - 1 + HALF) + @%:@endif]], + [[long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0;]])], + [ac_cv_type_long_long_int=yes], + [ac_cv_type_long_long_int=no], + [ac_cv_type_long_long_int=yes])], + [ac_cv_type_long_long_int=no])]) + if test $ac_cv_type_long_long_int = yes; then + AC_DEFINE([HAVE_LONG_LONG_INT], [1], + [Define to 1 if the system has the type `long long int'.]) + fi +]) + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1], + [Define to 1 if the system has the type `unsigned long long int'.]) + fi +]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) diff --git a/m4/malloc.m4 b/m4/malloc.m4 new file mode 100644 index 000000000..7a749254a --- /dev/null +++ b/m4/malloc.m4 @@ -0,0 +1,66 @@ +# malloc.m4 serial 12 +dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# gl_FUNC_MALLOC_GNU +# ------------------ +# Test whether 'malloc (0)' is handled like in GNU libc, and replace malloc if +# it is not. +AC_DEFUN([gl_FUNC_MALLOC_GNU], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + dnl _AC_FUNC_MALLOC_IF is defined in Autoconf. + _AC_FUNC_MALLOC_IF( + [AC_DEFINE([HAVE_MALLOC_GNU], [1], + [Define to 1 if your system has a GNU libc compatible 'malloc' + function, and to 0 otherwise.])], + [AC_DEFINE([HAVE_MALLOC_GNU], [0]) + gl_REPLACE_MALLOC + ]) +]) + +# gl_FUNC_MALLOC_POSIX +# -------------------- +# Test whether 'malloc' is POSIX compliant (sets errno to ENOMEM when it +# fails), and replace malloc if it is not. +AC_DEFUN([gl_FUNC_MALLOC_POSIX], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_REQUIRE([gl_CHECK_MALLOC_POSIX]) + if test $gl_cv_func_malloc_posix = yes; then + AC_DEFINE([HAVE_MALLOC_POSIX], [1], + [Define if the 'malloc' function is POSIX compliant.]) + else + gl_REPLACE_MALLOC + fi +]) + +# Test whether malloc, realloc, calloc are POSIX compliant, +# Set gl_cv_func_malloc_posix to yes or no accordingly. +AC_DEFUN([gl_CHECK_MALLOC_POSIX], +[ + AC_CACHE_CHECK([whether malloc, realloc, calloc are POSIX compliant], + [gl_cv_func_malloc_posix], + [ + dnl It is too dangerous to try to allocate a large amount of memory: + dnl some systems go to their knees when you do that. So assume that + dnl all Unix implementations of the function are POSIX compliant. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[]], + [[#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + choke me + #endif + ]])], + [gl_cv_func_malloc_posix=yes], + [gl_cv_func_malloc_posix=no]) + ]) +]) + +AC_DEFUN([gl_REPLACE_MALLOC], +[ + AC_LIBOBJ([malloc]) + REPLACE_MALLOC=1 +]) diff --git a/m4/mbrtowc.m4 b/m4/mbrtowc.m4 new file mode 100644 index 000000000..28b9c43bf --- /dev/null +++ b/m4/mbrtowc.m4 @@ -0,0 +1,393 @@ +# mbrtowc.m4 serial 18 +dnl Copyright (C) 2001-2002, 2004-2005, 2008-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_MBRTOWC], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + gl_MBSTATE_T_BROKEN + + AC_CHECK_FUNCS_ONCE([mbrtowc]) + if test $ac_cv_func_mbrtowc = no; then + HAVE_MBRTOWC=0 + else + if test $REPLACE_MBSTATE_T = 1; then + REPLACE_MBRTOWC=1 + else + gl_MBRTOWC_NULL_ARG + gl_MBRTOWC_RETVAL + gl_MBRTOWC_NUL_RETVAL + case "$gl_cv_func_mbrtowc_null_arg" in + *yes) ;; + *) AC_DEFINE([MBRTOWC_NULL_ARG_BUG], [1], + [Define if the mbrtowc function has the NULL string argument bug.]) + REPLACE_MBRTOWC=1 + ;; + esac + case "$gl_cv_func_mbrtowc_retval" in + *yes) ;; + *) AC_DEFINE([MBRTOWC_RETVAL_BUG], [1], + [Define if the mbrtowc function returns a wrong return value.]) + REPLACE_MBRTOWC=1 + ;; + esac + case "$gl_cv_func_mbrtowc_nul_retval" in + *yes) ;; + *) AC_DEFINE([MBRTOWC_NUL_RETVAL_BUG], [1], + [Define if the mbrtowc function does not return 0 for a NUL character.]) + REPLACE_MBRTOWC=1 + ;; + esac + fi + fi + if test $HAVE_MBRTOWC = 0 || test $REPLACE_MBRTOWC = 1; then + gl_REPLACE_WCHAR_H + AC_LIBOBJ([mbrtowc]) + gl_PREREQ_MBRTOWC + fi +]) + +dnl Test whether mbsinit() and mbrtowc() need to be overridden in a way that +dnl redefines the semantics of the given mbstate_t type. +dnl Result is REPLACE_MBSTATE_T. +dnl When this is set to 1, we replace both mbsinit() and mbrtowc(), in order to +dnl avoid inconsistencies. + +AC_DEFUN([gl_MBSTATE_T_BROKEN], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + AC_CHECK_FUNCS_ONCE([mbsinit]) + AC_CHECK_FUNCS_ONCE([mbrtowc]) + if test $ac_cv_func_mbsinit = yes && test $ac_cv_func_mbrtowc = yes; then + gl_MBRTOWC_INCOMPLETE_STATE + gl_MBRTOWC_SANITYCHECK + REPLACE_MBSTATE_T=0 + case "$gl_cv_func_mbrtowc_incomplete_state" in + *yes) ;; + *) REPLACE_MBSTATE_T=1 ;; + esac + case "$gl_cv_func_mbrtowc_sanitycheck" in + *yes) ;; + *) REPLACE_MBSTATE_T=1 ;; + esac + else + REPLACE_MBSTATE_T=1 + fi + if test $REPLACE_MBSTATE_T = 1; then + gl_REPLACE_WCHAR_H + fi +]) + +dnl Test whether mbrtowc puts the state into non-initial state when parsing an +dnl incomplete multibyte character. +dnl Result is gl_cv_func_mbrtowc_incomplete_state. + +AC_DEFUN([gl_MBRTOWC_INCOMPLETE_STATE], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_JA]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc handles incomplete characters], + [gl_cv_func_mbrtowc_incomplete_state], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on AIX and OSF/1. + aix* | osf*) gl_cv_func_mbrtowc_incomplete_state="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbrtowc_incomplete_state="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_JA != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +int main () +{ + if (setlocale (LC_ALL, "$LOCALE_JA") != NULL) + { + const char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */ + mbstate_t state; + wchar_t wc; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2)) + if (mbsinit (&state)) + return 1; + } + return 0; +}]])], + [gl_cv_func_mbrtowc_incomplete_state=yes], + [gl_cv_func_mbrtowc_incomplete_state=no], + [:]) + fi + ]) +]) + +dnl Test whether mbrtowc works not worse than mbtowc. +dnl Result is gl_cv_func_mbrtowc_sanitycheck. + +AC_DEFUN([gl_MBRTOWC_SANITYCHECK], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_ZH_CN]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc works as well as mbtowc], + [gl_cv_func_mbrtowc_sanitycheck], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on Solaris 8. + solaris2.8) gl_cv_func_mbrtowc_sanitycheck="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbrtowc_sanitycheck="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_ZH_CN != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +#include +int main () +{ + /* This fails on Solaris 8: + mbrtowc returns 2, and sets wc to 0x00F0. + mbtowc returns 4 (correct) and sets wc to 0x5EDC. */ + if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL) + { + char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */ + mbstate_t state; + wchar_t wc; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (&wc, input + 3, 6, &state) != 4 + && mbtowc (&wc, input + 3, 6) == 4) + return 1; + } + return 0; +}]])], + [gl_cv_func_mbrtowc_sanitycheck=yes], + [gl_cv_func_mbrtowc_sanitycheck=no], + [:]) + fi + ]) +]) + +dnl Test whether mbrtowc supports a NULL string argument correctly. +dnl Result is gl_cv_func_mbrtowc_null_arg. + +AC_DEFUN([gl_MBRTOWC_NULL_ARG], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_FR_UTF8]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument], + [gl_cv_func_mbrtowc_null_arg], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on OSF/1. + osf*) gl_cv_func_mbrtowc_null_arg="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbrtowc_null_arg="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_FR_UTF8 != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +int main () +{ + if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL) + { + mbstate_t state; + wchar_t wc; + int ret; + + memset (&state, '\0', sizeof (mbstate_t)); + wc = (wchar_t) 0xBADFACE; + mbrtowc (&wc, NULL, 5, &state); + /* Check that wc was not modified. */ + if (wc != (wchar_t) 0xBADFACE) + return 1; + } + return 0; +}]])], + [gl_cv_func_mbrtowc_null_arg=yes], + [gl_cv_func_mbrtowc_null_arg=no], + [:]) + fi + ]) +]) + +dnl Test whether mbrtowc, when parsing the end of a multibyte character, +dnl correctly returns the number of bytes that were needed to complete the +dnl character (not the total number of bytes of the multibyte character). +dnl Result is gl_cv_func_mbrtowc_retval. + +AC_DEFUN([gl_MBRTOWC_RETVAL], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_FR_UTF8]) + AC_REQUIRE([gt_LOCALE_JA]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc has a correct return value], + [gl_cv_func_mbrtowc_retval], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on HP-UX and Solaris. + hpux* | solaris*) gl_cv_func_mbrtowc_retval="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbrtowc_retval="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +int main () +{ + /* This fails on Solaris. */ + if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL) + { + char input[] = "B\303\274\303\237er"; /* "Büßer" */ + mbstate_t state; + wchar_t wc; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2)) + { + input[1] = '\0'; + if (mbrtowc (&wc, input + 2, 5, &state) != 1) + return 1; + } + } + /* This fails on HP-UX 11.11. */ + if (setlocale (LC_ALL, "$LOCALE_JA") != NULL) + { + char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */ + mbstate_t state; + wchar_t wc; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (&wc, input + 1, 1, &state) == (size_t)(-2)) + { + input[1] = '\0'; + if (mbrtowc (&wc, input + 2, 5, &state) != 2) + return 1; + } + } + return 0; +}]])], + [gl_cv_func_mbrtowc_retval=yes], + [gl_cv_func_mbrtowc_retval=no], + [:]) + fi + ]) +]) + +dnl Test whether mbrtowc, when parsing a NUL character, correctly returns 0. +dnl Result is gl_cv_func_mbrtowc_nul_retval. + +AC_DEFUN([gl_MBRTOWC_NUL_RETVAL], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_ZH_CN]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc returns 0 when parsing a NUL character], + [gl_cv_func_mbrtowc_nul_retval], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on Solaris 8 and 9. + solaris2.[89]) gl_cv_func_mbrtowc_nul_retval="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbrtowc_nul_retval="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_ZH_CN != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +int main () +{ + /* This fails on Solaris 8 and 9. */ + if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL) + { + mbstate_t state; + wchar_t wc; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (&wc, "", 1, &state) != 0) + return 1; + } + return 0; +}]])], + [gl_cv_func_mbrtowc_nul_retval=yes], + [gl_cv_func_mbrtowc_nul_retval=no], + [:]) + fi + ]) +]) + +# Prerequisites of lib/mbrtowc.c. +AC_DEFUN([gl_PREREQ_MBRTOWC], [ + : +]) + + +dnl From Paul Eggert + +dnl This override of an autoconf macro can be removed when autoconf 2.60 or +dnl newer can be assumed everywhere. + +m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.60]),[-1],[ +AC_DEFUN([AC_FUNC_MBRTOWC], +[ + dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60. + AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared], + gl_cv_func_mbrtowc, + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[wchar_t wc; + char const s[] = ""; + size_t n = 1; + mbstate_t state; + return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])], + gl_cv_func_mbrtowc=yes, + gl_cv_func_mbrtowc=no)]) + if test $gl_cv_func_mbrtowc = yes; then + AC_DEFINE([HAVE_MBRTOWC], [1], + [Define to 1 if mbrtowc and mbstate_t are properly declared.]) + fi +]) +]) diff --git a/m4/mbsinit.m4 b/m4/mbsinit.m4 new file mode 100644 index 000000000..46c106fc4 --- /dev/null +++ b/m4/mbsinit.m4 @@ -0,0 +1,32 @@ +# mbsinit.m4 serial 4 +dnl Copyright (C) 2008, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_MBSINIT], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + gl_MBSTATE_T_BROKEN + + AC_CHECK_FUNCS_ONCE([mbsinit]) + if test $ac_cv_func_mbsinit = no; then + HAVE_MBSINIT=0 + else + if test $REPLACE_MBSTATE_T = 1; then + REPLACE_MBSINIT=1 + fi + fi + if test $HAVE_MBSINIT = 0 || test $REPLACE_MBSINIT = 1; then + gl_REPLACE_WCHAR_H + AC_LIBOBJ([mbsinit]) + gl_PREREQ_MBSINIT + fi +]) + +# Prerequisites of lib/mbsinit.c. +AC_DEFUN([gl_PREREQ_MBSINIT], [ + : +]) diff --git a/m4/mbsrtowcs.m4 b/m4/mbsrtowcs.m4 new file mode 100644 index 000000000..e854337ff --- /dev/null +++ b/m4/mbsrtowcs.m4 @@ -0,0 +1,123 @@ +# mbsrtowcs.m4 serial 7 +dnl Copyright (C) 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_MBSRTOWCS], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + gl_MBSTATE_T_BROKEN + + AC_CHECK_FUNCS_ONCE([mbsrtowcs]) + if test $ac_cv_func_mbsrtowcs = no; then + HAVE_MBSRTOWCS=0 + else + if test $REPLACE_MBSTATE_T = 1; then + REPLACE_MBSRTOWCS=1 + else + gl_MBSRTOWCS_WORKS + case "$gl_cv_func_mbsrtowcs_works" in + *yes) ;; + *) REPLACE_MBSRTOWCS=1 ;; + esac + fi + fi + if test $HAVE_MBSRTOWCS = 0 || test $REPLACE_MBSRTOWCS = 1; then + gl_REPLACE_WCHAR_H + AC_LIBOBJ([mbsrtowcs]) + AC_LIBOBJ([mbsrtowcs-state]) + gl_PREREQ_MBSRTOWCS + fi +]) + +dnl Test whether mbsrtowcs works. +dnl Result is gl_cv_func_mbsrtowcs_works. + +AC_DEFUN([gl_MBSRTOWCS_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_FR_UTF8]) + AC_REQUIRE([gt_LOCALE_JA]) + AC_REQUIRE([gt_LOCALE_ZH_CN]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbsrtowcs works], + [gl_cv_func_mbsrtowcs_works], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on HP-UX and Solaris. + hpux* | solaris*) gl_cv_func_mbsrtowcs_works="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbsrtowcs_works="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none || test $LOCALE_ZH_CN != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +int main () +{ + /* Test whether the function works when started with a conversion state + in non-initial state. This fails on HP-UX 11.11 and Solaris 10. */ + if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL) + { + const char input[] = "B\303\274\303\237er"; + mbstate_t state; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (NULL, input + 1, 1, &state) == (size_t)(-2)) + if (!mbsinit (&state)) + { + const char *src = input + 2; + if (mbsrtowcs (NULL, &src, 10, &state) != 4) + return 1; + } + } + if (setlocale (LC_ALL, "$LOCALE_JA") != NULL) + { + const char input[] = "<\306\374\313\334\270\354>"; + mbstate_t state; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (NULL, input + 3, 1, &state) == (size_t)(-2)) + if (!mbsinit (&state)) + { + const char *src = input + 4; + if (mbsrtowcs (NULL, &src, 10, &state) != 3) + return 1; + } + } + if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL) + { + const char input[] = "B\250\271\201\060\211\070er"; + mbstate_t state; + + memset (&state, '\0', sizeof (mbstate_t)); + if (mbrtowc (NULL, input + 1, 1, &state) == (size_t)(-2)) + if (!mbsinit (&state)) + { + const char *src = input + 2; + if (mbsrtowcs (NULL, &src, 10, &state) != 4) + return 1; + } + } + return 0; +}]])], + [gl_cv_func_mbsrtowcs_works=yes], + [gl_cv_func_mbsrtowcs_works=no], + [:]) + fi + ]) +]) + +# Prerequisites of lib/mbsrtowcs.c. +AC_DEFUN([gl_PREREQ_MBSRTOWCS], [ + : +]) diff --git a/m4/mbstate_t.m4 b/m4/mbstate_t.m4 new file mode 100644 index 000000000..3e2df29f8 --- /dev/null +++ b/m4/mbstate_t.m4 @@ -0,0 +1,34 @@ +# mbstate_t.m4 serial 12 +dnl Copyright (C) 2000-2002, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# From Paul Eggert. + +# BeOS 5 has but does not define mbstate_t, +# so you can't declare an object of that type. +# Check for this incompatibility with Standard C. + +# AC_TYPE_MBSTATE_T +# ----------------- +AC_DEFUN([AC_TYPE_MBSTATE_T], +[ + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) dnl for HP-UX 11.11 + + AC_CACHE_CHECK([for mbstate_t], [ac_cv_type_mbstate_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT[ +# include ]], + [[mbstate_t x; return sizeof x;]])], + [ac_cv_type_mbstate_t=yes], + [ac_cv_type_mbstate_t=no])]) + if test $ac_cv_type_mbstate_t = yes; then + AC_DEFINE([HAVE_MBSTATE_T], [1], + [Define to 1 if declares mbstate_t.]) + else + AC_DEFINE([mbstate_t], [int], + [Define to a type if does not define.]) + fi +]) diff --git a/m4/memchr.m4 b/m4/memchr.m4 new file mode 100644 index 000000000..b05a79a02 --- /dev/null +++ b/m4/memchr.m4 @@ -0,0 +1,87 @@ +# memchr.m4 serial 9 +dnl Copyright (C) 2002-2004, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN_ONCE([gl_FUNC_MEMCHR], +[ + dnl Check for prerequisites for memory fence checks. + gl_FUNC_MMAP_ANON + AC_CHECK_HEADERS_ONCE([sys/mman.h]) + AC_CHECK_FUNCS_ONCE([mprotect]) + + dnl These days, we assume memchr is present. But just in case... + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_CHECK_FUNCS_ONCE([memchr]) + if test $ac_cv_func_memchr = yes; then + # Detect platform-specific bugs in some versions of glibc: + # memchr should not dereference anything with length 0 + # http://bugzilla.redhat.com/499689 + # memchr should not dereference overestimated length after a match + # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=521737 + # http://sourceware.org/bugzilla/show_bug.cgi?id=10162 + # Assume that memchr works on platforms that lack mprotect. + AC_CACHE_CHECK([whether memchr works], [gl_cv_func_memchr_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#if HAVE_SYS_MMAN_H +# include +# include +# include +# include +# ifndef MAP_FILE +# define MAP_FILE 0 +# endif +#endif +]], [[ + char *fence = NULL; +#if HAVE_SYS_MMAN_H && HAVE_MPROTECT +# if HAVE_MAP_ANONYMOUS + const int flags = MAP_ANONYMOUS | MAP_PRIVATE; + const int fd = -1; +# else /* !HAVE_MAP_ANONYMOUS */ + const int flags = MAP_FILE | MAP_PRIVATE; + int fd = open ("/dev/zero", O_RDONLY, 0666); + if (fd >= 0) +# endif + { + int pagesize = getpagesize (); + char *two_pages = + (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE, + flags, fd, 0); + if (two_pages != (char *)(-1) + && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0) + fence = two_pages + pagesize; + } +#endif + if (fence) + { + if (memchr (fence, 0, 0)) + return 1; + strcpy (fence - 9, "12345678"); + if (memchr (fence - 9, 0, 79) != fence - 1) + return 2; + if (memchr (fence - 1, 0, 3) != fence - 1) + return 3; + } + return 0; +]])], [gl_cv_func_memchr_works=yes], [gl_cv_func_memchr_works=no], + [dnl Be pessimistic for now. + gl_cv_func_memchr_works="guessing no"])]) + if test "$gl_cv_func_memchr_works" != yes; then + REPLACE_MEMCHR=1 + fi + else + HAVE_MEMCHR=0 + fi + if test $HAVE_MEMCHR = 0 || test $REPLACE_MEMCHR = 1; then + AC_LIBOBJ([memchr]) + gl_PREREQ_MEMCHR + fi +]) + +# Prerequisites of lib/memchr.c. +AC_DEFUN([gl_PREREQ_MEMCHR], [ + AC_CHECK_HEADERS([bp-sym.h]) +]) diff --git a/m4/mempcpy.m4 b/m4/mempcpy.m4 new file mode 100644 index 000000000..12df771e4 --- /dev/null +++ b/m4/mempcpy.m4 @@ -0,0 +1,27 @@ +# mempcpy.m4 serial 10 +dnl Copyright (C) 2003-2004, 2006-2007, 2009-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_MEMPCPY], +[ + dnl Persuade glibc to declare mempcpy(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + dnl The mempcpy() declaration in lib/string.in.h uses 'restrict'. + AC_REQUIRE([AC_C_RESTRICT]) + + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_REPLACE_FUNCS([mempcpy]) + if test $ac_cv_func_mempcpy = no; then + HAVE_MEMPCPY=0 + gl_PREREQ_MEMPCPY + fi +]) + +# Prerequisites of lib/mempcpy.c. +AC_DEFUN([gl_PREREQ_MEMPCPY], [ + : +]) diff --git a/m4/mmap-anon.m4 b/m4/mmap-anon.m4 new file mode 100644 index 000000000..a6b7b9ac3 --- /dev/null +++ b/m4/mmap-anon.m4 @@ -0,0 +1,59 @@ +# mmap-anon.m4 serial 8 +dnl Copyright (C) 2005, 2007, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Detect how mmap can be used to create anonymous (not file-backed) memory +# mappings. +# - On Linux, AIX, OSF/1, Solaris, Cygwin, Interix, Haiku, both MAP_ANONYMOUS +# and MAP_ANON exist and have the same value. +# - On HP-UX, only MAP_ANONYMOUS exists. +# - On MacOS X, FreeBSD, NetBSD, OpenBSD, only MAP_ANON exists. +# - On IRIX, neither exists, and a file descriptor opened to /dev/zero must be +# used. + +AC_DEFUN([gl_FUNC_MMAP_ANON], +[ + dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57. + AC_REQUIRE([AC_PROG_CPP]) + AC_REQUIRE([AC_PROG_EGREP]) + + dnl Persuade glibc to define MAP_ANONYMOUS. + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + # Check for mmap(). Don't use AC_FUNC_MMAP, because it checks too much: it + # fails on HP-UX 11, because MAP_FIXED mappings do not work. But this is + # irrelevant for anonymous mappings. + AC_CHECK_FUNC([mmap], [gl_have_mmap=yes], [gl_have_mmap=no]) + + # Try to allow MAP_ANONYMOUS. + gl_have_mmap_anonymous=no + if test $gl_have_mmap = yes; then + AC_MSG_CHECKING([for MAP_ANONYMOUS]) + AC_EGREP_CPP([I cant identify this map.], [ +#include +#ifdef MAP_ANONYMOUS + I cant identify this map. +#endif +], + [gl_have_mmap_anonymous=yes]) + if test $gl_have_mmap_anonymous != yes; then + AC_EGREP_CPP([I cant identify this map.], [ +#include +#ifdef MAP_ANON + I cant identify this map. +#endif +], + [AC_DEFINE([MAP_ANONYMOUS], [MAP_ANON], + [Define to a substitute value for mmap()'s MAP_ANONYMOUS flag.]) + gl_have_mmap_anonymous=yes]) + fi + AC_MSG_RESULT([$gl_have_mmap_anonymous]) + if test $gl_have_mmap_anonymous = yes; then + AC_DEFINE([HAVE_MAP_ANONYMOUS], [1], + [Define to 1 if mmap()'s MAP_ANONYMOUS flag is available after including + config.h and .]) + fi + fi +]) diff --git a/m4/multiarch.m4 b/m4/multiarch.m4 new file mode 100644 index 000000000..389bd2bba --- /dev/null +++ b/m4/multiarch.m4 @@ -0,0 +1,65 @@ +# multiarch.m4 serial 5 +dnl Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Determine whether the compiler is or may be producing universal binaries. +# +# On MacOS X 10.5 and later systems, the user can create libraries and +# executables that work on multiple system types--known as "fat" or +# "universal" binaries--by specifying multiple '-arch' options to the +# compiler but only a single '-arch' option to the preprocessor. Like +# this: +# +# ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ +# CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ +# CPP="gcc -E" CXXCPP="g++ -E" +# +# Detect this situation and set the macro AA_APPLE_UNIVERSAL_BUILD at the +# beginning of config.h and set APPLE_UNIVERSAL_BUILD accordingly. + +AC_DEFUN_ONCE([gl_MULTIARCH], +[ + dnl Code similar to autoconf-2.63 AC_C_BIGENDIAN. + gl_cv_c_multiarch=no + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + ]])], + [ + dnl Check for potential -arch flags. It is not universal unless + dnl there are at least two -arch flags with different values. + arch= + prev= + for word in ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}; do + if test -n "$prev"; then + case $word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$arch" || test "$arch" = "$word"; then + arch="$word" + else + gl_cv_c_multiarch=yes + fi + ;; + esac + prev= + else + if test "x$word" = "x-arch"; then + prev=arch + fi + fi + done + ]) + if test $gl_cv_c_multiarch = yes; then + AC_DEFINE([AA_APPLE_UNIVERSAL_BUILD], [1], + [Define if the compiler is building for multiple architectures of Apple platforms at once.]) + APPLE_UNIVERSAL_BUILD=1 + else + APPLE_UNIVERSAL_BUILD=0 + fi + AC_SUBST([APPLE_UNIVERSAL_BUILD]) +]) diff --git a/m4/nl_langinfo.m4 b/m4/nl_langinfo.m4 new file mode 100644 index 000000000..ad456a264 --- /dev/null +++ b/m4/nl_langinfo.m4 @@ -0,0 +1,25 @@ +# nl_langinfo.m4 serial 3 +dnl Copyright (C) 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_NL_LANGINFO], +[ + AC_REQUIRE([gl_LANGINFO_H_DEFAULTS]) + AC_REQUIRE([gl_LANGINFO_H]) + AC_CHECK_FUNCS_ONCE([nl_langinfo]) + if test $ac_cv_func_nl_langinfo = yes; then + if test $HAVE_LANGINFO_CODESET = 1 && test $HAVE_LANGINFO_ERA = 1; then + : + else + REPLACE_NL_LANGINFO=1 + AC_DEFINE([REPLACE_NL_LANGINFO], [1], + [Define if nl_langinfo exists but is overridden by gnulib.]) + AC_LIBOBJ([nl_langinfo]) + fi + else + HAVE_NL_LANGINFO=0 + AC_LIBOBJ([nl_langinfo]) + fi +]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 000000000..003704c4b --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,32 @@ +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 000000000..47f36a41a --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,449 @@ +# po.m4 serial 17 (gettext-0.18) +dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" < +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}]])], + [gt_cv_func_printf_posix=yes], + [gt_cv_func_printf_posix=no], + [ + AC_EGREP_CPP([notposix], [ +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], + [gt_cv_func_printf_posix="guessing no"], + [gt_cv_func_printf_posix="guessing yes"]) + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE([HAVE_POSIX_PRINTF], [1], + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/m4/printf.m4 b/m4/printf.m4 new file mode 100644 index 000000000..e850862c0 --- /dev/null +++ b/m4/printf.m4 @@ -0,0 +1,1462 @@ +# printf.m4 serial 35 +dnl Copyright (C) 2003, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Test whether the *printf family of functions supports the 'j', 'z', 't', +dnl 'L' size specifiers. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_sizes_c99. + +AC_DEFUN([gl_PRINTF_SIZES_C99], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports size specifiers as in C99], + [gl_cv_func_printf_sizes_c99], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +# include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +# include +#endif +static char buf[100]; +int main () +{ +#if HAVE_STDINT_H_WITH_UINTMAX || HAVE_INTTYPES_H_WITH_UINTMAX + buf[0] = '\0'; + if (sprintf (buf, "%ju %d", (uintmax_t) 12345671, 33, 44, 55) < 0 + || strcmp (buf, "12345671 33") != 0) + return 1; +#endif + buf[0] = '\0'; + if (sprintf (buf, "%zu %d", (size_t) 12345672, 33, 44, 55) < 0 + || strcmp (buf, "12345672 33") != 0) + return 1; + buf[0] = '\0'; + if (sprintf (buf, "%tu %d", (ptrdiff_t) 12345673, 33, 44, 55) < 0 + || strcmp (buf, "12345673 33") != 0) + return 1; + buf[0] = '\0'; + if (sprintf (buf, "%Lg %d", (long double) 1.5, 33, 44, 55) < 0 + || strcmp (buf, "1.5 33") != 0) + return 1; + return 0; +}]])], + [gl_cv_func_printf_sizes_c99=yes], + [gl_cv_func_printf_sizes_c99=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_sizes_c99="guessing yes";; + # Guess yes on FreeBSD >= 5. + freebsd[1-4]*) gl_cv_func_printf_sizes_c99="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_printf_sizes_c99="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_printf_sizes_c99="guessing no";; + darwin*) gl_cv_func_printf_sizes_c99="guessing yes";; + # Guess yes on OpenBSD >= 3.9. + openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*) + gl_cv_func_printf_sizes_c99="guessing no";; + openbsd*) gl_cv_func_printf_sizes_c99="guessing yes";; + # Guess yes on Solaris >= 2.10. + solaris2.[0-9]*) gl_cv_func_printf_sizes_c99="guessing no";; + solaris*) gl_cv_func_printf_sizes_c99="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_printf_sizes_c99="guessing no";; + netbsd*) gl_cv_func_printf_sizes_c99="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_sizes_c99="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports 'long double' +dnl arguments together with the 'L' size specifier. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_long_double. + +AC_DEFUN([gl_PRINTF_LONG_DOUBLE], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports 'long double' arguments], + [gl_cv_func_printf_long_double], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[10000]; +int main () +{ + buf[0] = '\0'; + if (sprintf (buf, "%Lf %d", 1.75L, 33, 44, 55) < 0 + || strcmp (buf, "1.750000 33") != 0) + return 1; + buf[0] = '\0'; + if (sprintf (buf, "%Le %d", 1.75L, 33, 44, 55) < 0 + || strcmp (buf, "1.750000e+00 33") != 0) + return 1; + buf[0] = '\0'; + if (sprintf (buf, "%Lg %d", 1.75L, 33, 44, 55) < 0 + || strcmp (buf, "1.75 33") != 0) + return 1; + return 0; +}]])], + [gl_cv_func_printf_long_double=yes], + [gl_cv_func_printf_long_double=no], + [ +changequote(,)dnl + case "$host_os" in + beos*) gl_cv_func_printf_long_double="guessing no";; + mingw* | pw*) gl_cv_func_printf_long_double="guessing no";; + *) gl_cv_func_printf_long_double="guessing yes";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports infinite and NaN +dnl 'double' arguments and negative zero arguments in the %f, %e, %g +dnl directives. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_infinite. + +AC_DEFUN([gl_PRINTF_INFINITE], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports infinite 'double' arguments], + [gl_cv_func_printf_infinite], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static int +strisnan (const char *string, size_t start_index, size_t end_index) +{ + if (start_index < end_index) + { + if (string[start_index] == '-') + start_index++; + if (start_index + 3 <= end_index + && memcmp (string + start_index, "nan", 3) == 0) + { + start_index += 3; + if (start_index == end_index + || (string[start_index] == '(' && string[end_index - 1] == ')')) + return 1; + } + } + return 0; +} +static int +have_minus_zero () +{ + static double plus_zero = 0.0; + double minus_zero = - plus_zero; + return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0; +} +static char buf[10000]; +static double zero = 0.0; +int main () +{ + if (sprintf (buf, "%f", 1.0 / 0.0) < 0 + || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0)) + return 1; + if (sprintf (buf, "%f", -1.0 / 0.0) < 0 + || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0)) + return 1; + if (sprintf (buf, "%f", zero / zero) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%e", 1.0 / 0.0) < 0 + || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0)) + return 1; + if (sprintf (buf, "%e", -1.0 / 0.0) < 0 + || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0)) + return 1; + if (sprintf (buf, "%e", zero / zero) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%g", 1.0 / 0.0) < 0 + || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0)) + return 1; + if (sprintf (buf, "%g", -1.0 / 0.0) < 0 + || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0)) + return 1; + if (sprintf (buf, "%g", zero / zero) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + /* This test fails on HP-UX 10.20. */ + if (have_minus_zero ()) + if (sprintf (buf, "%g", - zero) < 0 + || strcmp (buf, "-0") != 0) + return 1; + return 0; +}]])], + [gl_cv_func_printf_infinite=yes], + [gl_cv_func_printf_infinite=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_infinite="guessing yes";; + # Guess yes on FreeBSD >= 6. + freebsd[1-5]*) gl_cv_func_printf_infinite="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_printf_infinite="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_printf_infinite="guessing no";; + darwin*) gl_cv_func_printf_infinite="guessing yes";; + # Guess yes on HP-UX >= 11. + hpux[7-9]* | hpux10*) gl_cv_func_printf_infinite="guessing no";; + hpux*) gl_cv_func_printf_infinite="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_printf_infinite="guessing no";; + netbsd*) gl_cv_func_printf_infinite="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_printf_infinite="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_infinite="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports infinite and NaN +dnl 'long double' arguments in the %f, %e, %g directives. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_infinite_long_double. + +AC_DEFUN([gl_PRINTF_INFINITE_LONG_DOUBLE], +[ + AC_REQUIRE([gl_PRINTF_LONG_DOUBLE]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gl_BIGENDIAN]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + dnl The user can set or unset the variable gl_printf_safe to indicate + dnl that he wishes a safe handling of non-IEEE-754 'long double' values. + if test -n "$gl_printf_safe"; then + AC_DEFINE([CHECK_PRINTF_SAFE], [1], + [Define if you wish *printf() functions that have a safe handling of + non-IEEE-754 'long double' values.]) + fi + case "$gl_cv_func_printf_long_double" in + *yes) + AC_CACHE_CHECK([whether printf supports infinite 'long double' arguments], + [gl_cv_func_printf_infinite_long_double], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +]GL_NOCRASH[ +#include +#include +#include +static int +strisnan (const char *string, size_t start_index, size_t end_index) +{ + if (start_index < end_index) + { + if (string[start_index] == '-') + start_index++; + if (start_index + 3 <= end_index + && memcmp (string + start_index, "nan", 3) == 0) + { + start_index += 3; + if (start_index == end_index + || (string[start_index] == '(' && string[end_index - 1] == ')')) + return 1; + } + } + return 0; +} +static char buf[10000]; +static long double zeroL = 0.0L; +int main () +{ + nocrash_init(); + if (sprintf (buf, "%Lf", 1.0L / 0.0L) < 0 + || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0)) + return 1; + if (sprintf (buf, "%Lf", -1.0L / 0.0L) < 0 + || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0)) + return 1; + if (sprintf (buf, "%Lf", zeroL / zeroL) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", 1.0L / 0.0L) < 0 + || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0)) + return 1; + if (sprintf (buf, "%Le", -1.0L / 0.0L) < 0 + || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0)) + return 1; + if (sprintf (buf, "%Le", zeroL / zeroL) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", 1.0L / 0.0L) < 0 + || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0)) + return 1; + if (sprintf (buf, "%Lg", -1.0L / 0.0L) < 0 + || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0)) + return 1; + if (sprintf (buf, "%Lg", zeroL / zeroL) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; +#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) +/* Representation of an 80-bit 'long double' as an initializer for a sequence + of 'unsigned int' words. */ +# ifdef WORDS_BIGENDIAN +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \ + ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16), \ + (unsigned int) (mantlo) << 16 \ + } +# else +# define LDBL80_WORDS(exponent,manthi,mantlo) \ + { mantlo, manthi, exponent } +# endif + { /* Quiet NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } + { /* Pseudo-NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + if (sprintf (buf, "%Lf", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Le", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + if (sprintf (buf, "%Lg", x.value) < 0 + || !strisnan (buf, 0, strlen (buf))) + return 1; + } +#endif + return 0; +}]])], + [gl_cv_func_printf_infinite_long_double=yes], + [gl_cv_func_printf_infinite_long_double=no], + [ +changequote(,)dnl + case "$host_cpu" in + # Guess no on ia64, x86_64, i386. + ia64 | x86_64 | i*86) gl_cv_func_printf_infinite_long_double="guessing no";; + *) + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_infinite_long_double="guessing yes";; + # Guess yes on FreeBSD >= 6. + freebsd[1-5]*) gl_cv_func_printf_infinite_long_double="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_printf_infinite_long_double="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_printf_infinite_long_double="guessing no";; + darwin*) gl_cv_func_printf_infinite_long_double="guessing yes";; + # Guess yes on HP-UX >= 11. + hpux[7-9]* | hpux10*) gl_cv_func_printf_infinite_long_double="guessing no";; + hpux*) gl_cv_func_printf_infinite_long_double="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_printf_infinite_long_double="guessing no";; + netbsd*) gl_cv_func_printf_infinite_long_double="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_infinite_long_double="guessing no";; + esac + ;; + esac +changequote([,])dnl + ]) + ]) + ;; + *) + gl_cv_func_printf_infinite_long_double="irrelevant" + ;; + esac +]) + +dnl Test whether the *printf family of functions supports the 'a' and 'A' +dnl conversion specifier for hexadecimal output of floating-point numbers. +dnl (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_directive_a. + +AC_DEFUN([gl_PRINTF_DIRECTIVE_A], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the 'a' and 'A' directives], + [gl_cv_func_printf_directive_a], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + if (sprintf (buf, "%a %d", 3.1416015625, 33, 44, 55) < 0 + || (strcmp (buf, "0x1.922p+1 33") != 0 + && strcmp (buf, "0x3.244p+0 33") != 0 + && strcmp (buf, "0x6.488p-1 33") != 0 + && strcmp (buf, "0xc.91p-2 33") != 0)) + return 1; + if (sprintf (buf, "%A %d", -3.1416015625, 33, 44, 55) < 0 + || (strcmp (buf, "-0X1.922P+1 33") != 0 + && strcmp (buf, "-0X3.244P+0 33") != 0 + && strcmp (buf, "-0X6.488P-1 33") != 0 + && strcmp (buf, "-0XC.91P-2 33") != 0)) + return 1; + /* This catches a FreeBSD 6.1 bug: it doesn't round. */ + if (sprintf (buf, "%.2a %d", 1.51, 33, 44, 55) < 0 + || (strcmp (buf, "0x1.83p+0 33") != 0 + && strcmp (buf, "0x3.05p-1 33") != 0 + && strcmp (buf, "0x6.0ap-2 33") != 0 + && strcmp (buf, "0xc.14p-3 33") != 0)) + return 1; + /* This catches a FreeBSD 6.1 bug. See + */ + if (sprintf (buf, "%010a %d", 1.0 / 0.0, 33, 44, 55) < 0 + || buf[0] == '0') + return 1; + /* This catches a MacOS X 10.3.9 (Darwin 7.9) bug. */ + if (sprintf (buf, "%.1a", 1.999) < 0 + || (strcmp (buf, "0x1.0p+1") != 0 + && strcmp (buf, "0x2.0p+0") != 0 + && strcmp (buf, "0x4.0p-1") != 0 + && strcmp (buf, "0x8.0p-2") != 0)) + return 1; + /* This catches the same MacOS X 10.3.9 (Darwin 7.9) bug and also a + glibc 2.4 bug . */ + if (sprintf (buf, "%.1La", 1.999L) < 0 + || (strcmp (buf, "0x1.0p+1") != 0 + && strcmp (buf, "0x2.0p+0") != 0 + && strcmp (buf, "0x4.0p-1") != 0 + && strcmp (buf, "0x8.0p-2") != 0)) + return 1; + return 0; +}]])], + [gl_cv_func_printf_directive_a=yes], + [gl_cv_func_printf_directive_a=no], + [ + case "$host_os" in + # Guess yes on glibc >= 2.5 systems. + *-gnu*) + AC_EGREP_CPP([BZ2908], [ + #include + #ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 5) || (__GLIBC__ > 2) + BZ2908 + #endif + #endif + ], + [gl_cv_func_printf_directive_a="guessing yes"], + [gl_cv_func_printf_directive_a="guessing no"]) + ;; + # If we don't know, assume the worst. + *) gl_cv_func_printf_directive_a="guessing no";; + esac + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports the %F format +dnl directive. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_directive_f. + +AC_DEFUN([gl_PRINTF_DIRECTIVE_F], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the 'F' directive], + [gl_cv_func_printf_directive_f], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + if (sprintf (buf, "%F %d", 1234567.0, 33, 44, 55) < 0 + || strcmp (buf, "1234567.000000 33") != 0) + return 1; + if (sprintf (buf, "%F", 1.0 / 0.0) < 0 + || (strcmp (buf, "INF") != 0 && strcmp (buf, "INFINITY") != 0)) + return 1; + /* This catches a Cygwin 1.5.x bug. */ + if (sprintf (buf, "%.F", 1234.0) < 0 + || strcmp (buf, "1234") != 0) + return 1; + return 0; +}]])], + [gl_cv_func_printf_directive_f=yes], + [gl_cv_func_printf_directive_f=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_directive_f="guessing yes";; + # Guess yes on FreeBSD >= 6. + freebsd[1-5]*) gl_cv_func_printf_directive_f="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_printf_directive_f="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_printf_directive_f="guessing no";; + darwin*) gl_cv_func_printf_directive_f="guessing yes";; + # Guess yes on Solaris >= 2.10. + solaris2.[0-9]*) gl_cv_func_printf_directive_f="guessing no";; + solaris*) gl_cv_func_printf_directive_f="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_directive_f="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports the %n format +dnl directive. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_printf_directive_n. + +AC_DEFUN([gl_PRINTF_DIRECTIVE_N], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the 'n' directive], + [gl_cv_func_printf_directive_n], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char fmtstring[10]; +static char buf[100]; +int main () +{ + int count = -1; + /* Copy the format string. Some systems (glibc with _FORTIFY_SOURCE=2) + support %n in format strings in read-only memory but not in writable + memory. */ + strcpy (fmtstring, "%d %n"); + if (sprintf (buf, fmtstring, 123, &count, 33, 44, 55) < 0 + || strcmp (buf, "123 ") != 0 + || count != 4) + return 1; + return 0; +}]])], + [gl_cv_func_printf_directive_n=yes], + [gl_cv_func_printf_directive_n=no], + [ +changequote(,)dnl + case "$host_os" in + *) gl_cv_func_printf_directive_n="guessing yes";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports the %ls format +dnl directive and in particular, when a precision is specified, whether +dnl the functions stop converting the wide string argument when the number +dnl of bytes that have been produced by this conversion equals or exceeds +dnl the precision. +dnl Result is gl_cv_func_printf_directive_ls. + +AC_DEFUN([gl_PRINTF_DIRECTIVE_LS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the 'ls' directive], + [gl_cv_func_printf_directive_ls], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +/* 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 +#include +int main () +{ + char buf[100]; + /* Test whether %ls works at all. + This test fails on OpenBSD 4.0, IRIX 6.5, Solaris 2.6, Haiku, but not on + Cygwin 1.5. */ + { + static const wchar_t wstring[] = { 'a', 'b', 'c', 0 }; + buf[0] = '\0'; + if (sprintf (buf, "%ls", wstring) < 0 + || strcmp (buf, "abc") != 0) + return 1; + } + /* This test fails on IRIX 6.5, Solaris 2.6, Cygwin 1.5, Haiku (with an + assertion failure inside libc), but not on OpenBSD 4.0. */ + { + static const wchar_t wstring[] = { 'a', 0 }; + buf[0] = '\0'; + if (sprintf (buf, "%ls", wstring) < 0 + || strcmp (buf, "a") != 0) + return 1; + } + /* Test whether precisions in %ls are supported as specified in ISO C 99 + section 7.19.6.1: + "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." + This test fails on Solaris 10. */ + { + static const wchar_t wstring[] = { 'a', 'b', (wchar_t) 0xfdfdfdfd, 0 }; + buf[0] = '\0'; + if (sprintf (buf, "%.2ls", wstring) < 0 + || strcmp (buf, "ab") != 0) + return 1; + } + return 0; +}]])], + [gl_cv_func_printf_directive_ls=yes], + [gl_cv_func_printf_directive_ls=no], + [ +changequote(,)dnl + case "$host_os" in + openbsd*) gl_cv_func_printf_directive_ls="guessing no";; + irix*) gl_cv_func_printf_directive_ls="guessing no";; + solaris*) gl_cv_func_printf_directive_ls="guessing no";; + cygwin*) gl_cv_func_printf_directive_ls="guessing no";; + beos* | haiku*) gl_cv_func_printf_directive_ls="guessing no";; + *) gl_cv_func_printf_directive_ls="guessing yes";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports POSIX/XSI format +dnl strings with positions. (POSIX:2001) +dnl Result is gl_cv_func_printf_positions. + +AC_DEFUN([gl_PRINTF_POSITIONS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports POSIX/XSI format strings with positions], + [gl_cv_func_printf_positions], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}]])], + [gl_cv_func_printf_positions=yes], + [gl_cv_func_printf_positions=no], + [ +changequote(,)dnl + case "$host_os" in + netbsd[1-3]* | netbsdelf[1-3]* | netbsdaout[1-3]* | netbsdcoff[1-3]*) + gl_cv_func_printf_positions="guessing no";; + beos*) gl_cv_func_printf_positions="guessing no";; + mingw* | pw*) gl_cv_func_printf_positions="guessing no";; + *) gl_cv_func_printf_positions="guessing yes";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports POSIX/XSI format +dnl strings with the ' flag for grouping of decimal digits. (POSIX:2001) +dnl Result is gl_cv_func_printf_flag_grouping. + +AC_DEFUN([gl_PRINTF_FLAG_GROUPING], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the grouping flag], + [gl_cv_func_printf_flag_grouping], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + if (sprintf (buf, "%'d %d", 1234567, 99) < 0 + || buf[strlen (buf) - 1] != '9') + return 1; + return 0; +}]])], + [gl_cv_func_printf_flag_grouping=yes], + [gl_cv_func_printf_flag_grouping=no], + [ +changequote(,)dnl + case "$host_os" in + cygwin*) gl_cv_func_printf_flag_grouping="guessing no";; + netbsd*) gl_cv_func_printf_flag_grouping="guessing no";; + mingw* | pw*) gl_cv_func_printf_flag_grouping="guessing no";; + *) gl_cv_func_printf_flag_grouping="guessing yes";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports the - flag correctly. +dnl (ISO C99.) See +dnl +dnl Result is gl_cv_func_printf_flag_leftadjust. + +AC_DEFUN([gl_PRINTF_FLAG_LEFTADJUST], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the left-adjust flag correctly], + [gl_cv_func_printf_flag_leftadjust], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + /* Check that a '-' flag is not annihilated by a negative width. */ + if (sprintf (buf, "a%-*sc", -3, "b") < 0 + || strcmp (buf, "ab c") != 0) + return 1; + return 0; +}]])], + [gl_cv_func_printf_flag_leftadjust=yes], + [gl_cv_func_printf_flag_leftadjust=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on HP-UX 11. + hpux11*) gl_cv_func_printf_flag_leftadjust="guessing yes";; + # Guess no on HP-UX 10 and older. + hpux*) gl_cv_func_printf_flag_leftadjust="guessing no";; + # Guess yes otherwise. + *) gl_cv_func_printf_flag_leftadjust="guessing yes";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports padding of non-finite +dnl values with the 0 flag correctly. (ISO C99 + TC1 + TC2.) See +dnl +dnl Result is gl_cv_func_printf_flag_zero. + +AC_DEFUN([gl_PRINTF_FLAG_ZERO], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the zero flag correctly], + [gl_cv_func_printf_flag_zero], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + if (sprintf (buf, "%010f", 1.0 / 0.0, 33, 44, 55) < 0 + || (strcmp (buf, " inf") != 0 + && strcmp (buf, " infinity") != 0)) + return 1; + return 0; +}]])], + [gl_cv_func_printf_flag_zero=yes], + [gl_cv_func_printf_flag_zero=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_flag_zero="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_printf_flag_zero="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_flag_zero="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions supports large precisions. +dnl On mingw, precisions larger than 512 are treated like 512, in integer, +dnl floating-point or pointer output. On BeOS, precisions larger than 1044 +dnl crash the program. +dnl Result is gl_cv_func_printf_precision. + +AC_DEFUN([gl_PRINTF_PRECISION], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports large precisions], + [gl_cv_func_printf_precision], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[5000]; +int main () +{ +#ifdef __BEOS__ + /* On BeOS, this would crash and show a dialog box. Avoid the crash. */ + return 1; +#endif + if (sprintf (buf, "%.4000d %d", 1, 33, 44) < 4000 + 3) + return 1; + return 0; +}]])], + [gl_cv_func_printf_precision=yes], + [gl_cv_func_printf_precision=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess no only on native Win32 and BeOS systems. + mingw* | pw*) gl_cv_func_printf_precision="guessing no" ;; + beos*) gl_cv_func_printf_precision="guessing no" ;; + *) gl_cv_func_printf_precision="guessing yes" ;; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the *printf family of functions recovers gracefully in case +dnl of an out-of-memory condition, or whether it crashes the entire program. +dnl Result is gl_cv_func_printf_enomem. + +AC_DEFUN([gl_PRINTF_ENOMEM], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gl_MULTIARCH]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf survives out-of-memory conditions], + [gl_cv_func_printf_enomem], + [ + gl_cv_func_printf_enomem="guessing no" + if test "$cross_compiling" = no; then + if test $APPLE_UNIVERSAL_BUILD = 0; then + AC_LANG_CONFTEST([AC_LANG_SOURCE([ +]GL_NOCRASH[ +changequote(,)dnl +#include +#include +#include +#include +#include +int main() +{ + struct rlimit limit; + int ret; + nocrash_init (); + /* Some printf implementations allocate temporary space with malloc. */ + /* On BSD systems, malloc() is limited by RLIMIT_DATA. */ +#ifdef RLIMIT_DATA + if (getrlimit (RLIMIT_DATA, &limit) < 0) + return 77; + if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000) + limit.rlim_max = 5000000; + limit.rlim_cur = limit.rlim_max; + if (setrlimit (RLIMIT_DATA, &limit) < 0) + return 77; +#endif + /* On Linux systems, malloc() is limited by RLIMIT_AS. */ +#ifdef RLIMIT_AS + if (getrlimit (RLIMIT_AS, &limit) < 0) + return 77; + if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000) + limit.rlim_max = 5000000; + limit.rlim_cur = limit.rlim_max; + if (setrlimit (RLIMIT_AS, &limit) < 0) + return 77; +#endif + /* Some printf implementations allocate temporary space on the stack. */ +#ifdef RLIMIT_STACK + if (getrlimit (RLIMIT_STACK, &limit) < 0) + return 77; + if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000) + limit.rlim_max = 5000000; + limit.rlim_cur = limit.rlim_max; + if (setrlimit (RLIMIT_STACK, &limit) < 0) + return 77; +#endif + ret = printf ("%.5000000f", 1.0); + return !(ret == 5000002 || (ret < 0 && errno == ENOMEM)); +} +changequote([,])dnl + ])]) + if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then + (./conftest + result=$? + if test $result != 0 && test $result != 77; then result=1; fi + exit $result + ) >/dev/null 2>/dev/null + case $? in + 0) gl_cv_func_printf_enomem="yes" ;; + 77) gl_cv_func_printf_enomem="guessing no" ;; + *) gl_cv_func_printf_enomem="no" ;; + esac + else + gl_cv_func_printf_enomem="guessing no" + fi + rm -fr conftest* + else + dnl A universal build on Apple MacOS X platforms. + dnl The result would be 'no' in 32-bit mode and 'yes' in 64-bit mode. + dnl But we need a configuration result that is valid in both modes. + gl_cv_func_printf_enomem="guessing no" + fi + fi + if test "$gl_cv_func_printf_enomem" = "guessing no"; then +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_enomem="guessing yes";; + # Guess yes on Solaris. + solaris*) gl_cv_func_printf_enomem="guessing yes";; + # Guess yes on AIX. + aix*) gl_cv_func_printf_enomem="guessing yes";; + # Guess yes on HP-UX/hppa. + hpux*) case "$host_cpu" in + hppa*) gl_cv_func_printf_enomem="guessing yes";; + *) gl_cv_func_printf_enomem="guessing no";; + esac + ;; + # Guess yes on IRIX. + irix*) gl_cv_func_printf_enomem="guessing yes";; + # Guess yes on OSF/1. + osf*) gl_cv_func_printf_enomem="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_printf_enomem="guessing yes";; + # Guess yes on Haiku. + haiku*) gl_cv_func_printf_enomem="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_enomem="guessing no";; + esac +changequote([,])dnl + fi + ]) +]) + +dnl Test whether the snprintf function exists. (ISO C99, POSIX:2001) +dnl Result is ac_cv_func_snprintf. + +AC_DEFUN([gl_SNPRINTF_PRESENCE], +[ + AC_CHECK_FUNCS_ONCE([snprintf]) +]) + +dnl Test whether the string produced by the snprintf function is always NUL +dnl terminated. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_snprintf_truncation_c99. + +AC_DEFUN([gl_SNPRINTF_TRUNCATION_C99], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether snprintf truncates the result as in C99], + [gl_cv_func_snprintf_truncation_c99], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + strcpy (buf, "ABCDEF"); + snprintf (buf, 3, "%d %d", 4567, 89); + if (memcmp (buf, "45\0DEF", 6) != 0) + return 1; + return 0; +}]])], + [gl_cv_func_snprintf_truncation_c99=yes], + [gl_cv_func_snprintf_truncation_c99=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on FreeBSD >= 5. + freebsd[1-4]*) gl_cv_func_snprintf_truncation_c99="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_snprintf_truncation_c99="guessing no";; + darwin*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on OpenBSD >= 3.9. + openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*) + gl_cv_func_snprintf_truncation_c99="guessing no";; + openbsd*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on Solaris >= 2.6. + solaris2.[0-5]*) gl_cv_func_snprintf_truncation_c99="guessing no";; + solaris*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on AIX >= 4. + aix[1-3]*) gl_cv_func_snprintf_truncation_c99="guessing no";; + aix*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on HP-UX >= 11. + hpux[7-9]* | hpux10*) gl_cv_func_snprintf_truncation_c99="guessing no";; + hpux*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on IRIX >= 6.5. + irix6.5) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on OSF/1 >= 5. + osf[3-4]*) gl_cv_func_snprintf_truncation_c99="guessing no";; + osf*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_snprintf_truncation_c99="guessing no";; + netbsd*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_snprintf_truncation_c99="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_snprintf_truncation_c99="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the return value of the snprintf function is the number +dnl of bytes (excluding the terminating NUL) that would have been produced +dnl if the buffer had been large enough. (ISO C99, POSIX:2001) +dnl For example, this test program fails on IRIX 6.5: +dnl --------------------------------------------------------------------- +dnl #include +dnl int main() +dnl { +dnl static char buf[8]; +dnl int retval = snprintf (buf, 3, "%d", 12345); +dnl return retval >= 0 && retval < 3; +dnl } +dnl --------------------------------------------------------------------- +dnl Result is gl_cv_func_snprintf_retval_c99. + +AC_DEFUN_ONCE([gl_SNPRINTF_RETVAL_C99], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether snprintf returns a byte count as in C99], + [gl_cv_func_snprintf_retval_c99], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char buf[100]; +int main () +{ + strcpy (buf, "ABCDEF"); + if (snprintf (buf, 3, "%d %d", 4567, 89) != 7) + return 1; + return 0; +}]])], + [gl_cv_func_snprintf_retval_c99=yes], + [gl_cv_func_snprintf_retval_c99=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on FreeBSD >= 5. + freebsd[1-4]*) gl_cv_func_snprintf_retval_c99="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_snprintf_retval_c99="guessing no";; + darwin*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on OpenBSD >= 3.9. + openbsd[1-2].* | openbsd3.[0-8] | openbsd3.[0-8].*) + gl_cv_func_snprintf_retval_c99="guessing no";; + openbsd*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on Solaris >= 2.6. + solaris2.[0-5]*) gl_cv_func_snprintf_retval_c99="guessing no";; + solaris*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on AIX >= 4. + aix[1-3]*) gl_cv_func_snprintf_retval_c99="guessing no";; + aix*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_snprintf_retval_c99="guessing no";; + netbsd*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_snprintf_retval_c99="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_snprintf_retval_c99="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the snprintf function supports the %n format directive +dnl also in truncated portions of the format string. (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_snprintf_directive_n. + +AC_DEFUN([gl_SNPRINTF_DIRECTIVE_N], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether snprintf fully supports the 'n' directive], + [gl_cv_func_snprintf_directive_n], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static char fmtstring[10]; +static char buf[100]; +int main () +{ + int count = -1; + /* Copy the format string. Some systems (glibc with _FORTIFY_SOURCE=2) + support %n in format strings in read-only memory but not in writable + memory. */ + strcpy (fmtstring, "%d %n"); + snprintf (buf, 4, fmtstring, 12345, &count, 33, 44, 55); + if (count != 6) + return 1; + return 0; +}]])], + [gl_cv_func_snprintf_directive_n=yes], + [gl_cv_func_snprintf_directive_n=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on FreeBSD >= 5. + freebsd[1-4]*) gl_cv_func_snprintf_directive_n="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_snprintf_directive_n="guessing no";; + darwin*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on Solaris >= 2.6. + solaris2.[0-5]*) gl_cv_func_snprintf_directive_n="guessing no";; + solaris*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on AIX >= 4. + aix[1-3]*) gl_cv_func_snprintf_directive_n="guessing no";; + aix*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on IRIX >= 6.5. + irix6.5) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on OSF/1 >= 5. + osf[3-4]*) gl_cv_func_snprintf_directive_n="guessing no";; + osf*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_snprintf_directive_n="guessing no";; + netbsd*) gl_cv_func_snprintf_directive_n="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_snprintf_directive_n="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_snprintf_directive_n="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl Test whether the snprintf function, when passed a size = 1, writes any +dnl output without bounds in this case, behaving like sprintf. This is the +dnl case on Linux libc5. +dnl Result is gl_cv_func_snprintf_size1. + +AC_DEFUN([gl_SNPRINTF_SIZE1], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([whether snprintf respects a size of 1], + [gl_cv_func_snprintf_size1], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +int main() +{ + static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' }; + snprintf (buf, 1, "%d", 12345); + return buf[1] != 'E'; +}]])], + [gl_cv_func_snprintf_size1=yes], + [gl_cv_func_snprintf_size1=no], + [gl_cv_func_snprintf_size1="guessing yes"]) + ]) +]) + +dnl Test whether the vsnprintf function, when passed a zero size, produces no +dnl output. (ISO C99, POSIX:2001) +dnl For example, snprintf nevertheless writes a NUL byte in this case +dnl on OSF/1 5.1: +dnl --------------------------------------------------------------------- +dnl #include +dnl int main() +dnl { +dnl static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' }; +dnl snprintf (buf, 0, "%d", 12345); +dnl return buf[0] != 'D'; +dnl } +dnl --------------------------------------------------------------------- +dnl And vsnprintf writes any output without bounds in this case, behaving like +dnl vsprintf, on HP-UX 11 and OSF/1 5.1: +dnl --------------------------------------------------------------------- +dnl #include +dnl #include +dnl static int my_snprintf (char *buf, int size, const char *format, ...) +dnl { +dnl va_list args; +dnl int ret; +dnl va_start (args, format); +dnl ret = vsnprintf (buf, size, format, args); +dnl va_end (args); +dnl return ret; +dnl } +dnl int main() +dnl { +dnl static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' }; +dnl my_snprintf (buf, 0, "%d", 12345); +dnl return buf[0] != 'D'; +dnl } +dnl --------------------------------------------------------------------- +dnl Result is gl_cv_func_vsnprintf_zerosize_c99. + +AC_DEFUN([gl_VSNPRINTF_ZEROSIZE_C99], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether vsnprintf respects a zero size as in C99], + [gl_cv_func_vsnprintf_zerosize_c99], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static int my_snprintf (char *buf, int size, const char *format, ...) +{ + va_list args; + int ret; + va_start (args, format); + ret = vsnprintf (buf, size, format, args); + va_end (args); + return ret; +} +int main() +{ + static char buf[8] = { 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F' }; + my_snprintf (buf, 0, "%d", 12345); + return buf[0] != 'D'; +}]])], + [gl_cv_func_vsnprintf_zerosize_c99=yes], + [gl_cv_func_vsnprintf_zerosize_c99=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on FreeBSD >= 5. + freebsd[1-4]*) gl_cv_func_vsnprintf_zerosize_c99="guessing no";; + freebsd* | kfreebsd*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on MacOS X >= 10.3. + darwin[1-6].*) gl_cv_func_vsnprintf_zerosize_c99="guessing no";; + darwin*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on Cygwin. + cygwin*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on Solaris >= 2.6. + solaris2.[0-5]*) gl_cv_func_vsnprintf_zerosize_c99="guessing no";; + solaris*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on AIX >= 4. + aix[1-3]*) gl_cv_func_vsnprintf_zerosize_c99="guessing no";; + aix*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on IRIX >= 6.5. + irix6.5) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on NetBSD >= 3. + netbsd[1-2]* | netbsdelf[1-2]* | netbsdaout[1-2]* | netbsdcoff[1-2]*) + gl_cv_func_vsnprintf_zerosize_c99="guessing no";; + netbsd*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # Guess yes on mingw. + mingw* | pw*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_vsnprintf_zerosize_c99="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + +dnl The results of these tests on various platforms are: +dnl +dnl 1 = gl_PRINTF_SIZES_C99 +dnl 2 = gl_PRINTF_LONG_DOUBLE +dnl 3 = gl_PRINTF_INFINITE +dnl 4 = gl_PRINTF_INFINITE_LONG_DOUBLE +dnl 5 = gl_PRINTF_DIRECTIVE_A +dnl 6 = gl_PRINTF_DIRECTIVE_F +dnl 7 = gl_PRINTF_DIRECTIVE_N +dnl 8 = gl_PRINTF_DIRECTIVE_LS +dnl 9 = gl_PRINTF_POSITIONS +dnl 10 = gl_PRINTF_FLAG_GROUPING +dnl 11 = gl_PRINTF_FLAG_LEFTADJUST +dnl 12 = gl_PRINTF_FLAG_ZERO +dnl 13 = gl_PRINTF_PRECISION +dnl 14 = gl_PRINTF_ENOMEM +dnl 15 = gl_SNPRINTF_PRESENCE +dnl 16 = gl_SNPRINTF_TRUNCATION_C99 +dnl 17 = gl_SNPRINTF_RETVAL_C99 +dnl 18 = gl_SNPRINTF_DIRECTIVE_N +dnl 19 = gl_SNPRINTF_SIZE1 +dnl 20 = gl_VSNPRINTF_ZEROSIZE_C99 +dnl +dnl 1 = checking whether printf supports size specifiers as in C99... +dnl 2 = checking whether printf supports 'long double' arguments... +dnl 3 = checking whether printf supports infinite 'double' arguments... +dnl 4 = checking whether printf supports infinite 'long double' arguments... +dnl 5 = checking whether printf supports the 'a' and 'A' directives... +dnl 6 = checking whether printf supports the 'F' directive... +dnl 7 = checking whether printf supports the 'n' directive... +dnl 8 = checking whether printf supports the 'ls' directive... +dnl 9 = checking whether printf supports POSIX/XSI format strings with positions... +dnl 10 = checking whether printf supports the grouping flag... +dnl 11 = checking whether printf supports the left-adjust flag correctly... +dnl 12 = checking whether printf supports the zero flag correctly... +dnl 13 = checking whether printf supports large precisions... +dnl 14 = checking whether printf survives out-of-memory conditions... +dnl 15 = checking for snprintf... +dnl 16 = checking whether snprintf truncates the result as in C99... +dnl 17 = checking whether snprintf returns a byte count as in C99... +dnl 18 = checking whether snprintf fully supports the 'n' directive... +dnl 19 = checking whether snprintf respects a size of 1... +dnl 20 = checking whether vsnprintf respects a zero size as in C99... +dnl +dnl . = yes, # = no. +dnl +dnl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 +dnl glibc 2.5 . . . . . . . . . . . . . . . . . . . . +dnl glibc 2.3.6 . . . . # . . . . . . . . . . . . . . . +dnl FreeBSD 5.4, 6.1 . . . . # . . . . . . # . # . . . . . . +dnl MacOS X 10.3.9 . . . . # . . . . . . # . # . . . . . . +dnl OpenBSD 3.9, 4.0 . . # # # # . # . # . # . # . . . . . . +dnl Cygwin 1.7.0 (2009) . . . # . . . ? . . . . . ? . . . . . . +dnl Cygwin 1.5.25 (2008) . . . # # . . # . . . . . # . . . . . . +dnl Cygwin 1.5.19 (2006) # . . # # # . # . # . # # # . . . . . . +dnl Solaris 10 . . # # # . . # . . . # . . . . . . . . +dnl Solaris 2.6 ... 9 # . # # # # . # . . . # . . . . . . . . +dnl Solaris 2.5.1 # . # # # # . # . . . # . . # # # # # # +dnl AIX 5.2, 7.1 . . # # # . . . . . . # . . . . . . . . +dnl AIX 4.3.2, 5.1 # . # # # # . . . . . # . . . . . . . . +dnl HP-UX 11.31 . . . . # . . . . . . # . . . . # # . . +dnl HP-UX 11.{00,11,23} # . . . # # . . . . . # . . . . # # . # +dnl HP-UX 10.20 # . # . # # . ? . . # # . . . . # # ? # +dnl IRIX 6.5 # . # # # # . # . . . # . . . . # . . . +dnl OSF/1 5.1 # . # # # # . . . . . # . . . . # . . # +dnl OSF/1 4.0d # . # # # # . . . . . # . . # # # # # # +dnl NetBSD 4.0 . ? ? ? ? ? . ? . ? ? ? ? ? . . . ? ? ? +dnl NetBSD 3.0 . . . . # # . ? # # ? # . # . . . . . . +dnl Haiku . . . # # # . # . . . . . ? . . . . . . +dnl BeOS # # . # # # . ? # . ? . # ? . . . . . . +dnl mingw # # # # # # . . # # . # # ? . # # # . . diff --git a/m4/progtest.m4 b/m4/progtest.m4 new file mode 100644 index 000000000..9ffa5c020 --- /dev/null +++ b/m4/progtest.m4 @@ -0,0 +1,91 @@ +# progtest.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1996-2003, 2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1996. + +AC_PREREQ([2.50]) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL([ac_cv_path_$1], +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$][$1]) +else + AC_MSG_RESULT([no]) +fi +AC_SUBST([$1])dnl +]) diff --git a/m4/rawmemchr.m4 b/m4/rawmemchr.m4 new file mode 100644 index 000000000..2a25a4904 --- /dev/null +++ b/m4/rawmemchr.m4 @@ -0,0 +1,21 @@ +# rawmemchr.m4 serial 1 +dnl Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_RAWMEMCHR], +[ + dnl Persuade glibc to declare rawmemchr(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_REPLACE_FUNCS([rawmemchr]) + if test $ac_cv_func_rawmemchr = no; then + HAVE_RAWMEMCHR=0 + gl_PREREQ_RAWMEMCHR + fi +]) + +# Prerequisites of lib/strchrnul.c. +AC_DEFUN([gl_PREREQ_RAWMEMCHR], [:]) diff --git a/m4/realloc.m4 b/m4/realloc.m4 new file mode 100644 index 000000000..01c1234f7 --- /dev/null +++ b/m4/realloc.m4 @@ -0,0 +1,44 @@ +# realloc.m4 serial 11 +dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# gl_FUNC_REALLOC_GNU +# ------------------- +# Test whether 'realloc (0, 0)' is handled like in GNU libc, and replace +# realloc if it is not. +AC_DEFUN([gl_FUNC_REALLOC_GNU], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + dnl _AC_FUNC_REALLOC_IF is defined in Autoconf. + _AC_FUNC_REALLOC_IF( + [AC_DEFINE([HAVE_REALLOC_GNU], [1], + [Define to 1 if your system has a GNU libc compatible 'realloc' + function, and to 0 otherwise.])], + [AC_DEFINE([HAVE_REALLOC_GNU], [0]) + gl_REPLACE_REALLOC + ]) +])# gl_FUNC_REALLOC_GNU + +# gl_FUNC_REALLOC_POSIX +# --------------------- +# Test whether 'realloc' is POSIX compliant (sets errno to ENOMEM when it +# fails), and replace realloc if it is not. +AC_DEFUN([gl_FUNC_REALLOC_POSIX], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_REQUIRE([gl_CHECK_MALLOC_POSIX]) + if test $gl_cv_func_malloc_posix = yes; then + AC_DEFINE([HAVE_REALLOC_POSIX], [1], + [Define if the 'realloc' function is POSIX compliant.]) + else + gl_REPLACE_REALLOC + fi +]) + +AC_DEFUN([gl_REPLACE_REALLOC], +[ + AC_LIBOBJ([realloc]) + REPLACE_REALLOC=1 +]) diff --git a/m4/regex.m4 b/m4/regex.m4 new file mode 100644 index 000000000..38f1dd76b --- /dev/null +++ b/m4/regex.m4 @@ -0,0 +1,235 @@ +# serial 56 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# +# 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. + +dnl Initially derived from code in GNU grep. +dnl Mostly written by Jim Meyering. + +AC_PREREQ([2.50]) + +AC_DEFUN([gl_REGEX], +[ + AC_CHECK_HEADERS_ONCE([locale.h]) + + AC_ARG_WITH([included-regex], + [AS_HELP_STRING([--without-included-regex], + [don't compile regex; this is the default on systems + with recent-enough versions of the GNU C Library + (use with caution on other systems).])]) + + case $with_included_regex in #( + yes|no) ac_use_included_regex=$with_included_regex + ;; + '') + # If the system regex support is good enough that it passes the + # following run test, then default to *not* using the included regex.c. + # If cross compiling, assume the test would fail and use the included + # regex.c. + AC_CACHE_CHECK([for working re_compile_pattern], + [gl_cv_func_re_compile_pattern_working], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT[ + #if HAVE_LOCALE_H + #include + #endif + #include + #include + ]], + [[static struct re_pattern_buffer regex; + unsigned char folded_chars[UCHAR_MAX + 1]; + int i; + const char *s; + struct re_registers regs; + + #if HAVE_LOCALE_H + /* http://sourceware.org/ml/libc-hacker/2006-09/msg00008.html + This test needs valgrind to catch the bug on Debian + GNU/Linux 3.1 x86, but it might catch the bug better + on other platforms and it shouldn't hurt to try the + test here. */ + if (setlocale (LC_ALL, "en_US.UTF-8")) + { + static char const pat[] = "insert into"; + static char const data[] = + "\xFF\0\x12\xA2\xAA\xC4\xB1,K\x12\xC4\xB1*\xACK"; + re_set_syntax (RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE + | RE_ICASE); + memset (®ex, 0, sizeof regex); + s = re_compile_pattern (pat, sizeof pat - 1, ®ex); + if (s) + return 1; + if (re_search (®ex, data, sizeof data - 1, + 0, sizeof data - 1, ®s) + != -1) + return 1; + if (! setlocale (LC_ALL, "C")) + return 1; + } + #endif + + /* This test is from glibc bug 3957, reported by Andrew Mackey. */ + re_set_syntax (RE_SYNTAX_EGREP | RE_HAT_LISTS_NOT_NEWLINE); + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("a[^x]b", 6, ®ex); + if (s) + return 1; + + /* This should fail, but succeeds for glibc-2.5. */ + if (re_search (®ex, "a\nb", 3, 0, 3, ®s) != -1) + return 1; + + /* This regular expression is from Spencer ere test number 75 + in grep-2.3. */ + re_set_syntax (RE_SYNTAX_POSIX_EGREP); + memset (®ex, 0, sizeof regex); + for (i = 0; i <= UCHAR_MAX; i++) + folded_chars[i] = i; + regex.translate = folded_chars; + s = re_compile_pattern ("a[[:@:>@:]]b\n", 11, ®ex); + /* This should fail with _Invalid character class name_ error. */ + if (!s) + return 1; + + /* Ensure that [b-a] is diagnosed as invalid, when + using RE_NO_EMPTY_RANGES. */ + re_set_syntax (RE_SYNTAX_POSIX_EGREP | RE_NO_EMPTY_RANGES); + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("a[b-a]", 6, ®ex); + if (s == 0) + return 1; + + /* This should succeed, but does not for glibc-2.1.3. */ + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("{1", 2, ®ex); + + if (s) + return 1; + + /* The following example is derived from a problem report + against gawk from Jorge Stolfi . */ + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("[an\371]*n", 7, ®ex); + if (s) + return 1; + + /* This should match, but does not for glibc-2.2.1. */ + if (re_match (®ex, "an", 2, 0, ®s) != 2) + return 1; + + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("x", 1, ®ex); + if (s) + return 1; + + /* glibc-2.2.93 does not work with a negative RANGE argument. */ + if (re_search (®ex, "wxy", 3, 2, -2, ®s) != 1) + return 1; + + /* The version of regex.c in older versions of gnulib + ignored RE_ICASE. Detect that problem too. */ + re_set_syntax (RE_SYNTAX_EMACS | RE_ICASE); + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("x", 1, ®ex); + if (s) + return 1; + + if (re_search (®ex, "WXY", 3, 0, 3, ®s) < 0) + return 1; + + /* Catch a bug reported by Vin Shelton in + http://lists.gnu.org/archive/html/bug-coreutils/2007-06/msg00089.html + */ + re_set_syntax (RE_SYNTAX_POSIX_BASIC + & ~RE_CONTEXT_INVALID_DUP + & ~RE_NO_EMPTY_RANGES); + memset (®ex, 0, sizeof regex); + s = re_compile_pattern ("[[:alnum:]_-]\\\\+$", 16, ®ex); + if (s) + return 1; + + /* REG_STARTEND was added to glibc on 2004-01-15. + Reject older versions. */ + if (! REG_STARTEND) + return 1; + +#if 0 + /* It would be nice to reject hosts whose regoff_t values are too + narrow (including glibc on hosts with 64-bit ptrdiff_t and + 32-bit int), but we should wait until glibc implements this + feature. Otherwise, support for equivalence classes and + multibyte collation symbols would always be broken except + when compiling --without-included-regex. */ + if (sizeof (regoff_t) < sizeof (ptrdiff_t) + || sizeof (regoff_t) < sizeof (ssize_t)) + return 1; +#endif + + return 0;]])], + [gl_cv_func_re_compile_pattern_working=yes], + [gl_cv_func_re_compile_pattern_working=no], + dnl When crosscompiling, assume it is not working. + [gl_cv_func_re_compile_pattern_working=no])]) + case $gl_cv_func_re_compile_pattern_working in #( + yes) ac_use_included_regex=no;; #( + no) ac_use_included_regex=yes;; + esac + ;; + *) AC_MSG_ERROR([Invalid value for --with-included-regex: $with_included_regex]) + ;; + esac + + if test $ac_use_included_regex = yes; then + AC_DEFINE([_REGEX_LARGE_OFFSETS], [1], + [Define if you want regoff_t to be at least as wide POSIX requires.]) + AC_DEFINE([re_syntax_options], [rpl_re_syntax_options], + [Define to rpl_re_syntax_options if the replacement should be used.]) + AC_DEFINE([re_set_syntax], [rpl_re_set_syntax], + [Define to rpl_re_set_syntax if the replacement should be used.]) + AC_DEFINE([re_compile_pattern], [rpl_re_compile_pattern], + [Define to rpl_re_compile_pattern if the replacement should be used.]) + AC_DEFINE([re_compile_fastmap], [rpl_re_compile_fastmap], + [Define to rpl_re_compile_fastmap if the replacement should be used.]) + AC_DEFINE([re_search], [rpl_re_search], + [Define to rpl_re_search if the replacement should be used.]) + AC_DEFINE([re_search_2], [rpl_re_search_2], + [Define to rpl_re_search_2 if the replacement should be used.]) + AC_DEFINE([re_match], [rpl_re_match], + [Define to rpl_re_match if the replacement should be used.]) + AC_DEFINE([re_match_2], [rpl_re_match_2], + [Define to rpl_re_match_2 if the replacement should be used.]) + AC_DEFINE([re_set_registers], [rpl_re_set_registers], + [Define to rpl_re_set_registers if the replacement should be used.]) + AC_DEFINE([re_comp], [rpl_re_comp], + [Define to rpl_re_comp if the replacement should be used.]) + AC_DEFINE([re_exec], [rpl_re_exec], + [Define to rpl_re_exec if the replacement should be used.]) + AC_DEFINE([regcomp], [rpl_regcomp], + [Define to rpl_regcomp if the replacement should be used.]) + AC_DEFINE([regexec], [rpl_regexec], + [Define to rpl_regexec if the replacement should be used.]) + AC_DEFINE([regerror], [rpl_regerror], + [Define to rpl_regerror if the replacement should be used.]) + AC_DEFINE([regfree], [rpl_regfree], + [Define to rpl_regfree if the replacement should be used.]) + AC_LIBOBJ([regex]) + gl_PREREQ_REGEX + fi +]) + +# Prerequisites of lib/regex.c and lib/regex_internal.c. +AC_DEFUN([gl_PREREQ_REGEX], +[ + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + AC_CHECK_HEADERS([libintl.h]) + AC_CHECK_FUNCS_ONCE([isblank iswctype wcscoll]) + AC_CHECK_DECLS([isblank], [], [], [#include ]) +]) diff --git a/m4/size_max.m4 b/m4/size_max.m4 new file mode 100644 index 000000000..f3b1a9dfb --- /dev/null +++ b/m4/size_max.m4 @@ -0,0 +1,79 @@ +# size_max.m4 serial 10 +dnl Copyright (C) 2003, 2005-2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS([stdint.h]) + dnl First test whether the system already has SIZE_MAX. + AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [ + gl_cv_size_max= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], [gl_cv_size_max=yes]) + if test -z "$gl_cv_size_max"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include +#include ], [size_t_bits_minus_1=]) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include ], [fits_in_uint=]) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + extern size_t foo; + extern unsigned long foo; + ]], + [[]])], + [fits_in_uint=0]) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi + dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after + dnl . Remember that the #undef in AH_VERBATIM gets replaced with + dnl #define by AC_DEFINE_UNQUOTED. + AH_VERBATIM([SIZE_MAX], +[/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +#ifndef SIZE_MAX +# undef SIZE_MAX +#endif]) +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) diff --git a/m4/sleep.m4 b/m4/sleep.m4 new file mode 100644 index 000000000..a5ec65520 --- /dev/null +++ b/m4/sleep.m4 @@ -0,0 +1,49 @@ +# sleep.m4 serial 3 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_SLEEP], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + dnl We expect to see the declaration of sleep() in a header file. + dnl Older versions of mingw have a sleep() function that is an alias to + dnl _sleep() in MSVCRT. It has a different signature than POSIX sleep(): + dnl it takes the number of milliseconds as argument and returns void. + dnl mingw does not declare this function. + AC_CHECK_DECLS([sleep], , , [#include ]) + AC_CHECK_FUNCS_ONCE([sleep]) + if test $ac_cv_have_decl_sleep != yes; then + HAVE_SLEEP=0 + AC_LIBOBJ([sleep]) + else + dnl Cygwin 1.5.x has a bug where sleep can't exceed 49.7 days. + AC_CACHE_CHECK([for working sleep], [gl_cv_func_sleep_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include +static void +handle_alarm (int sig) +{ + if (sig != SIGALRM) + _exit (2); +} +]], [[ + /* Failure to compile this test due to missing alarm is okay, + since all such platforms (mingw) also lack sleep. */ + unsigned int pentecost = 50 * 24 * 60 * 60; /* 50 days. */ + unsigned int remaining; + signal (SIGALRM, handle_alarm); + alarm (1); + remaining = sleep (pentecost); + return !(pentecost - 10 < remaining && remaining <= pentecost);]])], + [gl_cv_func_sleep_works=yes], [gl_cv_func_sleep_works=no], + [gl_cv_func_sleep_works="guessing no"])]) + if test "$gl_cv_func_sleep_works" != yes; then + REPLACE_SLEEP=1 + AC_LIBOBJ([sleep]) + fi + fi +]) diff --git a/m4/ssize_t.m4 b/m4/ssize_t.m4 new file mode 100644 index 000000000..e4c160b50 --- /dev/null +++ b/m4/ssize_t.m4 @@ -0,0 +1,23 @@ +# ssize_t.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2001-2003, 2006, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether ssize_t is defined. + +AC_DEFUN([gt_TYPE_SSIZE_T], +[ + AC_CACHE_CHECK([for ssize_t], [gt_cv_ssize_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[int x = sizeof (ssize_t *) + sizeof (ssize_t); + return !x;]])], + [gt_cv_ssize_t=yes], [gt_cv_ssize_t=no])]) + if test $gt_cv_ssize_t = no; then + AC_DEFINE([ssize_t], [int], + [Define as a signed type of the same size as size_t.]) + fi +]) diff --git a/m4/stdbool.m4 b/m4/stdbool.m4 new file mode 100644 index 000000000..1efe59ea1 --- /dev/null +++ b/m4/stdbool.m4 @@ -0,0 +1,103 @@ +# Check for stdbool.h that conforms to C99. + +dnl Copyright (C) 2002-2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +#serial 3 + +# Prepare for substituting if it is not supported. + +AC_DEFUN([AM_STDBOOL_H], +[ + AC_REQUIRE([AC_HEADER_STDBOOL]) + + # Define two additional variables used in the Makefile substitution. + + if test "$ac_cv_header_stdbool_h" = yes; then + STDBOOL_H='' + else + STDBOOL_H='stdbool.h' + fi + AC_SUBST([STDBOOL_H]) + + if test "$ac_cv_type__Bool" = yes; then + HAVE__BOOL=1 + else + HAVE__BOOL=0 + fi + AC_SUBST([HAVE__BOOL]) +]) + +# AM_STDBOOL_H will be renamed to gl_STDBOOL_H in the future. +AC_DEFUN([gl_STDBOOL_H], [AM_STDBOOL_H]) + +# This version of the macro is needed in autoconf <= 2.67. Autoconf has +# it built in since 2.60, but we want the tweaks from the 2.68 version +# to avoid rejecting xlc and clang due to relying on extensions. + +AC_DEFUN([AC_HEADER_STDBOOL], + [AC_CACHE_CHECK([for stdbool.h that conforms to C99], + [ac_cv_header_stdbool_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ + #include + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #endif + #ifndef true + "error: true is not defined" + #endif + #if true != 1 + "error: true is not 1" + #endif + #ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" + #endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) 0.5 == true ? 1 : -1]; + /* See body of main program for 'e'. */ + char f[(_Bool) 0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + _Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + */ + _Bool q = true; + _Bool *pq = &q; + ]], + [[ + bool e = &s; + *pq |= q; + *pq |= ! q; + /* Refer to every declared value, to avoid compiler optimizations. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + + !m + !n + !o + !p + !q + !pq); + ]])], + [ac_cv_header_stdbool_h=yes], + [ac_cv_header_stdbool_h=no])]) + AC_CHECK_TYPES([_Bool]) + if test $ac_cv_header_stdbool_h = yes; then + AC_DEFINE([HAVE_STDBOOL_H], [1], [Define to 1 if stdbool.h conforms to C99.]) + fi]) diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4 new file mode 100644 index 000000000..c3ae56943 --- /dev/null +++ b/m4/stddef_h.m4 @@ -0,0 +1,45 @@ +dnl A placeholder for POSIX 2008 , for platforms that have issues. +# stddef_h.m4 serial 2 +dnl Copyright (C) 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_STDDEF_H], +[ + AC_REQUIRE([gl_STDDEF_H_DEFAULTS]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + if test $gt_cv_c_wchar_t = no; then + HAVE_WCHAR_T=0 + STDDEF_H=stddef.h + fi + AC_CACHE_CHECK([whether NULL can be used in arbitrary expressions], + [gl_cv_decl_null_works], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + int test[2 * (sizeof NULL == sizeof (void *)) -1]; +]])], + [gl_cv_decl_null_works=yes], + [gl_cv_decl_null_works=no])]) + if test $gl_cv_decl_null_works = no; then + REPLACE_NULL=1 + STDDEF_H=stddef.h + fi + if test -n "$STDDEF_H"; then + gl_CHECK_NEXT_HEADERS([stddef.h]) + fi +]) + +AC_DEFUN([gl_STDDEF_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_STDDEF_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) +]) + +AC_DEFUN([gl_STDDEF_H_DEFAULTS], +[ + dnl Assume proper GNU behavior unless another module says otherwise. + REPLACE_NULL=0; AC_SUBST([REPLACE_NULL]) + HAVE_WCHAR_T=1; AC_SUBST([HAVE_WCHAR_T]) + STDDEF_H=''; AC_SUBST([STDDEF_H]) +]) diff --git a/m4/stdint.m4 b/m4/stdint.m4 new file mode 100644 index 000000000..c5e813a96 --- /dev/null +++ b/m4/stdint.m4 @@ -0,0 +1,472 @@ +# stdint.m4 serial 35 +dnl Copyright (C) 2001-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert and Bruno Haible. +dnl Test whether is supported or must be substituted. + +AC_DEFUN([gl_STDINT_H], +[ + AC_PREREQ([2.59])dnl + + dnl Check for long long int and unsigned long long int. + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + if test $ac_cv_type_long_long_int = yes; then + HAVE_LONG_LONG_INT=1 + else + HAVE_LONG_LONG_INT=0 + fi + AC_SUBST([HAVE_LONG_LONG_INT]) + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + HAVE_UNSIGNED_LONG_LONG_INT=1 + else + HAVE_UNSIGNED_LONG_LONG_INT=0 + fi + AC_SUBST([HAVE_UNSIGNED_LONG_LONG_INT]) + + dnl Check for . + dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_inttypes_h. + if test $ac_cv_header_inttypes_h = yes; then + HAVE_INTTYPES_H=1 + else + HAVE_INTTYPES_H=0 + fi + AC_SUBST([HAVE_INTTYPES_H]) + + dnl Check for . + dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_sys_types_h. + if test $ac_cv_header_sys_types_h = yes; then + HAVE_SYS_TYPES_H=1 + else + HAVE_SYS_TYPES_H=0 + fi + AC_SUBST([HAVE_SYS_TYPES_H]) + + gl_CHECK_NEXT_HEADERS([stdint.h]) + if test $ac_cv_header_stdint_h = yes; then + HAVE_STDINT_H=1 + else + HAVE_STDINT_H=0 + fi + AC_SUBST([HAVE_STDINT_H]) + + dnl Now see whether we need a substitute . + if test $ac_cv_header_stdint_h = yes; then + AC_CACHE_CHECK([whether stdint.h conforms to C99], + [gl_cv_header_working_stdint_h], + [gl_cv_header_working_stdint_h=no + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */ +#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */ +#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */ +#include +/* Dragonfly defines WCHAR_MIN, WCHAR_MAX only in . */ +#if !(defined WCHAR_MIN && defined WCHAR_MAX) +#error "WCHAR_MIN, WCHAR_MAX not defined in " +#endif +] +gl_STDINT_INCLUDES +[ +#ifdef INT8_MAX +int8_t a1 = INT8_MAX; +int8_t a1min = INT8_MIN; +#endif +#ifdef INT16_MAX +int16_t a2 = INT16_MAX; +int16_t a2min = INT16_MIN; +#endif +#ifdef INT32_MAX +int32_t a3 = INT32_MAX; +int32_t a3min = INT32_MIN; +#endif +#ifdef INT64_MAX +int64_t a4 = INT64_MAX; +int64_t a4min = INT64_MIN; +#endif +#ifdef UINT8_MAX +uint8_t b1 = UINT8_MAX; +#else +typedef int b1[(unsigned char) -1 != 255 ? 1 : -1]; +#endif +#ifdef UINT16_MAX +uint16_t b2 = UINT16_MAX; +#endif +#ifdef UINT32_MAX +uint32_t b3 = UINT32_MAX; +#endif +#ifdef UINT64_MAX +uint64_t b4 = UINT64_MAX; +#endif +int_least8_t c1 = INT8_C (0x7f); +int_least8_t c1max = INT_LEAST8_MAX; +int_least8_t c1min = INT_LEAST8_MIN; +int_least16_t c2 = INT16_C (0x7fff); +int_least16_t c2max = INT_LEAST16_MAX; +int_least16_t c2min = INT_LEAST16_MIN; +int_least32_t c3 = INT32_C (0x7fffffff); +int_least32_t c3max = INT_LEAST32_MAX; +int_least32_t c3min = INT_LEAST32_MIN; +int_least64_t c4 = INT64_C (0x7fffffffffffffff); +int_least64_t c4max = INT_LEAST64_MAX; +int_least64_t c4min = INT_LEAST64_MIN; +uint_least8_t d1 = UINT8_C (0xff); +uint_least8_t d1max = UINT_LEAST8_MAX; +uint_least16_t d2 = UINT16_C (0xffff); +uint_least16_t d2max = UINT_LEAST16_MAX; +uint_least32_t d3 = UINT32_C (0xffffffff); +uint_least32_t d3max = UINT_LEAST32_MAX; +uint_least64_t d4 = UINT64_C (0xffffffffffffffff); +uint_least64_t d4max = UINT_LEAST64_MAX; +int_fast8_t e1 = INT_FAST8_MAX; +int_fast8_t e1min = INT_FAST8_MIN; +int_fast16_t e2 = INT_FAST16_MAX; +int_fast16_t e2min = INT_FAST16_MIN; +int_fast32_t e3 = INT_FAST32_MAX; +int_fast32_t e3min = INT_FAST32_MIN; +int_fast64_t e4 = INT_FAST64_MAX; +int_fast64_t e4min = INT_FAST64_MIN; +uint_fast8_t f1 = UINT_FAST8_MAX; +uint_fast16_t f2 = UINT_FAST16_MAX; +uint_fast32_t f3 = UINT_FAST32_MAX; +uint_fast64_t f4 = UINT_FAST64_MAX; +#ifdef INTPTR_MAX +intptr_t g = INTPTR_MAX; +intptr_t gmin = INTPTR_MIN; +#endif +#ifdef UINTPTR_MAX +uintptr_t h = UINTPTR_MAX; +#endif +intmax_t i = INTMAX_MAX; +uintmax_t j = UINTMAX_MAX; + +#include /* for CHAR_BIT */ +#define TYPE_MINIMUM(t) \ + ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) +#define TYPE_MAXIMUM(t) \ + ((t) ((t) 0 < (t) -1 ? (t) -1 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) +struct s { + int check_PTRDIFF: + PTRDIFF_MIN == TYPE_MINIMUM (ptrdiff_t) + && PTRDIFF_MAX == TYPE_MAXIMUM (ptrdiff_t) + ? 1 : -1; + /* Detect bug in FreeBSD 6.0 / ia64. */ + int check_SIG_ATOMIC: + SIG_ATOMIC_MIN == TYPE_MINIMUM (sig_atomic_t) + && SIG_ATOMIC_MAX == TYPE_MAXIMUM (sig_atomic_t) + ? 1 : -1; + int check_SIZE: SIZE_MAX == TYPE_MAXIMUM (size_t) ? 1 : -1; + int check_WCHAR: + WCHAR_MIN == TYPE_MINIMUM (wchar_t) + && WCHAR_MAX == TYPE_MAXIMUM (wchar_t) + ? 1 : -1; + /* Detect bug in mingw. */ + int check_WINT: + WINT_MIN == TYPE_MINIMUM (wint_t) + && WINT_MAX == TYPE_MAXIMUM (wint_t) + ? 1 : -1; + + /* Detect bugs in glibc 2.4 and Solaris 10 stdint.h, among others. */ + int check_UINT8_C: + (-1 < UINT8_C (0)) == (-1 < (uint_least8_t) 0) ? 1 : -1; + int check_UINT16_C: + (-1 < UINT16_C (0)) == (-1 < (uint_least16_t) 0) ? 1 : -1; + + /* Detect bugs in OpenBSD 3.9 stdint.h. */ +#ifdef UINT8_MAX + int check_uint8: (uint8_t) -1 == UINT8_MAX ? 1 : -1; +#endif +#ifdef UINT16_MAX + int check_uint16: (uint16_t) -1 == UINT16_MAX ? 1 : -1; +#endif +#ifdef UINT32_MAX + int check_uint32: (uint32_t) -1 == UINT32_MAX ? 1 : -1; +#endif +#ifdef UINT64_MAX + int check_uint64: (uint64_t) -1 == UINT64_MAX ? 1 : -1; +#endif + int check_uint_least8: (uint_least8_t) -1 == UINT_LEAST8_MAX ? 1 : -1; + int check_uint_least16: (uint_least16_t) -1 == UINT_LEAST16_MAX ? 1 : -1; + int check_uint_least32: (uint_least32_t) -1 == UINT_LEAST32_MAX ? 1 : -1; + int check_uint_least64: (uint_least64_t) -1 == UINT_LEAST64_MAX ? 1 : -1; + int check_uint_fast8: (uint_fast8_t) -1 == UINT_FAST8_MAX ? 1 : -1; + int check_uint_fast16: (uint_fast16_t) -1 == UINT_FAST16_MAX ? 1 : -1; + int check_uint_fast32: (uint_fast32_t) -1 == UINT_FAST32_MAX ? 1 : -1; + int check_uint_fast64: (uint_fast64_t) -1 == UINT_FAST64_MAX ? 1 : -1; + int check_uintptr: (uintptr_t) -1 == UINTPTR_MAX ? 1 : -1; + int check_uintmax: (uintmax_t) -1 == UINTMAX_MAX ? 1 : -1; + int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1; +}; + ]])], + [dnl Determine whether the various *_MIN, *_MAX macros are usable + dnl in preprocessor expression. We could do it by compiling a test + dnl program for each of these macros. It is faster to run a program + dnl that inspects the macro expansion. + dnl This detects a bug on HP-UX 11.23/ia64. + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */ +#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */ +#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */ +#include +] +gl_STDINT_INCLUDES +[ +#include +#include +#define MVAL(macro) MVAL1(macro) +#define MVAL1(expression) #expression +static const char *macro_values[] = + { +#ifdef INT8_MAX + MVAL (INT8_MAX), +#endif +#ifdef INT16_MAX + MVAL (INT16_MAX), +#endif +#ifdef INT32_MAX + MVAL (INT32_MAX), +#endif +#ifdef INT64_MAX + MVAL (INT64_MAX), +#endif +#ifdef UINT8_MAX + MVAL (UINT8_MAX), +#endif +#ifdef UINT16_MAX + MVAL (UINT16_MAX), +#endif +#ifdef UINT32_MAX + MVAL (UINT32_MAX), +#endif +#ifdef UINT64_MAX + MVAL (UINT64_MAX), +#endif + NULL + }; +]], [[ + const char **mv; + for (mv = macro_values; *mv != NULL; mv++) + { + const char *value = *mv; + /* Test whether it looks like a cast expression. */ + if (strncmp (value, "((unsigned int)"/*)*/, 15) == 0 + || strncmp (value, "((unsigned short)"/*)*/, 17) == 0 + || strncmp (value, "((unsigned char)"/*)*/, 16) == 0 + || strncmp (value, "((int)"/*)*/, 6) == 0 + || strncmp (value, "((signed short)"/*)*/, 15) == 0 + || strncmp (value, "((signed char)"/*)*/, 14) == 0) + return 1; + } + return 0; +]])], + [gl_cv_header_working_stdint_h=yes], + [], + [dnl When cross-compiling, assume it works. + gl_cv_header_working_stdint_h=yes + ]) + ]) + ]) + fi + if test "$gl_cv_header_working_stdint_h" = yes; then + STDINT_H= + else + dnl Check for , and for + dnl (used in Linux libc4 >= 4.6.7 and libc5). + AC_CHECK_HEADERS([sys/inttypes.h sys/bitypes.h]) + if test $ac_cv_header_sys_inttypes_h = yes; then + HAVE_SYS_INTTYPES_H=1 + else + HAVE_SYS_INTTYPES_H=0 + fi + AC_SUBST([HAVE_SYS_INTTYPES_H]) + if test $ac_cv_header_sys_bitypes_h = yes; then + HAVE_SYS_BITYPES_H=1 + else + HAVE_SYS_BITYPES_H=0 + fi + AC_SUBST([HAVE_SYS_BITYPES_H]) + + dnl Check for (missing in Linux uClibc when built without wide + dnl character support). + AC_CHECK_HEADERS_ONCE([wchar.h]) + + gl_STDINT_TYPE_PROPERTIES + STDINT_H=stdint.h + fi + AC_SUBST([STDINT_H]) +]) + +dnl gl_STDINT_BITSIZEOF(TYPES, INCLUDES) +dnl Determine the size of each of the given types in bits. +AC_DEFUN([gl_STDINT_BITSIZEOF], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + m4_foreach_w([gltype], [$1], + [AH_TEMPLATE([BITSIZEOF_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [Define to the number of bits in type ']gltype['.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([for bit size of $gltype], [gl_cv_bitsizeof_${gltype}], + [AC_COMPUTE_INT([result], [sizeof ($gltype) * CHAR_BIT], + [$2 +#include ], [result=unknown]) + eval gl_cv_bitsizeof_${gltype}=\$result + ]) + eval result=\$gl_cv_bitsizeof_${gltype} + if test $result = unknown; then + dnl Use a nonempty default, because some compilers, such as IRIX 5 cc, + dnl do a syntax check even on unused #if conditions and give an error + dnl on valid C code like this: + dnl #if 0 + dnl # if > 32 + dnl # endif + dnl #endif + result=0 + fi + GLTYPE=`echo "$gltype" | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + AC_DEFINE_UNQUOTED([BITSIZEOF_${GLTYPE}], [$result]) + eval BITSIZEOF_${GLTYPE}=\$result + done + m4_foreach_w([gltype], [$1], + [AC_SUBST([BITSIZEOF_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) +]) + +dnl gl_CHECK_TYPES_SIGNED(TYPES, INCLUDES) +dnl Determine the signedness of each of the given types. +dnl Define HAVE_SIGNED_TYPE if type is signed. +AC_DEFUN([gl_CHECK_TYPES_SIGNED], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + m4_foreach_w([gltype], [$1], + [AH_TEMPLATE([HAVE_SIGNED_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [Define to 1 if ']gltype[' is a signed integer type.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([whether $gltype is signed], [gl_cv_type_${gltype}_signed], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2[ + int verify[2 * (($gltype) -1 < ($gltype) 0) - 1];]])], + result=yes, result=no) + eval gl_cv_type_${gltype}_signed=\$result + ]) + eval result=\$gl_cv_type_${gltype}_signed + GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + if test "$result" = yes; then + AC_DEFINE_UNQUOTED([HAVE_SIGNED_${GLTYPE}], [1]) + eval HAVE_SIGNED_${GLTYPE}=1 + else + eval HAVE_SIGNED_${GLTYPE}=0 + fi + done + m4_foreach_w([gltype], [$1], + [AC_SUBST([HAVE_SIGNED_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) +]) + +dnl gl_INTEGER_TYPE_SUFFIX(TYPES, INCLUDES) +dnl Determine the suffix to use for integer constants of the given types. +dnl Define t_SUFFIX for each such type. +AC_DEFUN([gl_INTEGER_TYPE_SUFFIX], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + m4_foreach_w([gltype], [$1], + [AH_TEMPLATE(m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX], + [Define to l, ll, u, ul, ull, etc., as suitable for + constants of type ']gltype['.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([for $gltype integer literal suffix], + [gl_cv_type_${gltype}_suffix], + [eval gl_cv_type_${gltype}_suffix=no + eval result=\$gl_cv_type_${gltype}_signed + if test "$result" = yes; then + glsufu= + else + glsufu=u + fi + for glsuf in "$glsufu" ${glsufu}l ${glsufu}ll ${glsufu}i64; do + case $glsuf in + '') gltype1='int';; + l) gltype1='long int';; + ll) gltype1='long long int';; + i64) gltype1='__int64';; + u) gltype1='unsigned int';; + ul) gltype1='unsigned long int';; + ull) gltype1='unsigned long long int';; + ui64)gltype1='unsigned __int64';; + esac + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2[ + extern $gltype foo; + extern $gltype1 foo;]])], + [eval gl_cv_type_${gltype}_suffix=\$glsuf]) + eval result=\$gl_cv_type_${gltype}_suffix + test "$result" != no && break + done]) + GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + eval result=\$gl_cv_type_${gltype}_suffix + test "$result" = no && result= + eval ${GLTYPE}_SUFFIX=\$result + AC_DEFINE_UNQUOTED([${GLTYPE}_SUFFIX], [$result]) + done + m4_foreach_w([gltype], [$1], + [AC_SUBST(m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])]) +]) + +dnl gl_STDINT_INCLUDES +AC_DEFUN([gl_STDINT_INCLUDES], +[[ + /* BSD/OS 4.0.1 has a bug: , and must be + included before . */ + #include + #include + #if HAVE_WCHAR_H + # include + # include + # include + #endif +]]) + +dnl gl_STDINT_TYPE_PROPERTIES +dnl Compute HAVE_SIGNED_t, BITSIZEOF_t and t_SUFFIX, for all the types t +dnl of interest to stdint.in.h. +AC_DEFUN([gl_STDINT_TYPE_PROPERTIES], +[ + AC_REQUIRE([gl_MULTIARCH]) + if test $APPLE_UNIVERSAL_BUILD = 0; then + gl_STDINT_BITSIZEOF([ptrdiff_t size_t], + [gl_STDINT_INCLUDES]) + fi + gl_STDINT_BITSIZEOF([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + gl_CHECK_TYPES_SIGNED([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + gl_cv_type_ptrdiff_t_signed=yes + gl_cv_type_size_t_signed=no + if test $APPLE_UNIVERSAL_BUILD = 0; then + gl_INTEGER_TYPE_SUFFIX([ptrdiff_t size_t], + [gl_STDINT_INCLUDES]) + fi + gl_INTEGER_TYPE_SUFFIX([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) + +# Hey Emacs! +# Local Variables: +# indent-tabs-mode: nil +# End: diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4 new file mode 100644 index 000000000..670c0cc2b --- /dev/null +++ b/m4/stdint_h.m4 @@ -0,0 +1,27 @@ +# stdint_h.m4 serial 9 +dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include ]], + [[uintmax_t i = (uintmax_t) -1; return !i;]])], + [gl_cv_header_stdint_h=yes], + [gl_cv_header_stdint_h=no])]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1], + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4 new file mode 100644 index 000000000..f5650cdea --- /dev/null +++ b/m4/stdio_h.m4 @@ -0,0 +1,159 @@ +# stdio_h.m4 serial 31 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_STDIO_H], +[ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([gl_ASM_SYMBOL_PREFIX]) + gl_CHECK_NEXT_HEADERS([stdio.h]) + dnl No need to create extra modules for these functions. Everyone who uses + dnl likely needs them. + GNULIB_FPRINTF=1 + GNULIB_PRINTF=1 + GNULIB_VFPRINTF=1 + GNULIB_VPRINTF=1 + GNULIB_FPUTC=1 + GNULIB_PUTC=1 + GNULIB_PUTCHAR=1 + GNULIB_FPUTS=1 + GNULIB_PUTS=1 + GNULIB_FWRITE=1 + dnl This ifdef is just an optimization, to avoid performing a configure + dnl check whose result is not used. It does not make the test of + dnl GNULIB_STDIO_H_SIGPIPE or GNULIB_SIGPIPE redundant. + m4_ifdef([gl_SIGNAL_SIGPIPE], [ + gl_SIGNAL_SIGPIPE + if test $gl_cv_header_signal_h_SIGPIPE != yes; then + REPLACE_STDIO_WRITE_FUNCS=1 + AC_LIBOBJ([stdio-write]) + fi + ]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use, and which is not + dnl guaranteed by C89. + gl_WARN_ON_USE_PREPARE([[#include + ]], [dprintf fpurge fseeko ftello getdelim getline popen renameat + snprintf tmpfile vdprintf vsnprintf]) +]) + +AC_DEFUN([gl_STDIO_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_STDIO_H_DEFAULTS], +[ + GNULIB_DPRINTF=0; AC_SUBST([GNULIB_DPRINTF]) + GNULIB_FCLOSE=0; AC_SUBST([GNULIB_FCLOSE]) + GNULIB_FFLUSH=0; AC_SUBST([GNULIB_FFLUSH]) + GNULIB_FOPEN=0; AC_SUBST([GNULIB_FOPEN]) + GNULIB_FPRINTF=0; AC_SUBST([GNULIB_FPRINTF]) + GNULIB_FPRINTF_POSIX=0; AC_SUBST([GNULIB_FPRINTF_POSIX]) + GNULIB_FPURGE=0; AC_SUBST([GNULIB_FPURGE]) + GNULIB_FPUTC=0; AC_SUBST([GNULIB_FPUTC]) + GNULIB_FPUTS=0; AC_SUBST([GNULIB_FPUTS]) + GNULIB_FREOPEN=0; AC_SUBST([GNULIB_FREOPEN]) + GNULIB_FSEEK=0; AC_SUBST([GNULIB_FSEEK]) + GNULIB_FSEEKO=0; AC_SUBST([GNULIB_FSEEKO]) + GNULIB_FTELL=0; AC_SUBST([GNULIB_FTELL]) + GNULIB_FTELLO=0; AC_SUBST([GNULIB_FTELLO]) + GNULIB_FWRITE=0; AC_SUBST([GNULIB_FWRITE]) + GNULIB_GETDELIM=0; AC_SUBST([GNULIB_GETDELIM]) + GNULIB_GETLINE=0; AC_SUBST([GNULIB_GETLINE]) + GNULIB_OBSTACK_PRINTF=0; AC_SUBST([GNULIB_OBSTACK_PRINTF]) + GNULIB_OBSTACK_PRINTF_POSIX=0; AC_SUBST([GNULIB_OBSTACK_PRINTF_POSIX]) + GNULIB_PERROR=0; AC_SUBST([GNULIB_PERROR]) + GNULIB_POPEN=0; AC_SUBST([GNULIB_POPEN]) + GNULIB_PRINTF=0; AC_SUBST([GNULIB_PRINTF]) + GNULIB_PRINTF_POSIX=0; AC_SUBST([GNULIB_PRINTF_POSIX]) + GNULIB_PUTC=0; AC_SUBST([GNULIB_PUTC]) + GNULIB_PUTCHAR=0; AC_SUBST([GNULIB_PUTCHAR]) + GNULIB_PUTS=0; AC_SUBST([GNULIB_PUTS]) + GNULIB_REMOVE=0; AC_SUBST([GNULIB_REMOVE]) + GNULIB_RENAME=0; AC_SUBST([GNULIB_RENAME]) + GNULIB_RENAMEAT=0; AC_SUBST([GNULIB_RENAMEAT]) + GNULIB_SNPRINTF=0; AC_SUBST([GNULIB_SNPRINTF]) + GNULIB_SPRINTF_POSIX=0; AC_SUBST([GNULIB_SPRINTF_POSIX]) + GNULIB_STDIO_H_SIGPIPE=0; AC_SUBST([GNULIB_STDIO_H_SIGPIPE]) + GNULIB_TMPFILE=0; AC_SUBST([GNULIB_TMPFILE]) + GNULIB_VASPRINTF=0; AC_SUBST([GNULIB_VASPRINTF]) + GNULIB_VDPRINTF=0; AC_SUBST([GNULIB_VDPRINTF]) + GNULIB_VFPRINTF=0; AC_SUBST([GNULIB_VFPRINTF]) + GNULIB_VFPRINTF_POSIX=0; AC_SUBST([GNULIB_VFPRINTF_POSIX]) + GNULIB_VPRINTF=0; AC_SUBST([GNULIB_VPRINTF]) + GNULIB_VPRINTF_POSIX=0; AC_SUBST([GNULIB_VPRINTF_POSIX]) + GNULIB_VSNPRINTF=0; AC_SUBST([GNULIB_VSNPRINTF]) + GNULIB_VSPRINTF_POSIX=0; AC_SUBST([GNULIB_VSPRINTF_POSIX]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_DECL_FPURGE=1; AC_SUBST([HAVE_DECL_FPURGE]) + HAVE_DECL_GETDELIM=1; AC_SUBST([HAVE_DECL_GETDELIM]) + HAVE_DECL_GETLINE=1; AC_SUBST([HAVE_DECL_GETLINE]) + HAVE_DECL_OBSTACK_PRINTF=1; AC_SUBST([HAVE_DECL_OBSTACK_PRINTF]) + HAVE_DECL_SNPRINTF=1; AC_SUBST([HAVE_DECL_SNPRINTF]) + HAVE_DECL_VSNPRINTF=1; AC_SUBST([HAVE_DECL_VSNPRINTF]) + HAVE_DPRINTF=1; AC_SUBST([HAVE_DPRINTF]) + HAVE_FSEEKO=1; AC_SUBST([HAVE_FSEEKO]) + HAVE_FTELLO=1; AC_SUBST([HAVE_FTELLO]) + HAVE_RENAMEAT=1; AC_SUBST([HAVE_RENAMEAT]) + HAVE_VASPRINTF=1; AC_SUBST([HAVE_VASPRINTF]) + HAVE_VDPRINTF=1; AC_SUBST([HAVE_VDPRINTF]) + REPLACE_DPRINTF=0; AC_SUBST([REPLACE_DPRINTF]) + REPLACE_FCLOSE=0; AC_SUBST([REPLACE_FCLOSE]) + REPLACE_FFLUSH=0; AC_SUBST([REPLACE_FFLUSH]) + REPLACE_FOPEN=0; AC_SUBST([REPLACE_FOPEN]) + REPLACE_FPRINTF=0; AC_SUBST([REPLACE_FPRINTF]) + REPLACE_FPURGE=0; AC_SUBST([REPLACE_FPURGE]) + REPLACE_FREOPEN=0; AC_SUBST([REPLACE_FREOPEN]) + REPLACE_FSEEK=0; AC_SUBST([REPLACE_FSEEK]) + REPLACE_FSEEKO=0; AC_SUBST([REPLACE_FSEEKO]) + REPLACE_FTELL=0; AC_SUBST([REPLACE_FTELL]) + REPLACE_FTELLO=0; AC_SUBST([REPLACE_FTELLO]) + REPLACE_GETDELIM=0; AC_SUBST([REPLACE_GETDELIM]) + REPLACE_GETLINE=0; AC_SUBST([REPLACE_GETLINE]) + REPLACE_OBSTACK_PRINTF=0; AC_SUBST([REPLACE_OBSTACK_PRINTF]) + REPLACE_PERROR=0; AC_SUBST([REPLACE_PERROR]) + REPLACE_POPEN=0; AC_SUBST([REPLACE_POPEN]) + REPLACE_PRINTF=0; AC_SUBST([REPLACE_PRINTF]) + REPLACE_REMOVE=0; AC_SUBST([REPLACE_REMOVE]) + REPLACE_RENAME=0; AC_SUBST([REPLACE_RENAME]) + REPLACE_RENAMEAT=0; AC_SUBST([REPLACE_RENAMEAT]) + REPLACE_SNPRINTF=0; AC_SUBST([REPLACE_SNPRINTF]) + REPLACE_SPRINTF=0; AC_SUBST([REPLACE_SPRINTF]) + REPLACE_STDIO_WRITE_FUNCS=0; AC_SUBST([REPLACE_STDIO_WRITE_FUNCS]) + REPLACE_TMPFILE=0; AC_SUBST([REPLACE_TMPFILE]) + REPLACE_VASPRINTF=0; AC_SUBST([REPLACE_VASPRINTF]) + REPLACE_VDPRINTF=0; AC_SUBST([REPLACE_VDPRINTF]) + REPLACE_VFPRINTF=0; AC_SUBST([REPLACE_VFPRINTF]) + REPLACE_VPRINTF=0; AC_SUBST([REPLACE_VPRINTF]) + REPLACE_VSNPRINTF=0; AC_SUBST([REPLACE_VSNPRINTF]) + REPLACE_VSPRINTF=0; AC_SUBST([REPLACE_VSPRINTF]) +]) + +dnl Code shared by fseeko and ftello. Determine if large files are supported, +dnl but stdin does not start as a large file by default. +AC_DEFUN([gl_STDIN_LARGE_OFFSET], + [ + AC_CACHE_CHECK([whether stdin defaults to large file offsets], + [gl_cv_var_stdin_large_offset], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], +[[#if defined __SL64 && defined __SCLE /* cygwin */ + /* Cygwin 1.5.24 and earlier fail to put stdin in 64-bit mode, making + fseeko/ftello needlessly fail. This bug was fixed in 1.5.25, and + it is easier to do a version check than building a runtime test. */ +# include +# if CYGWIN_VERSION_DLL_COMBINED < CYGWIN_VERSION_DLL_MAKE_COMBINED (1005, 25) + choke me +# endif +#endif]])], + [gl_cv_var_stdin_large_offset=yes], + [gl_cv_var_stdin_large_offset=no])]) +]) diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4 new file mode 100644 index 000000000..fc150197b --- /dev/null +++ b/m4/stdlib_h.m4 @@ -0,0 +1,112 @@ +# stdlib_h.m4 serial 30 +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_STDLIB_H], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + gl_CHECK_NEXT_HEADERS([stdlib.h]) + AC_CHECK_HEADERS([random.h], [], [], [AC_INCLUDES_DEFAULT]) + if test $ac_cv_header_random_h = yes; then + HAVE_RANDOM_H=1 + else + HAVE_RANDOM_H=0 + fi + AC_SUBST([HAVE_RANDOM_H]) + AC_CHECK_TYPES([struct random_data], + [], [HAVE_STRUCT_RANDOM_DATA=0], + [[#include + #if HAVE_RANDOM_H + # include + #endif + ]]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use, and which is not + dnl guaranteed by C89. + gl_WARN_ON_USE_PREPARE([[#include +#if HAVE_SYS_LOADAVG_H +# include +#endif +#if HAVE_RANDOM_H +# include +#endif + ]], [_Exit atoll canonicalize_file_name getloadavg getsubopt grantpt mkdtemp + mkostemp mkostemps mkstemp mkstemps ptsname random_r initstat_r srandom_r + setstate_r realpath rpmatch setenv strtod strtoll strtoull unlockpt + unsetenv]) +]) + +AC_DEFUN([gl_STDLIB_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_STDLIB_H_DEFAULTS], +[ + GNULIB__EXIT=0; AC_SUBST([GNULIB__EXIT]) + GNULIB_ATOLL=0; AC_SUBST([GNULIB_ATOLL]) + GNULIB_CALLOC_POSIX=0; AC_SUBST([GNULIB_CALLOC_POSIX]) + GNULIB_CANONICALIZE_FILE_NAME=0; AC_SUBST([GNULIB_CANONICALIZE_FILE_NAME]) + GNULIB_GETLOADAVG=0; AC_SUBST([GNULIB_GETLOADAVG]) + GNULIB_GETSUBOPT=0; AC_SUBST([GNULIB_GETSUBOPT]) + GNULIB_GRANTPT=0; AC_SUBST([GNULIB_GRANTPT]) + GNULIB_MALLOC_POSIX=0; AC_SUBST([GNULIB_MALLOC_POSIX]) + GNULIB_MKDTEMP=0; AC_SUBST([GNULIB_MKDTEMP]) + GNULIB_MKOSTEMP=0; AC_SUBST([GNULIB_MKOSTEMP]) + GNULIB_MKOSTEMPS=0; AC_SUBST([GNULIB_MKOSTEMPS]) + GNULIB_MKSTEMP=0; AC_SUBST([GNULIB_MKSTEMP]) + GNULIB_MKSTEMPS=0; AC_SUBST([GNULIB_MKSTEMPS]) + GNULIB_PTSNAME=0; AC_SUBST([GNULIB_PTSNAME]) + GNULIB_PUTENV=0; AC_SUBST([GNULIB_PUTENV]) + GNULIB_RANDOM_R=0; AC_SUBST([GNULIB_RANDOM_R]) + GNULIB_REALLOC_POSIX=0; AC_SUBST([GNULIB_REALLOC_POSIX]) + GNULIB_REALPATH=0; AC_SUBST([GNULIB_REALPATH]) + GNULIB_RPMATCH=0; AC_SUBST([GNULIB_RPMATCH]) + GNULIB_SETENV=0; AC_SUBST([GNULIB_SETENV]) + GNULIB_STRTOD=0; AC_SUBST([GNULIB_STRTOD]) + GNULIB_STRTOLL=0; AC_SUBST([GNULIB_STRTOLL]) + GNULIB_STRTOULL=0; AC_SUBST([GNULIB_STRTOULL]) + GNULIB_UNLOCKPT=0; AC_SUBST([GNULIB_UNLOCKPT]) + GNULIB_UNSETENV=0; AC_SUBST([GNULIB_UNSETENV]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE__EXIT=1; AC_SUBST([HAVE__EXIT]) + HAVE_ATOLL=1; AC_SUBST([HAVE_ATOLL]) + HAVE_CANONICALIZE_FILE_NAME=1; AC_SUBST([HAVE_CANONICALIZE_FILE_NAME]) + HAVE_DECL_GETLOADAVG=1; AC_SUBST([HAVE_DECL_GETLOADAVG]) + HAVE_GETSUBOPT=1; AC_SUBST([HAVE_GETSUBOPT]) + HAVE_GRANTPT=1; AC_SUBST([HAVE_GRANTPT]) + HAVE_MKDTEMP=1; AC_SUBST([HAVE_MKDTEMP]) + HAVE_MKOSTEMP=1; AC_SUBST([HAVE_MKOSTEMP]) + HAVE_MKOSTEMPS=1; AC_SUBST([HAVE_MKOSTEMPS]) + HAVE_MKSTEMP=1; AC_SUBST([HAVE_MKSTEMP]) + HAVE_MKSTEMPS=1; AC_SUBST([HAVE_MKSTEMPS]) + HAVE_PTSNAME=1; AC_SUBST([HAVE_PTSNAME]) + HAVE_RANDOM_R=1; AC_SUBST([HAVE_RANDOM_R]) + HAVE_REALPATH=1; AC_SUBST([HAVE_REALPATH]) + HAVE_RPMATCH=1; AC_SUBST([HAVE_RPMATCH]) + HAVE_SETENV=1; AC_SUBST([HAVE_SETENV]) + HAVE_STRTOD=1; AC_SUBST([HAVE_STRTOD]) + HAVE_STRTOLL=1; AC_SUBST([HAVE_STRTOLL]) + HAVE_STRTOULL=1; AC_SUBST([HAVE_STRTOULL]) + HAVE_STRUCT_RANDOM_DATA=1; AC_SUBST([HAVE_STRUCT_RANDOM_DATA]) + HAVE_SYS_LOADAVG_H=0; AC_SUBST([HAVE_SYS_LOADAVG_H]) + HAVE_UNLOCKPT=1; AC_SUBST([HAVE_UNLOCKPT]) + HAVE_UNSETENV=1; AC_SUBST([HAVE_UNSETENV]) + REPLACE_CALLOC=0; AC_SUBST([REPLACE_CALLOC]) + REPLACE_CANONICALIZE_FILE_NAME=0; AC_SUBST([REPLACE_CANONICALIZE_FILE_NAME]) + REPLACE_MALLOC=0; AC_SUBST([REPLACE_MALLOC]) + REPLACE_MKSTEMP=0; AC_SUBST([REPLACE_MKSTEMP]) + REPLACE_PUTENV=0; AC_SUBST([REPLACE_PUTENV]) + REPLACE_REALLOC=0; AC_SUBST([REPLACE_REALLOC]) + REPLACE_REALPATH=0; AC_SUBST([REPLACE_REALPATH]) + REPLACE_SETENV=0; AC_SUBST([REPLACE_SETENV]) + REPLACE_STRTOD=0; AC_SUBST([REPLACE_STRTOD]) + REPLACE_UNSETENV=0; AC_SUBST([REPLACE_UNSETENV]) +]) diff --git a/m4/strcase.m4 b/m4/strcase.m4 new file mode 100644 index 000000000..33de423a0 --- /dev/null +++ b/m4/strcase.m4 @@ -0,0 +1,44 @@ +# strcase.m4 serial 10 +dnl Copyright (C) 2002, 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_STRCASE], +[ + gl_FUNC_STRCASECMP + gl_FUNC_STRNCASECMP +]) + +AC_DEFUN([gl_FUNC_STRCASECMP], +[ + AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS]) + AC_REPLACE_FUNCS([strcasecmp]) + if test $ac_cv_func_strcasecmp = no; then + HAVE_STRCASECMP=0 + gl_PREREQ_STRCASECMP + fi +]) + +AC_DEFUN([gl_FUNC_STRNCASECMP], +[ + AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS]) + AC_REPLACE_FUNCS([strncasecmp]) + if test $ac_cv_func_strncasecmp = no; then + gl_PREREQ_STRNCASECMP + fi + AC_CHECK_DECLS([strncasecmp]) + if test $ac_cv_have_decl_strncasecmp = no; then + HAVE_DECL_STRNCASECMP=0 + fi +]) + +# Prerequisites of lib/strcasecmp.c. +AC_DEFUN([gl_PREREQ_STRCASECMP], [ + : +]) + +# Prerequisites of lib/strncasecmp.c. +AC_DEFUN([gl_PREREQ_STRNCASECMP], [ + : +]) diff --git a/m4/strchrnul.m4 b/m4/strchrnul.m4 new file mode 100644 index 000000000..0072e60e7 --- /dev/null +++ b/m4/strchrnul.m4 @@ -0,0 +1,21 @@ +# strchrnul.m4 serial 7 +dnl Copyright (C) 2003, 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRCHRNUL], +[ + dnl Persuade glibc to declare strchrnul(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_REPLACE_FUNCS([strchrnul]) + if test $ac_cv_func_strchrnul = no; then + HAVE_STRCHRNUL=0 + gl_PREREQ_STRCHRNUL + fi +]) + +# Prerequisites of lib/strchrnul.c. +AC_DEFUN([gl_PREREQ_STRCHRNUL], [:]) diff --git a/m4/strerror.m4 b/m4/strerror.m4 new file mode 100644 index 000000000..1649b2451 --- /dev/null +++ b/m4/strerror.m4 @@ -0,0 +1,68 @@ +# strerror.m4 serial 9 +dnl Copyright (C) 2002, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRERROR], +[ + AC_REQUIRE([gl_FUNC_STRERROR_SEPARATE]) + if test $REPLACE_STRERROR = 1; then + AC_LIBOBJ([strerror]) + AC_DEFINE_UNQUOTED([REPLACE_STRERROR], [$REPLACE_STRERROR], + [Define this to 1 if strerror is broken.]) + fi +]) + +# Like gl_FUNC_STRERROR, except prepare for separate compilation (no AC_LIBOBJ). +AC_DEFUN([gl_FUNC_STRERROR_SEPARATE], +[ + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_REQUIRE([gl_HEADER_ERRNO_H]) + if test -z "$ERRNO_H"; then + AC_CACHE_CHECK([for working strerror function], + [gl_cv_func_working_strerror], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[return !*strerror (-2);]])], + [gl_cv_func_working_strerror=yes], + [gl_cv_func_working_strerror=no], + [dnl Assume crossbuild works if it compiles. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[return !*strerror (-2);]])], + [gl_cv_func_working_strerror=yes], + [gl_cv_func_working_strerror=no]) + ]) + ]) + if test $gl_cv_func_working_strerror = no; then + dnl The system's strerror() fails to return a string for out-of-range + dnl integers. Replace it. + REPLACE_STRERROR=1 + fi + else + dnl The system's strerror() cannot know about the new errno values we add + dnl to . Replace it. + REPLACE_STRERROR=1 + fi + if test $REPLACE_STRERROR = 1; then + gl_PREREQ_STRERROR + fi +]) + +# Prerequisites of lib/strerror.c. +AC_DEFUN([gl_PREREQ_STRERROR], [ + AC_CHECK_DECLS([strerror]) + AC_CHECK_HEADERS_ONCE([sys/socket.h]) + if test $ac_cv_header_sys_socket_h != yes; then + dnl We cannot use AC_CHECK_HEADERS_ONCE here, because that would make + dnl the check for those headers unconditional; yet cygwin reports + dnl that the headers are present but cannot be compiled (since on + dnl cygwin, all socket information should come from sys/socket.h). + AC_CHECK_HEADERS([winsock2.h]) + fi +]) diff --git a/m4/string_h.m4 b/m4/string_h.m4 new file mode 100644 index 000000000..1977aecf9 --- /dev/null +++ b/m4/string_h.m4 @@ -0,0 +1,112 @@ +# Configure a GNU-like replacement for . + +# Copyright (C) 2007-2010 Free Software Foundation, Inc. +# 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. + +# serial 17 + +# Written by Paul Eggert. + +AC_DEFUN([gl_HEADER_STRING_H], +[ + dnl Use AC_REQUIRE here, so that the default behavior below is expanded + dnl once only, before all statements that occur in other macros. + AC_REQUIRE([gl_HEADER_STRING_H_BODY]) +]) + +AC_DEFUN([gl_HEADER_STRING_H_BODY], +[ + AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + gl_CHECK_NEXT_HEADERS([string.h]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use, and which is not + dnl guaranteed by C89. + gl_WARN_ON_USE_PREPARE([[#include + ]], + [memmem mempcpy memrchr rawmemchr stpcpy stpncpy strchrnul strdup + strncat strndup strnlen strpbrk strsep strcasestr strtok_r strsignal + strverscmp]) +]) + +AC_DEFUN([gl_STRING_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS], +[ + GNULIB_MEMCHR=0; AC_SUBST([GNULIB_MEMCHR]) + GNULIB_MEMMEM=0; AC_SUBST([GNULIB_MEMMEM]) + GNULIB_MEMPCPY=0; AC_SUBST([GNULIB_MEMPCPY]) + GNULIB_MEMRCHR=0; AC_SUBST([GNULIB_MEMRCHR]) + GNULIB_RAWMEMCHR=0; AC_SUBST([GNULIB_RAWMEMCHR]) + GNULIB_STPCPY=0; AC_SUBST([GNULIB_STPCPY]) + GNULIB_STPNCPY=0; AC_SUBST([GNULIB_STPNCPY]) + GNULIB_STRCHRNUL=0; AC_SUBST([GNULIB_STRCHRNUL]) + GNULIB_STRDUP=0; AC_SUBST([GNULIB_STRDUP]) + GNULIB_STRNCAT=0; AC_SUBST([GNULIB_STRNCAT]) + GNULIB_STRNDUP=0; AC_SUBST([GNULIB_STRNDUP]) + GNULIB_STRNLEN=0; AC_SUBST([GNULIB_STRNLEN]) + GNULIB_STRPBRK=0; AC_SUBST([GNULIB_STRPBRK]) + GNULIB_STRSEP=0; AC_SUBST([GNULIB_STRSEP]) + GNULIB_STRSTR=0; AC_SUBST([GNULIB_STRSTR]) + GNULIB_STRCASESTR=0; AC_SUBST([GNULIB_STRCASESTR]) + GNULIB_STRTOK_R=0; AC_SUBST([GNULIB_STRTOK_R]) + GNULIB_MBSLEN=0; AC_SUBST([GNULIB_MBSLEN]) + GNULIB_MBSNLEN=0; AC_SUBST([GNULIB_MBSNLEN]) + GNULIB_MBSCHR=0; AC_SUBST([GNULIB_MBSCHR]) + GNULIB_MBSRCHR=0; AC_SUBST([GNULIB_MBSRCHR]) + GNULIB_MBSSTR=0; AC_SUBST([GNULIB_MBSSTR]) + GNULIB_MBSCASECMP=0; AC_SUBST([GNULIB_MBSCASECMP]) + GNULIB_MBSNCASECMP=0; AC_SUBST([GNULIB_MBSNCASECMP]) + GNULIB_MBSPCASECMP=0; AC_SUBST([GNULIB_MBSPCASECMP]) + GNULIB_MBSCASESTR=0; AC_SUBST([GNULIB_MBSCASESTR]) + GNULIB_MBSCSPN=0; AC_SUBST([GNULIB_MBSCSPN]) + GNULIB_MBSPBRK=0; AC_SUBST([GNULIB_MBSPBRK]) + GNULIB_MBSSPN=0; AC_SUBST([GNULIB_MBSSPN]) + GNULIB_MBSSEP=0; AC_SUBST([GNULIB_MBSSEP]) + GNULIB_MBSTOK_R=0; AC_SUBST([GNULIB_MBSTOK_R]) + GNULIB_STRERROR=0; AC_SUBST([GNULIB_STRERROR]) + GNULIB_STRSIGNAL=0; AC_SUBST([GNULIB_STRSIGNAL]) + GNULIB_STRVERSCMP=0; AC_SUBST([GNULIB_STRVERSCMP]) + HAVE_MBSLEN=0; AC_SUBST([HAVE_MBSLEN]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_MEMCHR=1; AC_SUBST([HAVE_MEMCHR]) + HAVE_DECL_MEMMEM=1; AC_SUBST([HAVE_DECL_MEMMEM]) + HAVE_MEMPCPY=1; AC_SUBST([HAVE_MEMPCPY]) + HAVE_DECL_MEMRCHR=1; AC_SUBST([HAVE_DECL_MEMRCHR]) + HAVE_RAWMEMCHR=1; AC_SUBST([HAVE_RAWMEMCHR]) + HAVE_STPCPY=1; AC_SUBST([HAVE_STPCPY]) + HAVE_STPNCPY=1; AC_SUBST([HAVE_STPNCPY]) + HAVE_STRCHRNUL=1; AC_SUBST([HAVE_STRCHRNUL]) + HAVE_DECL_STRDUP=1; AC_SUBST([HAVE_DECL_STRDUP]) + HAVE_DECL_STRNDUP=1; AC_SUBST([HAVE_DECL_STRNDUP]) + HAVE_DECL_STRNLEN=1; AC_SUBST([HAVE_DECL_STRNLEN]) + HAVE_STRPBRK=1; AC_SUBST([HAVE_STRPBRK]) + HAVE_STRSEP=1; AC_SUBST([HAVE_STRSEP]) + HAVE_STRCASESTR=1; AC_SUBST([HAVE_STRCASESTR]) + HAVE_DECL_STRTOK_R=1; AC_SUBST([HAVE_DECL_STRTOK_R]) + HAVE_DECL_STRSIGNAL=1; AC_SUBST([HAVE_DECL_STRSIGNAL]) + HAVE_STRVERSCMP=1; AC_SUBST([HAVE_STRVERSCMP]) + REPLACE_MEMCHR=0; AC_SUBST([REPLACE_MEMCHR]) + REPLACE_MEMMEM=0; AC_SUBST([REPLACE_MEMMEM]) + REPLACE_STPNCPY=0; AC_SUBST([REPLACE_STPNCPY]) + REPLACE_STRDUP=0; AC_SUBST([REPLACE_STRDUP]) + REPLACE_STRSTR=0; AC_SUBST([REPLACE_STRSTR]) + REPLACE_STRCASESTR=0; AC_SUBST([REPLACE_STRCASESTR]) + REPLACE_STRERROR=0; AC_SUBST([REPLACE_STRERROR]) + REPLACE_STRNCAT=0; AC_SUBST([REPLACE_STRNCAT]) + REPLACE_STRNDUP=0; AC_SUBST([REPLACE_STRNDUP]) + REPLACE_STRNLEN=0; AC_SUBST([REPLACE_STRNLEN]) + REPLACE_STRSIGNAL=0; AC_SUBST([REPLACE_STRSIGNAL]) + REPLACE_STRTOK_R=0; AC_SUBST([REPLACE_STRTOK_R]) + UNDEFINE_STRTOK_R=0; AC_SUBST([UNDEFINE_STRTOK_R]) +]) diff --git a/m4/strings_h.m4 b/m4/strings_h.m4 new file mode 100644 index 000000000..4374c7cbe --- /dev/null +++ b/m4/strings_h.m4 @@ -0,0 +1,39 @@ +# Configure a replacement for . +# serial 3 + +# Copyright (C) 2007, 2009-2010 Free Software Foundation, Inc. +# 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. + +AC_DEFUN([gl_HEADER_STRINGS_H], +[ + dnl Use AC_REQUIRE here, so that the default behavior below is expanded + dnl once only, before all statements that occur in other macros. + AC_REQUIRE([gl_HEADER_STRINGS_H_BODY]) +]) + +AC_DEFUN([gl_HEADER_STRINGS_H_BODY], +[ + AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS]) + gl_CHECK_NEXT_HEADERS([strings.h]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[#include + ]], [strcasecmp strncasecmp]) +]) + +AC_DEFUN([gl_STRINGS_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_HEADER_STRINGS_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) +]) + +AC_DEFUN([gl_HEADER_STRINGS_H_DEFAULTS], +[ + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_STRCASECMP=1; AC_SUBST([HAVE_STRCASECMP]) + HAVE_DECL_STRNCASECMP=1; AC_SUBST([HAVE_DECL_STRNCASECMP]) +]) diff --git a/m4/strndup.m4 b/m4/strndup.m4 new file mode 100644 index 000000000..b3567d898 --- /dev/null +++ b/m4/strndup.m4 @@ -0,0 +1,53 @@ +# strndup.m4 serial 18 +dnl Copyright (C) 2002-2003, 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRNDUP], +[ + dnl Persuade glibc to declare strndup(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_CHECK_DECLS_ONCE([strndup]) + AC_CHECK_FUNCS_ONCE([strndup]) + if test $ac_cv_have_decl_strndup = no; then + HAVE_DECL_STRNDUP=0 + fi + + if test $ac_cv_func_strndup = yes; then + # AIX 4.3.3, AIX 5.1 have a function that fails to add the terminating '\0'. + AC_CACHE_CHECK([for working strndup], [gl_cv_func_strndup_works], + [AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[#include + #include ]], [[ +#ifndef HAVE_DECL_STRNDUP + extern char *strndup (const char *, size_t); +#endif + char *s; + s = strndup ("some longer string", 15); + free (s); + s = strndup ("shorter string", 13); + return s[13] != '\0';]])], + [gl_cv_func_strndup_works=yes], + [gl_cv_func_strndup_works=no], + [ +changequote(,)dnl + case $host_os in + aix | aix[3-6]*) gl_cv_func_strndup_works="guessing no";; + *) gl_cv_func_strndup_works="guessing yes";; + esac +changequote([,])dnl + ])]) + case $gl_cv_func_strndup_works in + *no) + REPLACE_STRNDUP=1 + AC_LIBOBJ([strndup]) + ;; + esac + else + AC_LIBOBJ([strndup]) + fi +]) diff --git a/m4/strnlen.m4 b/m4/strnlen.m4 new file mode 100644 index 000000000..52bb838f9 --- /dev/null +++ b/m4/strnlen.m4 @@ -0,0 +1,32 @@ +# strnlen.m4 serial 12 +dnl Copyright (C) 2002-2003, 2005-2007, 2009-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRNLEN], +[ + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + + dnl Persuade glibc to declare strnlen(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_DECLS_ONCE([strnlen]) + if test $ac_cv_have_decl_strnlen = no; then + HAVE_DECL_STRNLEN=0 + else + AC_FUNC_STRNLEN + dnl Note: AC_FUNC_STRNLEN does AC_LIBOBJ([strnlen]). + if test $ac_cv_func_strnlen_working = no; then + REPLACE_STRNLEN=1 + fi + fi + if test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1; then + AC_LIBOBJ([strnlen]) + gl_PREREQ_STRNLEN + fi +]) + +# Prerequisites of lib/strnlen.c. +AC_DEFUN([gl_PREREQ_STRNLEN], [:]) diff --git a/m4/sys_wait_h.m4 b/m4/sys_wait_h.m4 new file mode 100644 index 000000000..b0d23fac7 --- /dev/null +++ b/m4/sys_wait_h.m4 @@ -0,0 +1,25 @@ +# sys_wait_h.m4 serial 4 +dnl Copyright (C) 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_SYS_WAIT_H], +[ + AC_REQUIRE([gl_SYS_WAIT_H_DEFAULTS]) + + dnl is always overridden, because of GNULIB_POSIXCHECK. + gl_CHECK_NEXT_HEADERS([sys/wait.h]) +]) + +AC_DEFUN([gl_SYS_WAIT_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_SYS_WAIT_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) +]) + +AC_DEFUN([gl_SYS_WAIT_H_DEFAULTS], +[ + dnl Assume proper GNU behavior unless another module says otherwise. +]) diff --git a/m4/sysexits.m4 b/m4/sysexits.m4 new file mode 100644 index 000000000..b3baa51ca --- /dev/null +++ b/m4/sysexits.m4 @@ -0,0 +1,43 @@ +# sysexits.m4 serial 5 +dnl Copyright (C) 2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_SYSEXITS], +[ + AC_CHECK_HEADERS_ONCE([sysexits.h]) + if test $ac_cv_header_sysexits_h = yes; then + HAVE_SYSEXITS_H=1 + gl_CHECK_NEXT_HEADERS([sysexits.h]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[switch (0) + { + case EX_OK: + case EX_USAGE: + case EX_DATAERR: + case EX_NOINPUT: + case EX_NOUSER: + case EX_NOHOST: + case EX_UNAVAILABLE: + case EX_SOFTWARE: + case EX_OSERR: + case EX_OSFILE: + case EX_CANTCREAT: + case EX_IOERR: + case EX_TEMPFAIL: + case EX_PROTOCOL: + case EX_NOPERM: + case EX_CONFIG: + break; + } + ]])], + [SYSEXITS_H=], + [SYSEXITS_H=sysexits.h]) + else + HAVE_SYSEXITS_H=0 + SYSEXITS_H=sysexits.h + fi + AC_SUBST([HAVE_SYSEXITS_H]) + AC_SUBST([SYSEXITS_H]) +]) diff --git a/m4/threadlib.m4 b/m4/threadlib.m4 new file mode 100644 index 000000000..bff01bc5e --- /dev/null +++ b/m4/threadlib.m4 @@ -0,0 +1,362 @@ +# threadlib.m4 serial 6 (gettext-0.18.2) +dnl Copyright (C) 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl gl_THREADLIB +dnl ------------ +dnl Tests for a multithreading library to be used. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WIN32_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_THREADLIB_EARLY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) +]) + +dnl The guts of gl_THREADLIB_EARLY. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_EARLY_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + dnl Check for multithreading. + m4_divert_text([DEFAULTS], [gl_use_threads_default=]) + AC_ARG_ENABLE([threads], +AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) +AC_HELP_STRING([--disable-threads], [build without multithread safety]), + [gl_use_threads=$enableval], + [if test -n "$gl_use_threads_default"; then + gl_use_threads="$gl_use_threads_default" + else +changequote(,)dnl + case "$host_os" in + dnl Disable multithreading by default on OSF/1, because it interferes + dnl with fork()/exec(): When msgexec is linked with -lpthread, its + dnl child process gets an endless segmentation fault inside execvp(). + dnl Disable multithreading by default on Cygwin 1.5.x, because it has + dnl bugs that lead to endless loops or crashes. See + dnl . + osf*) gl_use_threads=no ;; + cygwin*) + case `uname -r` in + 1.[0-5].*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ;; + *) gl_use_threads=yes ;; + esac +changequote([,])dnl + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using : + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_LINK_IFELSE test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi +]) + +dnl The guts of gl_THREADLIB. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_BODY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_CACHE_CHECK([whether imported symbols can be declared weak], + [gl_cv_have_weak], + [gl_cv_have_weak=no + dnl First, test whether the compiler accepts it syntactically. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[extern void xyzzy (); +#pragma weak xyzzy]], + [[xyzzy();]])], + [gl_cv_have_weak=maybe]) + if test $gl_cv_have_weak = maybe; then + dnl Second, test whether it actually works. On Cygwin 1.7.2, with + dnl gcc 4.3, symbols declared weak always evaluate to the address 0. + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#pragma weak fputs +int main () +{ + return (fputs == NULL); +}]])], + [gl_cv_have_weak=yes], + [gl_cv_have_weak=no], + [dnl When cross-compiling, assume that only ELF platforms support + dnl weak symbols. + AC_EGREP_CPP([Extensible Linking Format], + [#ifdef __ELF__ + Extensible Linking Format + #endif + ], + [gl_cv_have_weak="guessing yes"], + [gl_cv_have_weak="guessing no"]) + ]) + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . It's added above, in gl_THREADLIB_EARLY_BODY. + AC_CHECK_HEADER([pthread.h], + [gl_have_pthread_h=yes], [gl_have_pthread_h=no]) + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);]])], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB([pthread], [pthread_kill], + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1], + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB([pthread], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB([c_r], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], [1], + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], [1], + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[thr_self();]])], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], [1], + [Define if the old Solaris multithreading library can be used.]) + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], [1], + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS([pth]) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include ]], [[pth_self();]])], + [gl_have_pth=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], [1], + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_PTH_THREADS_WEAK], [1], + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + AC_DEFINE([USE_WIN32_THREADS], [1], + [Define if the Win32 multithreading API can be used.]) + fi + fi + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST([LIBTHREAD]) + AC_SUBST([LTLIBTHREAD]) + AC_SUBST([LIBMULTITHREAD]) + AC_SUBST([LTLIBMULTITHREAD]) +]) + +AC_DEFUN([gl_THREADLIB], +[ + AC_REQUIRE([gl_THREADLIB_EARLY]) + AC_REQUIRE([gl_THREADLIB_BODY]) +]) + + +dnl gl_DISABLE_THREADS +dnl ------------------ +dnl Sets the gl_THREADLIB default so that threads are not used by default. +dnl The user can still override it at installation time, by using the +dnl configure option '--enable-threads'. + +AC_DEFUN([gl_DISABLE_THREADS], [ + m4_divert_text([INIT_PREPARE], [gl_use_threads_default=no]) +]) + + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl MacOS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw win32 N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4 new file mode 100644 index 000000000..03b51bcfe --- /dev/null +++ b/m4/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 12 +dnl Copyright (C) 1997-2004, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ([2.13]) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type], + [Define to unsigned long or unsigned long long + if and don't define.]) + else + AC_DEFINE([HAVE_UINTMAX_T], [1], + [Define if you have the 'uintmax_t' type in or .]) + fi +]) diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4 new file mode 100644 index 000000000..48d06c742 --- /dev/null +++ b/m4/unistd_h.m4 @@ -0,0 +1,159 @@ +# unistd_h.m4 serial 46 +dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Simon Josefsson, Bruno Haible. + +AC_DEFUN([gl_UNISTD_H], +[ + dnl Use AC_REQUIRE here, so that the default behavior below is expanded + dnl once only, before all statements that occur in other macros. + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + AC_REQUIRE([AC_C_INLINE]) + + gl_CHECK_NEXT_HEADERS([unistd.h]) + + AC_CHECK_HEADERS_ONCE([unistd.h]) + if test $ac_cv_header_unistd_h = yes; then + HAVE_UNISTD_H=1 + else + HAVE_UNISTD_H=0 + fi + AC_SUBST([HAVE_UNISTD_H]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[#include +/* Some systems declare various items in the wrong headers. */ +#ifndef __GLIBC__ +# include +# include +# include +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# include +# endif +#endif + ]], [chown dup2 dup3 environ euidaccess faccessat fchdir fchownat + fsync ftruncate getcwd getdomainname getdtablesize getgroups + gethostname getlogin getlogin_r getpagesize getusershell setusershell + endusershell lchown link linkat lseek pipe2 pread pwrite readlink + readlinkat rmdir sleep symlink symlinkat ttyname_r unlink unlinkat + usleep]) +]) + +AC_DEFUN([gl_UNISTD_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_UNISTD_H_DEFAULTS], +[ + GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN]) + GNULIB_CLOSE=0; AC_SUBST([GNULIB_CLOSE]) + GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2]) + GNULIB_DUP3=0; AC_SUBST([GNULIB_DUP3]) + GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON]) + GNULIB_EUIDACCESS=0; AC_SUBST([GNULIB_EUIDACCESS]) + GNULIB_FACCESSAT=0; AC_SUBST([GNULIB_FACCESSAT]) + GNULIB_FCHDIR=0; AC_SUBST([GNULIB_FCHDIR]) + GNULIB_FCHOWNAT=0; AC_SUBST([GNULIB_FCHOWNAT]) + GNULIB_FSYNC=0; AC_SUBST([GNULIB_FSYNC]) + GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE]) + GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD]) + GNULIB_GETDOMAINNAME=0; AC_SUBST([GNULIB_GETDOMAINNAME]) + GNULIB_GETDTABLESIZE=0; AC_SUBST([GNULIB_GETDTABLESIZE]) + GNULIB_GETGROUPS=0; AC_SUBST([GNULIB_GETGROUPS]) + GNULIB_GETHOSTNAME=0; AC_SUBST([GNULIB_GETHOSTNAME]) + GNULIB_GETLOGIN=0; AC_SUBST([GNULIB_GETLOGIN]) + GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R]) + GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE]) + GNULIB_GETUSERSHELL=0; AC_SUBST([GNULIB_GETUSERSHELL]) + GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) + GNULIB_LINK=0; AC_SUBST([GNULIB_LINK]) + GNULIB_LINKAT=0; AC_SUBST([GNULIB_LINKAT]) + GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) + GNULIB_PIPE2=0; AC_SUBST([GNULIB_PIPE2]) + GNULIB_PREAD=0; AC_SUBST([GNULIB_PREAD]) + GNULIB_PWRITE=0; AC_SUBST([GNULIB_PWRITE]) + GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) + GNULIB_READLINKAT=0; AC_SUBST([GNULIB_READLINKAT]) + GNULIB_RMDIR=0; AC_SUBST([GNULIB_RMDIR]) + GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP]) + GNULIB_SYMLINK=0; AC_SUBST([GNULIB_SYMLINK]) + GNULIB_SYMLINKAT=0; AC_SUBST([GNULIB_SYMLINKAT]) + GNULIB_TTYNAME_R=0; AC_SUBST([GNULIB_TTYNAME_R]) + GNULIB_UNISTD_H_GETOPT=0; AC_SUBST([GNULIB_UNISTD_H_GETOPT]) + GNULIB_UNISTD_H_SIGPIPE=0; AC_SUBST([GNULIB_UNISTD_H_SIGPIPE]) + GNULIB_UNLINK=0; AC_SUBST([GNULIB_UNLINK]) + GNULIB_UNLINKAT=0; AC_SUBST([GNULIB_UNLINKAT]) + GNULIB_USLEEP=0; AC_SUBST([GNULIB_USLEEP]) + GNULIB_WRITE=0; AC_SUBST([GNULIB_WRITE]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_CHOWN=1; AC_SUBST([HAVE_CHOWN]) + HAVE_DUP2=1; AC_SUBST([HAVE_DUP2]) + HAVE_DUP3=1; AC_SUBST([HAVE_DUP3]) + HAVE_EUIDACCESS=1; AC_SUBST([HAVE_EUIDACCESS]) + HAVE_FACCESSAT=1; AC_SUBST([HAVE_FACCESSAT]) + HAVE_FCHDIR=1; AC_SUBST([HAVE_FCHDIR]) + HAVE_FCHOWNAT=1; AC_SUBST([HAVE_FCHOWNAT]) + HAVE_FSYNC=1; AC_SUBST([HAVE_FSYNC]) + HAVE_FTRUNCATE=1; AC_SUBST([HAVE_FTRUNCATE]) + HAVE_GETDOMAINNAME=1; AC_SUBST([HAVE_GETDOMAINNAME]) + HAVE_GETDTABLESIZE=1; AC_SUBST([HAVE_GETDTABLESIZE]) + HAVE_GETGROUPS=1; AC_SUBST([HAVE_GETGROUPS]) + HAVE_GETHOSTNAME=1; AC_SUBST([HAVE_GETHOSTNAME]) + HAVE_GETLOGIN=1; AC_SUBST([HAVE_GETLOGIN]) + HAVE_GETPAGESIZE=1; AC_SUBST([HAVE_GETPAGESIZE]) + HAVE_LCHOWN=1; AC_SUBST([HAVE_LCHOWN]) + HAVE_LINK=1; AC_SUBST([HAVE_LINK]) + HAVE_LINKAT=1; AC_SUBST([HAVE_LINKAT]) + HAVE_PIPE2=1; AC_SUBST([HAVE_PIPE2]) + HAVE_PREAD=1; AC_SUBST([HAVE_PREAD]) + HAVE_PWRITE=1; AC_SUBST([HAVE_PWRITE]) + HAVE_READLINK=1; AC_SUBST([HAVE_READLINK]) + HAVE_READLINKAT=1; AC_SUBST([HAVE_READLINKAT]) + HAVE_SLEEP=1; AC_SUBST([HAVE_SLEEP]) + HAVE_SYMLINK=1; AC_SUBST([HAVE_SYMLINK]) + HAVE_SYMLINKAT=1; AC_SUBST([HAVE_SYMLINKAT]) + HAVE_TTYNAME_R=1; AC_SUBST([HAVE_TTYNAME_R]) + HAVE_UNLINKAT=1; AC_SUBST([HAVE_UNLINKAT]) + HAVE_USLEEP=1; AC_SUBST([HAVE_USLEEP]) + HAVE_DECL_ENVIRON=1; AC_SUBST([HAVE_DECL_ENVIRON]) + HAVE_DECL_GETLOGIN_R=1; AC_SUBST([HAVE_DECL_GETLOGIN_R]) + HAVE_DECL_GETPAGESIZE=1; AC_SUBST([HAVE_DECL_GETPAGESIZE]) + HAVE_DECL_GETUSERSHELL=1; AC_SUBST([HAVE_DECL_GETUSERSHELL]) + HAVE_OS_H=0; AC_SUBST([HAVE_OS_H]) + HAVE_SYS_PARAM_H=0; AC_SUBST([HAVE_SYS_PARAM_H]) + REPLACE_CHOWN=0; AC_SUBST([REPLACE_CHOWN]) + REPLACE_CLOSE=0; AC_SUBST([REPLACE_CLOSE]) + REPLACE_DUP=0; AC_SUBST([REPLACE_DUP]) + REPLACE_DUP2=0; AC_SUBST([REPLACE_DUP2]) + REPLACE_FCHOWNAT=0; AC_SUBST([REPLACE_FCHOWNAT]) + REPLACE_GETCWD=0; AC_SUBST([REPLACE_GETCWD]) + REPLACE_GETGROUPS=0; AC_SUBST([REPLACE_GETGROUPS]) + REPLACE_GETPAGESIZE=0; AC_SUBST([REPLACE_GETPAGESIZE]) + REPLACE_LCHOWN=0; AC_SUBST([REPLACE_LCHOWN]) + REPLACE_LINK=0; AC_SUBST([REPLACE_LINK]) + REPLACE_LINKAT=0; AC_SUBST([REPLACE_LINKAT]) + REPLACE_LSEEK=0; AC_SUBST([REPLACE_LSEEK]) + REPLACE_PREAD=0; AC_SUBST([REPLACE_PREAD]) + REPLACE_PWRITE=0; AC_SUBST([REPLACE_PWRITE]) + REPLACE_READLINK=0; AC_SUBST([REPLACE_READLINK]) + REPLACE_RMDIR=0; AC_SUBST([REPLACE_RMDIR]) + REPLACE_SLEEP=0; AC_SUBST([REPLACE_SLEEP]) + REPLACE_SYMLINK=0; AC_SUBST([REPLACE_SYMLINK]) + REPLACE_TTYNAME_R=0; AC_SUBST([REPLACE_TTYNAME_R]) + REPLACE_UNLINK=0; AC_SUBST([REPLACE_UNLINK]) + REPLACE_UNLINKAT=0; AC_SUBST([REPLACE_UNLINKAT]) + REPLACE_USLEEP=0; AC_SUBST([REPLACE_USLEEP]) + REPLACE_WRITE=0; AC_SUBST([REPLACE_WRITE]) + UNISTD_H_HAVE_WINSOCK2_H=0; AC_SUBST([UNISTD_H_HAVE_WINSOCK2_H]) + UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS=0; + AC_SUBST([UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS]) +]) diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4 new file mode 100644 index 000000000..ebe3c52cd --- /dev/null +++ b/m4/vasnprintf.m4 @@ -0,0 +1,288 @@ +# vasnprintf.m4 serial 31 +dnl Copyright (C) 2002-2004, 2006-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_VASNPRINTF], +[ + AC_CHECK_FUNCS_ONCE([vasnprintf]) + if test $ac_cv_func_vasnprintf = no; then + gl_REPLACE_VASNPRINTF + fi +]) + +AC_DEFUN([gl_REPLACE_VASNPRINTF], +[ + AC_CHECK_FUNCS_ONCE([vasnprintf]) + AC_LIBOBJ([vasnprintf]) + AC_LIBOBJ([printf-args]) + AC_LIBOBJ([printf-parse]) + AC_LIBOBJ([asnprintf]) + if test $ac_cv_func_vasnprintf = yes; then + AC_DEFINE([REPLACE_VASNPRINTF], [1], + [Define if vasnprintf exists but is overridden by gnulib.]) + fi + gl_PREREQ_PRINTF_ARGS + gl_PREREQ_PRINTF_PARSE + gl_PREREQ_VASNPRINTF + gl_PREREQ_ASNPRINTF +]) + +# Prequisites of lib/printf-args.h, lib/printf-args.c. +AC_DEFUN([gl_PREREQ_PRINTF_ARGS], +[ + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + AC_REQUIRE([gt_TYPE_WINT_T]) +]) + +# Prequisites of lib/printf-parse.h, lib/printf-parse.c. +AC_DEFUN([gl_PREREQ_PRINTF_PARSE], +[ + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + AC_REQUIRE([gt_TYPE_WINT_T]) + AC_REQUIRE([AC_TYPE_SIZE_T]) + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_REQUIRE([gt_AC_TYPE_INTMAX_T]) +]) + +# Prerequisites of lib/vasnprintf.c. +AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF], +[ + AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([AC_FUNC_ALLOCA]) + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + AC_REQUIRE([gt_TYPE_WINT_T]) + AC_CHECK_FUNCS([snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + AC_CHECK_DECLS([_snprintf], , , [#include ]) + dnl We can avoid a lot of code by assuming that snprintf's return value + dnl conforms to ISO C99. So check that. + AC_REQUIRE([gl_SNPRINTF_RETVAL_C99]) + case "$gl_cv_func_snprintf_retval_c99" in + *yes) + AC_DEFINE([HAVE_SNPRINTF_RETVAL_C99], [1], + [Define if the return value of the snprintf function is the number of + of bytes (excluding the terminating NUL) that would have been produced + if the buffer had been large enough.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting 'long double' +# arguments. +AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF_LONG_DOUBLE], +[ + AC_REQUIRE([gl_PRINTF_LONG_DOUBLE]) + case "$gl_cv_func_printf_long_double" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + 'long double' arguments.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting infinite 'double' +# arguments. +AC_DEFUN([gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE], +[ + AC_REQUIRE([gl_PRINTF_INFINITE]) + case "$gl_cv_func_printf_infinite" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_INFINITE_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + infinite 'double' arguments.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting infinite 'long double' +# arguments. +AC_DEFUN([gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE], +[ + AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE]) + dnl There is no need to set NEED_PRINTF_INFINITE_LONG_DOUBLE if + dnl NEED_PRINTF_LONG_DOUBLE is already set. + AC_REQUIRE([gl_PREREQ_VASNPRINTF_LONG_DOUBLE]) + case "$gl_cv_func_printf_long_double" in + *yes) + case "$gl_cv_func_printf_infinite_long_double" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_INFINITE_LONG_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + infinite 'long double' arguments.]) + ;; + esac + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting the 'a' directive. +AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_A], +[ + AC_REQUIRE([gl_PRINTF_DIRECTIVE_A]) + case "$gl_cv_func_printf_directive_a" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_DIRECTIVE_A], [1], + [Define if the vasnprintf implementation needs special code for + the 'a' and 'A' directives.]) + AC_CHECK_FUNCS([nl_langinfo]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting the 'F' directive. +AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_F], +[ + AC_REQUIRE([gl_PRINTF_DIRECTIVE_F]) + case "$gl_cv_func_printf_directive_f" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_DIRECTIVE_F], [1], + [Define if the vasnprintf implementation needs special code for + the 'F' directive.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting the 'ls' directive. +AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LS], +[ + AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS]) + case "$gl_cv_func_printf_directive_ls" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_DIRECTIVE_LS], [1], + [Define if the vasnprintf implementation needs special code for + the 'ls' directive.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting the ' flag. +AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING], +[ + AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + case "$gl_cv_func_printf_flag_grouping" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_FLAG_GROUPING], [1], + [Define if the vasnprintf implementation needs special code for the + ' flag.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting the '-' flag. +AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST], +[ + AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST]) + case "$gl_cv_func_printf_flag_leftadjust" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_FLAG_LEFTADJUST], [1], + [Define if the vasnprintf implementation needs special code for the + '-' flag.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting the 0 flag. +AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO], +[ + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) + case "$gl_cv_func_printf_flag_zero" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_FLAG_ZERO], [1], + [Define if the vasnprintf implementation needs special code for the + 0 flag.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for supporting large precisions. +AC_DEFUN([gl_PREREQ_VASNPRINTF_PRECISION], +[ + AC_REQUIRE([gl_PRINTF_PRECISION]) + case "$gl_cv_func_printf_precision" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_UNBOUNDED_PRECISION], [1], + [Define if the vasnprintf implementation needs special code for + supporting large precisions without arbitrary bounds.]) + AC_DEFINE([NEED_PRINTF_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + 'double' arguments.]) + AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + 'long double' arguments.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for surviving out-of-memory +# conditions. +AC_DEFUN([gl_PREREQ_VASNPRINTF_ENOMEM], +[ + AC_REQUIRE([gl_PRINTF_ENOMEM]) + case "$gl_cv_func_printf_enomem" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_ENOMEM], [1], + [Define if the vasnprintf implementation needs special code for + surviving out-of-memory conditions.]) + AC_DEFINE([NEED_PRINTF_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + 'double' arguments.]) + AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], [1], + [Define if the vasnprintf implementation needs special code for + 'long double' arguments.]) + ;; + esac +]) + +# Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance. +AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS], +[ + AC_REQUIRE([gl_PREREQ_VASNPRINTF]) + gl_PREREQ_VASNPRINTF_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_DIRECTIVE_A + gl_PREREQ_VASNPRINTF_DIRECTIVE_F + gl_PREREQ_VASNPRINTF_DIRECTIVE_LS + gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST + gl_PREREQ_VASNPRINTF_FLAG_ZERO + gl_PREREQ_VASNPRINTF_PRECISION + gl_PREREQ_VASNPRINTF_ENOMEM +]) + +# Prerequisites of lib/asnprintf.c. +AC_DEFUN([gl_PREREQ_ASNPRINTF], +[ +]) diff --git a/m4/visibility.m4 b/m4/visibility.m4 new file mode 100644 index 000000000..19cd8f3d3 --- /dev/null +++ b/m4/visibility.m4 @@ -0,0 +1,77 @@ +# visibility.m4 serial 4 (gettext-0.18.2) +dnl Copyright (C) 2005, 2008, 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl MacOS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + dnl First, check whether -Werror can be added to the command line, or + dnl whether it leads to an error because of some other option that the + dnl user has put into $CC $CFLAGS $CPPFLAGS. + AC_MSG_CHECKING([whether the -Werror option is usable]) + AC_CACHE_VAL([gl_cv_cc_vis_werror], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [gl_cv_cc_vis_werror=yes], + [gl_cv_cc_vis_werror=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_vis_werror]) + dnl Now check whether visibility declarations are supported. + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL([gl_cv_cc_visibility], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + dnl We use the option -Werror and a function dummyfunc, because on some + dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning + dnl "visibility attribute not supported in this configuration; ignored" + dnl at the first function definition in every compilation unit, and we + dnl don't want to use the option in this case. + if test $gl_cv_cc_vis_werror = yes; then + CFLAGS="$CFLAGS -Werror" + fi + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void); + void dummyfunc (void) {} + ]], + [[]])], + [gl_cv_cc_visibility=yes], + [gl_cv_cc_visibility=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) diff --git a/m4/vsnprintf.m4 b/m4/vsnprintf.m4 new file mode 100644 index 000000000..ed189c238 --- /dev/null +++ b/m4/vsnprintf.m4 @@ -0,0 +1,40 @@ +# vsnprintf.m4 serial 5 +dnl Copyright (C) 2002-2004, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_VSNPRINTF], +[ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + gl_cv_func_vsnprintf_usable=no + AC_CHECK_FUNCS([vsnprintf]) + if test $ac_cv_func_vsnprintf = yes; then + gl_SNPRINTF_SIZE1 + case "$gl_cv_func_snprintf_size1" in + *yes) + gl_cv_func_vsnprintf_usable=yes + ;; + esac + fi + if test $gl_cv_func_vsnprintf_usable = no; then + gl_REPLACE_VSNPRINTF + fi + AC_CHECK_DECLS_ONCE([vsnprintf]) + if test $ac_cv_have_decl_vsnprintf = no; then + HAVE_DECL_VSNPRINTF=0 + fi +]) + +AC_DEFUN([gl_REPLACE_VSNPRINTF], +[ + AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + AC_LIBOBJ([vsnprintf]) + if test $ac_cv_func_vsnprintf = yes; then + REPLACE_VSNPRINTF=1 + fi + gl_PREREQ_VSNPRINTF +]) + +# Prerequisites of lib/vsnprintf.c. +AC_DEFUN([gl_PREREQ_VSNPRINTF], [:]) diff --git a/m4/warn-on-use.m4 b/m4/warn-on-use.m4 new file mode 100644 index 000000000..42daae87b --- /dev/null +++ b/m4/warn-on-use.m4 @@ -0,0 +1,45 @@ +# warn-on-use.m4 serial 2 +dnl Copyright (C) 2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# gl_WARN_ON_USE_PREPARE(INCLUDES, NAMES) +# --------------------------------------- +# For each whitespace-separated element in the list of NAMES, define +# HAVE_RAW_DECL_name if the function has a declaration among INCLUDES +# even after being undefined as a macro. +# +# See warn-on-use.h for some hints on how to poison function names, as +# well as ideas on poisoning global variables and macros. NAMES may +# include global variables, but remember that only functions work with +# _GL_WARN_ON_USE. Typically, INCLUDES only needs to list a single +# header, but if the replacement header pulls in other headers because +# some systems declare functions in the wrong header, then INCLUDES +# should do likewise. +# +# If you assume C89, then it is generally safe to assume declarations +# for functions declared in that standard (such as gets) without +# needing gl_WARN_ON_USE_PREPARE. +AC_DEFUN([gl_WARN_ON_USE_PREPARE], +[ + m4_foreach_w([gl_decl], [$2], + [AH_TEMPLATE([HAVE_RAW_DECL_]AS_TR_CPP(m4_defn([gl_decl])), + [Define to 1 if ]m4_defn([gl_decl])[ is declared even after + undefining macros.])])dnl + for gl_func in m4_flatten([$2]); do + AS_VAR_PUSHDEF([gl_Symbol], [gl_cv_have_raw_decl_$gl_func])dnl + AC_CACHE_CHECK([whether $gl_func is declared without a macro], + gl_Symbol, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$1], +[@%:@undef $gl_func + (void) $gl_func;])], + [AS_VAR_SET(gl_Symbol, [yes])], [AS_VAR_SET(gl_Symbol, [no])])]) + AS_VAR_IF(gl_Symbol, [yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_RAW_DECL_$gl_func]), [1]) + dnl shortcut - if the raw declaration exists, then set a cache + dnl variable to allow skipping any later AC_CHECK_DECL efforts + eval ac_cv_have_decl_$gl_func=yes]) + AS_VAR_POPDEF([gl_Symbol])dnl + done +]) diff --git a/m4/wchar_h.m4 b/m4/wchar_h.m4 new file mode 100644 index 000000000..8cae82dd0 --- /dev/null +++ b/m4/wchar_h.m4 @@ -0,0 +1,152 @@ +dnl A placeholder for ISO C99 , for platforms that have issues. + +dnl Copyright (C) 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Eric Blake. + +# wchar_h.m4 serial 33 + +AC_DEFUN([gl_WCHAR_H], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + AC_REQUIRE([gl_WCHAR_H_INLINE_OK]) + dnl Prepare for creating substitute . + dnl Check for (missing in Linux uClibc when built without wide + dnl character support). + dnl is always overridden, because of GNULIB_POSIXCHECK. + AC_CHECK_HEADERS_ONCE([wchar.h]) + gl_CHECK_NEXT_HEADERS([wchar.h]) + if test $ac_cv_header_wchar_h = yes; then + HAVE_WCHAR_H=1 + else + HAVE_WCHAR_H=0 + fi + AC_SUBST([HAVE_WCHAR_H]) + + AC_REQUIRE([gt_TYPE_WINT_T]) + if test $gt_cv_c_wint_t = yes; then + HAVE_WINT_T=1 + else + HAVE_WINT_T=0 + fi + AC_SUBST([HAVE_WINT_T]) + + dnl Check for declarations of anything we want to poison if the + dnl corresponding gnulib module is not in use. + gl_WARN_ON_USE_PREPARE([[ +/* Some systems require additional headers. */ +#ifndef __GLIBC__ +# include +# include +# include +#endif +#include + ]], [btowc wctob mbsinit mbrtowc mbrlen mbsrtowcs mbsnrtowcs wcrtomb + wcsrtombs wcsnrtombs wcwidth]) +]) + +dnl Check whether is usable at all. +AC_DEFUN([gl_WCHAR_H_INLINE_OK], +[ + dnl Test whether suffers due to the transition from '__inline' to + dnl 'gnu_inline'. See + dnl and . In summary, + dnl glibc version 2.5 or older, together with gcc version 4.3 or newer and + dnl the option -std=c99 or -std=gnu99, leads to a broken . + AC_CACHE_CHECK([whether uses 'inline' correctly], + [gl_cv_header_wchar_h_correct_inline], + [gl_cv_header_wchar_h_correct_inline=yes + AC_LANG_CONFTEST([ + AC_LANG_SOURCE([[#define wcstod renamed_wcstod +#include +extern int zero (void); +int main () { return zero(); } +]])]) + if AC_TRY_EVAL([ac_compile]); then + mv conftest.$ac_objext conftest1.$ac_objext + AC_LANG_CONFTEST([ + AC_LANG_SOURCE([[#define wcstod renamed_wcstod +#include +int zero (void) { return 0; } +]])]) + if AC_TRY_EVAL([ac_compile]); then + mv conftest.$ac_objext conftest2.$ac_objext + if $CC -o conftest$ac_exeext $CFLAGS $LDFLAGS conftest1.$ac_objext conftest2.$ac_objext $LIBS >&AS_MESSAGE_LOG_FD 2>&1; then + : + else + gl_cv_header_wchar_h_correct_inline=no + fi + fi + fi + rm -f conftest1.$ac_objext conftest2.$ac_objext conftest$ac_exeext + ]) + if test $gl_cv_header_wchar_h_correct_inline = no; then + AC_MSG_ERROR([ cannot be used with this compiler ($CC $CFLAGS $CPPFLAGS). +This is a known interoperability problem of glibc <= 2.5 with gcc >= 4.3 in +C99 mode. You have four options: + - Add the flag -fgnu89-inline to CC and reconfigure, or + - Fix your include files, using parts of + , or + - Use a gcc version older than 4.3, or + - Don't use the flags -std=c99 or -std=gnu99. +Configuration aborted.]) + fi +]) + +dnl Unconditionally enables the replacement of . +AC_DEFUN([gl_REPLACE_WCHAR_H], +[ + dnl This is a no-op, because is always overridden. + : +]) + +AC_DEFUN([gl_WCHAR_MODULE_INDICATOR], +[ + dnl Use AC_REQUIRE here, so that the default settings are expanded once only. + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + gl_MODULE_INDICATOR_SET_VARIABLE([$1]) + dnl Define it also as a C macro, for the benefit of the unit tests. + gl_MODULE_INDICATOR_FOR_TESTS([$1]) +]) + +AC_DEFUN([gl_WCHAR_H_DEFAULTS], +[ + GNULIB_BTOWC=0; AC_SUBST([GNULIB_BTOWC]) + GNULIB_WCTOB=0; AC_SUBST([GNULIB_WCTOB]) + GNULIB_MBSINIT=0; AC_SUBST([GNULIB_MBSINIT]) + GNULIB_MBRTOWC=0; AC_SUBST([GNULIB_MBRTOWC]) + GNULIB_MBRLEN=0; AC_SUBST([GNULIB_MBRLEN]) + GNULIB_MBSRTOWCS=0; AC_SUBST([GNULIB_MBSRTOWCS]) + GNULIB_MBSNRTOWCS=0; AC_SUBST([GNULIB_MBSNRTOWCS]) + GNULIB_WCRTOMB=0; AC_SUBST([GNULIB_WCRTOMB]) + GNULIB_WCSRTOMBS=0; AC_SUBST([GNULIB_WCSRTOMBS]) + GNULIB_WCSNRTOMBS=0; AC_SUBST([GNULIB_WCSNRTOMBS]) + GNULIB_WCWIDTH=0; AC_SUBST([GNULIB_WCWIDTH]) + dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_BTOWC=1; AC_SUBST([HAVE_BTOWC]) + HAVE_MBSINIT=1; AC_SUBST([HAVE_MBSINIT]) + HAVE_MBRTOWC=1; AC_SUBST([HAVE_MBRTOWC]) + HAVE_MBRLEN=1; AC_SUBST([HAVE_MBRLEN]) + HAVE_MBSRTOWCS=1; AC_SUBST([HAVE_MBSRTOWCS]) + HAVE_MBSNRTOWCS=1; AC_SUBST([HAVE_MBSNRTOWCS]) + HAVE_WCRTOMB=1; AC_SUBST([HAVE_WCRTOMB]) + HAVE_WCSRTOMBS=1; AC_SUBST([HAVE_WCSRTOMBS]) + HAVE_WCSNRTOMBS=1; AC_SUBST([HAVE_WCSNRTOMBS]) + HAVE_DECL_WCTOB=1; AC_SUBST([HAVE_DECL_WCTOB]) + HAVE_DECL_WCWIDTH=1; AC_SUBST([HAVE_DECL_WCWIDTH]) + REPLACE_MBSTATE_T=0; AC_SUBST([REPLACE_MBSTATE_T]) + REPLACE_BTOWC=0; AC_SUBST([REPLACE_BTOWC]) + REPLACE_WCTOB=0; AC_SUBST([REPLACE_WCTOB]) + REPLACE_MBSINIT=0; AC_SUBST([REPLACE_MBSINIT]) + REPLACE_MBRTOWC=0; AC_SUBST([REPLACE_MBRTOWC]) + REPLACE_MBRLEN=0; AC_SUBST([REPLACE_MBRLEN]) + REPLACE_MBSRTOWCS=0; AC_SUBST([REPLACE_MBSRTOWCS]) + REPLACE_MBSNRTOWCS=0; AC_SUBST([REPLACE_MBSNRTOWCS]) + REPLACE_WCRTOMB=0; AC_SUBST([REPLACE_WCRTOMB]) + REPLACE_WCSRTOMBS=0; AC_SUBST([REPLACE_WCSRTOMBS]) + REPLACE_WCSNRTOMBS=0; AC_SUBST([REPLACE_WCSNRTOMBS]) + REPLACE_WCWIDTH=0; AC_SUBST([REPLACE_WCWIDTH]) +]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 new file mode 100644 index 000000000..a133e6ad5 --- /dev/null +++ b/m4/wchar_t.m4 @@ -0,0 +1,24 @@ +# wchar_t.m4 serial 4 (gettext-0.18.2) +dnl Copyright (C) 2002-2003, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + wchar_t foo = (wchar_t)'\0';]], + [[]])], + [gt_cv_c_wchar_t=yes], + [gt_cv_c_wchar_t=no])]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/m4/wcrtomb.m4 b/m4/wcrtomb.m4 new file mode 100644 index 000000000..0de262e61 --- /dev/null +++ b/m4/wcrtomb.m4 @@ -0,0 +1,94 @@ +# wcrtomb.m4 serial 6 +dnl Copyright (C) 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_WCRTOMB], +[ + AC_REQUIRE([gl_WCHAR_H_DEFAULTS]) + + AC_REQUIRE([AC_TYPE_MBSTATE_T]) + gl_MBSTATE_T_BROKEN + + AC_CHECK_FUNCS_ONCE([wcrtomb]) + if test $ac_cv_func_wcrtomb = no; then + HAVE_WCRTOMB=0 + else + if test $REPLACE_MBSTATE_T = 1; then + REPLACE_WCRTOMB=1 + else + dnl On AIX 4.3, OSF/1 5.1 and Solaris 10, wcrtomb (NULL, 0, NULL) sometimes + dnl returns 0 instead of 1. + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_FR]) + AC_REQUIRE([gt_LOCALE_FR_UTF8]) + AC_REQUIRE([gt_LOCALE_JA]) + AC_REQUIRE([gt_LOCALE_ZH_CN]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether wcrtomb return value is correct], + [gl_cv_func_wcrtomb_retval], + [ + dnl Initial guess, used when cross-compiling or when no suitable locale + dnl is present. +changequote(,)dnl + case "$host_os" in + # Guess no on AIX 4, OSF/1 and Solaris. + aix4* | osf* | solaris*) gl_cv_func_wcrtomb_retval="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_wcrtomb_retval="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_FR != none || test $LOCALE_FR_UTF8 != none || test $LOCALE_JA != none || test $LOCALE_ZH_CN != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +#include +int main () +{ + if (setlocale (LC_ALL, "$LOCALE_FR") != NULL) + { + if (wcrtomb (NULL, 0, NULL) != 1) + return 1; + } + if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL) + { + if (wcrtomb (NULL, 0, NULL) != 1) + return 1; + } + if (setlocale (LC_ALL, "$LOCALE_JA") != NULL) + { + if (wcrtomb (NULL, 0, NULL) != 1) + return 1; + } + if (setlocale (LC_ALL, "$LOCALE_ZH_CN") != NULL) + { + if (wcrtomb (NULL, 0, NULL) != 1) + return 1; + } + return 0; +}]])], + [gl_cv_func_wcrtomb_retval=yes], + [gl_cv_func_wcrtomb_retval=no], + [:]) + fi + ]) + case "$gl_cv_func_wcrtomb_retval" in + *yes) ;; + *) REPLACE_WCRTOMB=1 ;; + esac + fi + fi + if test $HAVE_WCRTOMB = 0 || test $REPLACE_WCRTOMB = 1; then + gl_REPLACE_WCHAR_H + AC_LIBOBJ([wcrtomb]) + gl_PREREQ_WCRTOMB + fi +]) + +# Prerequisites of lib/wcrtomb.c. +AC_DEFUN([gl_PREREQ_WCRTOMB], [ + : +]) diff --git a/m4/wctype_h.m4 b/m4/wctype_h.m4 new file mode 100644 index 000000000..bc6b6e791 --- /dev/null +++ b/m4/wctype_h.m4 @@ -0,0 +1,85 @@ +# wctype_h.m4 serial 8 + +dnl A placeholder for ISO C99 , for platforms that lack it. + +dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Paul Eggert. + +AC_DEFUN([gl_WCTYPE_H], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CHECK_FUNCS_ONCE([iswcntrl]) + if test $ac_cv_func_iswcntrl = yes; then + HAVE_ISWCNTRL=1 + else + HAVE_ISWCNTRL=0 + fi + AC_SUBST([HAVE_ISWCNTRL]) + AC_CHECK_FUNCS_ONCE([iswblank]) + AC_CHECK_DECLS_ONCE([iswblank]) + if test $ac_cv_func_iswblank = yes; then + HAVE_ISWBLANK=1 + REPLACE_ISWBLANK=0 + else + HAVE_ISWBLANK=0 + if test $ac_cv_have_decl_iswblank = yes; then + REPLACE_ISWBLANK=1 + else + REPLACE_ISWBLANK=0 + fi + fi + AC_SUBST([HAVE_ISWBLANK]) + AC_SUBST([REPLACE_ISWBLANK]) + + AC_CHECK_HEADERS_ONCE([wctype.h]) + AC_REQUIRE([AC_C_INLINE]) + + AC_REQUIRE([gt_TYPE_WINT_T]) + if test $gt_cv_c_wint_t = yes; then + HAVE_WINT_T=1 + else + HAVE_WINT_T=0 + fi + AC_SUBST([HAVE_WINT_T]) + + if test $ac_cv_header_wctype_h = yes; then + if test $ac_cv_func_iswcntrl = yes; then + dnl Linux libc5 has an iswprint function that returns 0 for all arguments. + dnl The other functions are likely broken in the same way. + AC_CACHE_CHECK([whether iswcntrl works], [gl_cv_func_iswcntrl_works], + [ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + #include + #include + #include + #include + int main () { return iswprint ('x') == 0; }]])], + [gl_cv_func_iswcntrl_works=yes], [gl_cv_func_iswcntrl_works=no], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #if __GNU_LIBRARY__ == 1 + Linux libc5 i18n is broken. + #endif]], [])], + [gl_cv_func_iswcntrl_works=yes], [gl_cv_func_iswcntrl_works=no]) + ]) + ]) + fi + gl_CHECK_NEXT_HEADERS([wctype.h]) + HAVE_WCTYPE_H=1 + else + HAVE_WCTYPE_H=0 + fi + AC_SUBST([HAVE_WCTYPE_H]) + + if test "$gl_cv_func_iswcntrl_works" = no; then + REPLACE_ISWCNTRL=1 + else + REPLACE_ISWCNTRL=0 + fi + AC_SUBST([REPLACE_ISWCNTRL]) +]) diff --git a/m4/wint_t.m4 b/m4/wint_t.m4 new file mode 100644 index 000000000..58ef86556 --- /dev/null +++ b/m4/wint_t.m4 @@ -0,0 +1,32 @@ +# wint_t.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2003, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +/* 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 + wint_t foo = (wchar_t)'\0';]], + [[]])], + [gt_cv_c_wint_t=yes], + [gt_cv_c_wint_t=no])]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/m4/xsize.m4 b/m4/xsize.m4 new file mode 100644 index 000000000..b653693a3 --- /dev/null +++ b/m4/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 4 +dnl Copyright (C) 2003-2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS([stdint.h]) +]) diff --git a/mkinstalldirs b/mkinstalldirs deleted file mode 100644 index ef7e16fda..000000000 --- a/mkinstalldirs +++ /dev/null @@ -1,161 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy - -scriptversion=2006-05-11.19 - -# Original author: Noah Friedman -# Created: 1993-05-16 -# Public domain. -# -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' -IFS=" "" $nl" -errstatus=0 -dirmode= - -usage="\ -Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... - -Create each directory DIR (with mode MODE, if specified), including all -leading file name components. - -Report bugs to ." - -# process command line arguments -while test $# -gt 0 ; do - case $1 in - -h | --help | --h*) # -h for help - echo "$usage" - exit $? - ;; - -m) # -m PERM arg - shift - test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } - dirmode=$1 - shift - ;; - --version) - echo "$0 $scriptversion" - exit $? - ;; - --) # stop option processing - shift - break - ;; - -*) # unknown option - echo "$usage" 1>&2 - exit 1 - ;; - *) # first non-opt arg - break - ;; - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in - 0) exit 0 ;; -esac - -# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and -# mkdir -p a/c at the same time, both will detect that a is missing, -# one will create a, then the other will try to create a and die with -# a "File exists" error. This is a problem when calling mkinstalldirs -# from a parallel make. We use --version in the probe to restrict -# ourselves to GNU mkdir, which is thread-safe. -case $dirmode in - '') - if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - test -d ./-p && rmdir ./-p - test -d ./--version && rmdir ./--version - fi - ;; - *) - if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && - test ! -d ./--version; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - else - # Clean up after NextStep and OpenStep mkdir. - for d in ./-m ./-p ./--version "./$dirmode"; - do - test -d $d && rmdir $d - done - fi - ;; -esac - -for file -do - case $file in - /*) pathcomp=/ ;; - *) pathcomp= ;; - esac - oIFS=$IFS - IFS=/ - set fnord $file - shift - IFS=$oIFS - - for d - do - test "x$d" = x && continue - - pathcomp=$pathcomp$d - case $pathcomp in - -*) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - lasterr= - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp=$pathcomp/ - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/partmap/bsdlabel.c b/partmap/bsdlabel.c deleted file mode 100644 index a27b8eaec..000000000 --- a/partmap/bsdlabel.c +++ /dev/null @@ -1,147 +0,0 @@ -/* bsdlabel.c - Read BSD style partition tables. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,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 - * 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 - -#ifdef GRUB_UTIL -#include -#endif - -static struct grub_partition_map grub_bsdlabel_partition_map; - - -static grub_err_t -bsdlabel_partition_map_iterate (grub_disk_t disk, - int (*hook) (grub_disk_t disk, - const grub_partition_t partition)) -{ - struct grub_partition_bsd_disk_label label; - struct grub_partition p; - grub_disk_addr_t delta = 0; - unsigned pos; - - /* Read the BSD label. */ - if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, - 0, sizeof (label), &label)) - return grub_errno; - - /* Check if it is valid. */ - if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) - return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); - - /* A kludge to determine a base of be.offset. */ - if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION - < grub_cpu_to_le16 (label.num_partitions)) - { - struct grub_partition_bsd_entry whole_disk_be; - - pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR - * GRUB_DISK_SECTOR_SIZE + sizeof (struct grub_partition_bsd_entry) - * GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION; - - if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE, - pos % GRUB_DISK_SECTOR_SIZE, sizeof (whole_disk_be), - &whole_disk_be)) - return grub_errno; - - delta = grub_le_to_cpu32 (whole_disk_be.offset); - } - - pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR - * GRUB_DISK_SECTOR_SIZE; - - for (p.number = 0; - p.number < grub_cpu_to_le16 (label.num_partitions); - p.number++, pos += sizeof (struct grub_partition_bsd_entry)) - { - struct grub_partition_bsd_entry be; - - if (p.number == GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION) - continue; - - p.offset = pos / GRUB_DISK_SECTOR_SIZE; - p.index = pos % GRUB_DISK_SECTOR_SIZE; - - if (grub_disk_read (disk, p.offset, p.index, sizeof (be), &be)) - return grub_errno; - - p.start = grub_le_to_cpu32 (be.offset); - p.len = grub_le_to_cpu32 (be.size); - p.partmap = &grub_bsdlabel_partition_map; - - grub_dprintf ("partition", - "partition %d: type 0x%x, start 0x%llx, len 0x%llx\n", - p.number, be.fs_type, - (unsigned long long) p.start, - (unsigned long long) p.len); - - if (p.len == 0) - continue; - - if (p.start < delta) - { -#ifdef GRUB_UTIL - char *partname; -#endif - grub_dprintf ("partition", - "partition %d: invalid start (found 0x%llx, wanted >= 0x%llx)\n", - p.number, - (unsigned long long) p.start, - (unsigned long long) delta); -#ifdef GRUB_UTIL - /* disk->partition != NULL as 0 < delta */ - partname = grub_partition_get_name (disk->partition); - grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)", - disk->name, partname, p.partmap->name, p.number + 1); - grub_free (partname); -#endif - continue; - } - - p.start -= delta; - - if (hook (disk, &p)) - return grub_errno; - } - - return GRUB_ERR_NONE; -} - - -/* Partition map type. */ -static struct grub_partition_map grub_bsdlabel_partition_map = - { - .name = "bsd", - .iterate = bsdlabel_partition_map_iterate, - }; - -GRUB_MOD_INIT(part_bsd) -{ - grub_partition_map_register (&grub_bsdlabel_partition_map); -} - -GRUB_MOD_FINI(part_bsd) -{ - grub_partition_map_unregister (&grub_bsdlabel_partition_map); -} diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 000000000..d0af6c962 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,464 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. +# +# Origin: gettext-0.18 +GETTEXT_MACRO_VERSION = 0.18 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: check-macro-version all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +check-macro-version: + @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell.in remove-potcdate.sed + if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \ + package_gnu='GNU '; \ + else \ + package_gnu=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_gnu}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES-shell.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + --join-existing --language=Shell --keyword=gettext_quoted \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES-shell.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_gnu}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + --join-existing --language=Shell --keyword=gettext_quoted \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + $(MAKE) update-po + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +# Recreate Makefile by invoking config.status. Explicitly invoke the shell, +# because execution permission bits may not work on the current file system. +# Use @SHELL@, which is the shell determined by autoconf for the use by its +# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && @SHELL@ ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 000000000..44857b1b8 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,41 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Free Software Foundation, Inc. + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = bug-grub@gnu.org + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES b/po/POTFILES deleted file mode 100644 index cfa1e33cb..000000000 --- a/po/POTFILES +++ /dev/null @@ -1,80 +0,0 @@ -# List of files which contain translatable strings. -commands/acpi.c -commands/blocklist.c -commands/boot.c -commands/cat.c -commands/cmp.c -commands/configfile.c -commands/crc.c -commands/date.c -commands/echo.c -commands/efi/fixvideo.c -commands/efi/loadbios.c -commands/gptsync.c -commands/halt.c -commands/hdparm.c -commands/help.c -commands/hexdump.c -commands/i386/cpuid.c -commands/i386/pc/drivemap.c -commands/i386/pc/halt.c -commands/i386/pc/play.c -commands/i386/pc/pxecmd.c -commands/i386/pc/vbeinfo.c -commands/i386/pc/vbetest.c -commands/ieee1275/suspend.c -commands/keystatus.c -commands/loadenv.c -commands/ls.c -commands/lsmmap.c -commands/lspci.c -commands/memrw.c -commands/minicmd.c -commands/parttool.c -commands/password.c -commands/probe.c -commands/read.c -commands/reboot.c -commands/search.c -commands/search_file.c -commands/search_label.c -commands/search_uuid.c -commands/sleep.c -commands/test.c -commands/true.c -commands/usbtest.c -commands/videotest.c -commands/xnu_uuid.c - -disk/loopback.c - -hello/hello.c - -lib/arg.c - -loader/efi/appleloader.c -loader/efi/chainloader.c -loader/i386/bsd.c -loader/i386/efi/linux.c -loader/i386/ieee1275/linux.c -loader/i386/linux.c -loader/i386/pc/chainloader.c -loader/i386/pc/linux.c -loader/i386/xnu.c -loader/multiboot.c -loader/powerpc/ieee1275/linux.c -loader/sparc64/ieee1275/linux.c -loader/xnu.c - -normal/auth.c -normal/color.c -normal/dyncmd.c -normal/main.c -normal/menu_entry.c -normal/menu_text.c -normal/misc.c - -term/serial.c - -util/grub-mkimage.c -util/i386/pc/grub-setup.c diff --git a/po/POTFILES-shell b/po/POTFILES-shell.in similarity index 78% rename from po/POTFILES-shell rename to po/POTFILES-shell.in index 90d2b978c..70c2a3fd4 100644 --- a/po/POTFILES-shell +++ b/po/POTFILES-shell.in @@ -1,5 +1,7 @@ # List of files which contain translatable strings. Only files written in # Shell language are included here. +util/grub.d/10_hurd.in util/grub.d/10_kfreebsd.in util/grub.d/10_linux.in util/grub.d/10_netbsd.in +util/grub.d/20_linux_xen.in diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 000000000..8329fdf0a --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,117 @@ +# List of files which contain translatable strings. +grub-core/commands/acpi.c +grub-core/commands/blocklist.c +grub-core/commands/boot.c +grub-core/commands/cat.c +grub-core/commands/cmp.c +grub-core/commands/configfile.c +grub-core/commands/date.c +grub-core/commands/echo.c +grub-core/commands/efi/fixvideo.c +grub-core/commands/efi/loadbios.c +grub-core/commands/gptsync.c +grub-core/commands/halt.c +grub-core/commands/hashsum.c +grub-core/commands/hdparm.c +grub-core/commands/help.c +grub-core/commands/hexdump.c +grub-core/commands/i386/cpuid.c +grub-core/commands/i386/pc/drivemap.c +grub-core/commands/i386/pc/halt.c +grub-core/commands/i386/pc/lsapm.c +grub-core/commands/i386/pc/play.c +grub-core/commands/i386/pc/pxecmd.c +grub-core/commands/ieee1275/suspend.c +grub-core/commands/iorw.c +grub-core/commands/keylayouts.c +grub-core/commands/keystatus.c +grub-core/commands/legacycfg.c +grub-core/commands/loadenv.c +grub-core/commands/ls.c +grub-core/commands/lsacpi.c +grub-core/commands/lsmmap.c +grub-core/commands/lspci.c +grub-core/commands/memrw.c +grub-core/commands/menuentry.c +grub-core/commands/minicmd.c +grub-core/commands/parttool.c +grub-core/commands/password.c +grub-core/commands/password_pbkdf2.c +grub-core/commands/probe.c +grub-core/commands/read.c +grub-core/commands/reboot.c +grub-core/commands/regexp.c +grub-core/commands/search.c +grub-core/commands/search_file.c +grub-core/commands/search_label.c +grub-core/commands/search_uuid.c +grub-core/commands/search_wrap.c +grub-core/commands/setpci.c +grub-core/commands/sleep.c +grub-core/commands/terminal.c +grub-core/commands/test.c +grub-core/commands/testload.c +grub-core/commands/true.c +grub-core/commands/usbtest.c +grub-core/commands/videoinfo.c +grub-core/commands/videotest.c +grub-core/commands/xnu_uuid.c + +grub-core/disk/loopback.c + +grub-core/efiemu/main.c + +grub-core/font/font_cmd.c + +grub-core/gettext/gettext.c + +grub-core/gfxmenu/gui_progress_bar.c + +grub-core/hello/hello.c + +grub-core/kern/corecmd.c +grub-core/kern/emu/hostdisk.c +grub-core/kern/emu/misc.c +grub-core/kern/err.c + +grub-core/lib/arg.c + +grub-core/loader/efi/appleloader.c +grub-core/loader/efi/chainloader.c +grub-core/loader/i386/bsd.c +grub-core/loader/i386/linux.c +grub-core/loader/i386/pc/chainloader.c +grub-core/loader/i386/pc/linux.c +grub-core/loader/i386/pc/ntldr.c +grub-core/loader/i386/xnu.c +grub-core/loader/mips/linux.c +grub-core/loader/multiboot.c +grub-core/loader/powerpc/ieee1275/linux.c +grub-core/loader/sparc64/ieee1275/linux.c +grub-core/loader/xnu.c + +grub-core/mmap/mmap.c + +grub-core/normal/auth.c +grub-core/normal/cmdline.c +grub-core/normal/color.c +grub-core/normal/context.c +grub-core/normal/dyncmd.c +grub-core/normal/main.c +grub-core/normal/menu.c +grub-core/normal/menu_entry.c +grub-core/normal/menu_text.c +grub-core/normal/misc.c + +grub-core/script/main.c + +grub-core/term/gfxterm.c +grub-core/term/serial.c +grub-core/term/terminfo.c + +grub-core/tests/test_blockarg.c + +util/grub-editenv.c +util/grub-fstest.c +util/grub-mkimage.c +util/grub-setup.c diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 000000000..af5248792 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,47 @@ +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 000000000..4b937aa51 --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 000000000..fedb6a06d --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 000000000..a9647fc35 --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 000000000..b26de01f6 --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 000000000..0122c4631 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 000000000..2436c49e7 --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/script/execute.c b/script/execute.c deleted file mode 100644 index c45a15d29..000000000 --- a/script/execute.c +++ /dev/null @@ -1,392 +0,0 @@ -/* execute.c -- Execute a GRUB script. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,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 - -/* Max digits for a char is 3 (0xFF is 255), similarly for an int it - is sizeof (int) * 3, and one extra for a possible -ve sign. */ -#define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1) - -static grub_err_t -grub_script_execute_cmd (struct grub_script_cmd *cmd) -{ - int ret; - char errnobuf[ERRNO_DIGITS_MAX + 1]; - - if (cmd == 0) - return 0; - - ret = cmd->exec (cmd); - - grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); - grub_env_set ("?", errnobuf); - return ret; -} - -#define ARG_ALLOCATION_UNIT (32 * sizeof (char)) -#define ARGV_ALLOCATION_UNIT (8 * sizeof (void*)) - -/* Expand arguments in ARGLIST into multiple arguments. */ -char ** -grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count) -{ - int i; - int oom; - int argc; - int empty; - char *ptr; - char **argv; - char *value; - struct grub_script_arg *arg; - - auto void push (char *str); - void push (char *str) - { - char **p; - - if (oom) - return; - - p = grub_realloc (argv, ALIGN_UP (sizeof(char*) * (argc + 1), ARGV_ALLOCATION_UNIT)); - if (!p) - oom = 1; - else - { - p[argc++] = str; - argv = p; - } - } - - auto char* append (const char *str, grub_size_t nchar); - char* append (const char *str, grub_size_t nchar) - { - int len; - int old; - char *p; - - if (oom || !str) - return 0; - - len = nchar ?: grub_strlen (str); - old = argv[argc - 1] ? grub_strlen (argv[argc - 1]) : 0; - p = grub_realloc (argv[argc - 1], ALIGN_UP(old + len + 1, ARG_ALLOCATION_UNIT)); - - if (p) - { - grub_strncpy (p + old, str, len); - p[old + len] = '\0'; - } - else - { - oom = 1; - grub_free (argv[argc - 1]); - } - argv[argc - 1] = p; - return argv[argc - 1]; - } - - /* Move *STR to the begining of next word, but return current word. */ - auto char* move_to_next (char **str); - char* move_to_next (char **str) - { - char *end; - char *start; - - if (oom || !str || !*str) - return 0; - - start = *str; - while (*start && grub_isspace (*start)) start++; - if (*start == '\0') - return 0; - - end = start + 1; - while (*end && !grub_isspace (*end)) end++; - - *str = end; - return start; - } - - oom = 0; - argv = 0; - argc = 0; - push (0); - for (; arglist; arglist = arglist->next) - { - empty = 1; - arg = arglist->arg; - while (arg) - { - switch (arg->type) - { - case GRUB_SCRIPT_ARG_TYPE_VAR: - value = grub_env_get (arg->str); - while (value && *value && (ptr = move_to_next(&value))) - { - empty = 0; - append (ptr, value - ptr); - if (*value) push(0); - } - break; - - case GRUB_SCRIPT_ARG_TYPE_TEXT: - if (grub_strlen (arg->str) > 0) - { - empty = 0; - append (arg->str, 0); - } - break; - - case GRUB_SCRIPT_ARG_TYPE_DQSTR: - case GRUB_SCRIPT_ARG_TYPE_SQSTR: - empty = 0; - append (arg->str, 0); - break; - - case GRUB_SCRIPT_ARG_TYPE_DQVAR: - empty = 0; - append (grub_env_get (arg->str), 0); - break; - } - arg = arg->next; - } - if (!empty) - push (0); - } - - if (oom) - { - for (i = 0; i < argc; i++) - grub_free (argv[i]); - grub_free (argv); - argv = 0; - } - - if (argv) - *count = argc - 1; - - return argv; -} - -/* Execute a single command line. */ -grub_err_t -grub_script_execute_cmdline (struct grub_script_cmd *cmd) -{ - struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd; - char **args = 0; - int i = 0; - grub_command_t grubcmd; - grub_err_t ret = 0; - int argcount = 0; - grub_script_function_t func = 0; - char errnobuf[18]; - char *cmdname; - - /* Lookup the command. */ - args = grub_script_execute_arglist_to_argv (cmdline->arglist, &argcount); - if (! args || ! args[0]) - return grub_errno; - - cmdname = args[0]; - grubcmd = grub_command_find (cmdname); - if (! grubcmd) - { - grub_errno = GRUB_ERR_NONE; - - /* It's not a GRUB command, try all functions. */ - func = grub_script_function_find (cmdname); - if (! func) - { - /* As a last resort, try if it is an assignment. */ - char *assign = grub_strdup (cmdname); - char *eq = grub_strchr (assign, '='); - - if (eq) - { - /* This was set because the command was not found. */ - grub_errno = GRUB_ERR_NONE; - - /* Create two strings and set the variable. */ - *eq = '\0'; - eq++; - grub_env_set (assign, eq); - } - grub_free (assign); - - grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno); - grub_env_set ("?", errnobuf); - - grub_print_error (); - - return 0; - } - } - - /* Execute the GRUB command or function. */ - if (grubcmd) - ret = (grubcmd->func) (grubcmd, argcount - 1, args + 1); - else - ret = grub_script_function_call (func, argcount - 1, args + 1); - - /* Free arguments. */ - for (i = 0; i < argcount; i++) - grub_free (args[i]); - grub_free (args); - - if (grub_errno == GRUB_ERR_TEST_FAILURE) - grub_errno = GRUB_ERR_NONE; - - grub_print_error (); - - grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); - grub_env_set ("?", errnobuf); - - return ret; -} - -/* Execute a block of one or more commands. */ -grub_err_t -grub_script_execute_cmdblock (struct grub_script_cmd *cmd) -{ - int ret = 0; - struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) cmd; - - /* Loop over every command and execute it. */ - for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next) - ret = grub_script_execute_cmd (cmd); - - return ret; -} - -/* Execute an if statement. */ -grub_err_t -grub_script_execute_cmdif (struct grub_script_cmd *cmd) -{ - struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd; - char *result; - - /* Check if the commands results in a true or a false. The value is - read from the env variable `?'. */ - grub_script_execute_cmd (cmdif->exec_to_evaluate); - result = grub_env_get ("?"); - - grub_errno = GRUB_ERR_NONE; - - /* Execute the `if' or the `else' part depending on the value of - `?'. */ - if (result && ! grub_strcmp (result, "0")) - return grub_script_execute_cmd (cmdif->exec_on_true); - else - return grub_script_execute_cmd (cmdif->exec_on_false); -} - -/* Execute a for statement. */ -grub_err_t -grub_script_execute_cmdfor (struct grub_script_cmd *cmd) -{ - int i; - int result; - char **args; - int argcount; - struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; - - args = grub_script_execute_arglist_to_argv (cmdfor->words, &argcount); - if (!args) - return grub_errno; - - result = 0; - for (i = 0; i < argcount; i++) - { - grub_env_set (cmdfor->name->str, args[i]); - result = grub_script_execute_cmd (cmdfor->list); - grub_free (args[i]); - } - - grub_free (args); - return result; -} - -/* Execute a "while" or "until" command. */ -grub_err_t -grub_script_execute_cmdwhile (struct grub_script_cmd *cmd) -{ - int cond; - int result; - struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd; - - result = 0; - do { - cond = grub_script_execute_cmd (cmdwhile->cond); - if (cmdwhile->until ? !cond : cond) - break; - - result = grub_script_execute_cmd (cmdwhile->list); - } while (1); /* XXX Put a check for ^C here */ - - return result; -} - -/* Execute the menu entry generate statement. */ -grub_err_t -grub_script_execute_menuentry (struct grub_script_cmd *cmd) -{ - struct grub_script_cmd_menuentry *cmd_menuentry; - char **args = 0; - int argcount = 0; - int i = 0; - - cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd; - - if (cmd_menuentry->arglist) - { - args = grub_script_execute_arglist_to_argv (cmd_menuentry->arglist, &argcount); - if (!args) - return grub_errno; - } - - grub_normal_add_menu_entry (argcount, (const char **) args, - cmd_menuentry->sourcecode); - - /* Free arguments. */ - for (i = 0; i < argcount; i++) - grub_free (args[i]); - grub_free (args); - - return grub_errno; -} - - - -/* Execute any GRUB pre-parsed command or script. */ -grub_err_t -grub_script_execute (struct grub_script *script) -{ - if (script == 0) - return 0; - - return grub_script_execute_cmd (script->cmd); -} - diff --git a/script/main.c b/script/main.c deleted file mode 100644 index 752a8cd8a..000000000 --- a/script/main.c +++ /dev/null @@ -1,41 +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 - -grub_err_t -grub_normal_parse_line (char *line, grub_reader_getline_t getline) -{ - struct grub_script *parsed_script; - - /* Parse the script. */ - parsed_script = grub_script_parse (line, getline); - - if (parsed_script) - { - /* Execute the command(s). */ - grub_script_execute (parsed_script); - - /* The parsed script was executed, throw it away. */ - grub_script_free (parsed_script); - } - - return grub_errno; -} diff --git a/term/at_keyboard.c b/term/at_keyboard.c deleted file mode 100644 index c3e71ea2d..000000000 --- a/term/at_keyboard.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 - * 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 short at_keyboard_status = 0; -static int pending_key = -1; - -#define KEYBOARD_STATUS_SHIFT_L (1 << 0) -#define KEYBOARD_STATUS_SHIFT_R (1 << 1) -#define KEYBOARD_STATUS_ALT_L (1 << 2) -#define KEYBOARD_STATUS_ALT_R (1 << 3) -#define KEYBOARD_STATUS_CTRL_L (1 << 4) -#define KEYBOARD_STATUS_CTRL_R (1 << 5) -#define KEYBOARD_STATUS_CAPS_LOCK (1 << 6) -#define KEYBOARD_STATUS_NUM_LOCK (1 << 7) - -static grub_uint8_t led_status; - -#define KEYBOARD_LED_SCROLL (1 << 0) -#define KEYBOARD_LED_NUM (1 << 1) -#define KEYBOARD_LED_CAPS (1 << 2) - -static char keyboard_map[128] = -{ - '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', '\0', '*', - '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_HOME, - GRUB_TERM_UP, GRUB_TERM_NPAGE, '-', GRUB_TERM_LEFT, '\0', GRUB_TERM_RIGHT, '+', GRUB_TERM_END, - GRUB_TERM_DOWN, GRUB_TERM_PPAGE, '\0', GRUB_TERM_DC, '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, - OLPC_RIGHT -}; - -static char keyboard_map_shift[128] = -{ - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?' -}; - -static grub_uint8_t grub_keyboard_controller_orig; - -static void -keyboard_controller_wait_until_ready (void) -{ - while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))); -} - -static void -grub_keyboard_controller_write (grub_uint8_t c) -{ - keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS); - grub_outb (c, KEYBOARD_REG_DATA); -} - -static grub_uint8_t -grub_keyboard_controller_read (void) -{ - keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_READ, KEYBOARD_REG_STATUS); - return grub_inb (KEYBOARD_REG_DATA); -} - -static void -keyboard_controller_led (grub_uint8_t leds) -{ - keyboard_controller_wait_until_ready (); - grub_outb (0xed, KEYBOARD_REG_DATA); - keyboard_controller_wait_until_ready (); - grub_outb (leds & 0x7, KEYBOARD_REG_DATA); -} - -/* FIXME: This should become an interrupt service routine. For now - it's just used to catch events from control keys. */ -static void -grub_keyboard_isr (char key) -{ - char is_make = KEYBOARD_ISMAKE (key); - key = KEYBOARD_SCANCODE (key); - if (is_make) - switch (key) - { - case SHIFT_L: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L; - break; - case SHIFT_R: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R; - break; - case CTRL: - at_keyboard_status |= KEYBOARD_STATUS_CTRL_L; - break; - case ALT: - at_keyboard_status |= KEYBOARD_STATUS_ALT_L; - break; - default: - /* Skip grub_dprintf. */ - return; - } - else - switch (key) - { - case SHIFT_L: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L; - break; - case SHIFT_R: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R; - break; - case CTRL: - at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L; - break; - case ALT: - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L; - break; - default: - /* Skip grub_dprintf. */ - return; - } -#ifdef DEBUG_AT_KEYBOARD - grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed"); -#endif -} - -/* If there is a raw key pending, return it; otherwise return -1. */ -static int -grub_keyboard_getkey (void) -{ - grub_uint8_t key; - if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) - return -1; - key = grub_inb (KEYBOARD_REG_DATA); - /* FIXME */ grub_keyboard_isr (key); - if (! KEYBOARD_ISMAKE (key)) - return -1; - return (KEYBOARD_SCANCODE (key)); -} - -/* If there is a character pending, return it; otherwise return -1. */ -static int -grub_at_keyboard_getkey_noblock (void) -{ - int code, key; - code = grub_keyboard_getkey (); - if (code == -1) - return -1; -#ifdef DEBUG_AT_KEYBOARD - grub_dprintf ("atkeyb", "Detected key 0x%x\n", key); -#endif - switch (code) - { - case CAPS_LOCK: - /* Caps lock sends scan code twice. Get the second one and discard it. */ - while (grub_keyboard_getkey () == -1); - - at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK; - led_status ^= KEYBOARD_LED_CAPS; - keyboard_controller_led (led_status); - -#ifdef DEBUG_AT_KEYBOARD - grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); -#endif - key = -1; - break; - case NUM_LOCK: - /* Num lock sends scan code twice. Get the second one and discard it. */ - while (grub_keyboard_getkey () == -1); - - at_keyboard_status ^= KEYBOARD_STATUS_NUM_LOCK; - led_status ^= KEYBOARD_LED_NUM; - keyboard_controller_led (led_status); - -#ifdef DEBUG_AT_KEYBOARD - grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); -#endif - key = -1; - break; - case SCROLL_LOCK: - /* For scroll lock we don't keep track of status. Only update its led. */ - led_status ^= KEYBOARD_LED_SCROLL; - keyboard_controller_led (led_status); - key = -1; - break; - default: - if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R)) - key = keyboard_map[code] - 'a' + 1; - else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R)) - && keyboard_map_shift[code]) - key = keyboard_map_shift[code]; - else - key = keyboard_map[code]; - - if (key == 0) - grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); - - if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK) - { - if ((key >= 'a') && (key <= 'z')) - key += 'A' - 'a'; - else if ((key >= 'A') && (key <= 'Z')) - key += 'a' - 'A'; - } - } - return key; -} - -static int -grub_at_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - if (pending_key != -1) - return 1; - - pending_key = grub_at_keyboard_getkey_noblock (); - - if (pending_key != -1) - return 1; - - return -1; -} - -static int -grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) -{ - int key; - if (pending_key != -1) - { - key = pending_key; - pending_key = -1; - return key; - } - do - { - key = grub_at_keyboard_getkey_noblock (); - } while (key == -1); - return key; -} - -static grub_err_t -grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unused))) -{ - pending_key = -1; - at_keyboard_status = 0; - grub_keyboard_controller_orig = grub_keyboard_controller_read (); - grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1); - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) -{ - grub_keyboard_controller_write (grub_keyboard_controller_orig); - return GRUB_ERR_NONE; -} - -static struct grub_term_input grub_at_keyboard_term = - { - .name = "at_keyboard", - .init = grub_keyboard_controller_init, - .fini = grub_keyboard_controller_fini, - .checkkey = grub_at_keyboard_checkkey, - .getkey = grub_at_keyboard_getkey, - }; - -GRUB_MOD_INIT(at_keyboard) -{ - grub_term_register_input ("at_keyboard", &grub_at_keyboard_term); -} - -GRUB_MOD_FINI(at_keyboard) -{ - grub_term_unregister_input (&grub_at_keyboard_term); -} diff --git a/term/serial.c b/term/serial.c deleted file mode 100644 index cf7759ef2..000000000 --- a/term/serial.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2001,2002,2003,2004,2005,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 - * 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 unsigned int registered = 0; - -/* Argument options. */ -static const struct grub_arg_option options[] = -{ - {"unit", 'u', 0, N_("Set the serial unit."), 0, ARG_TYPE_INT}, - {"port", 'p', 0, N_("Set the serial port address."), 0, ARG_TYPE_STRING}, - {"speed", 's', 0, N_("Set the serial port speed."), 0, ARG_TYPE_INT}, - {"word", 'w', 0, N_("Set the serial port word length."), 0, ARG_TYPE_INT}, - {"parity", 'r', 0, N_("Set the serial port parity."), 0, ARG_TYPE_STRING}, - {"stop", 't', 0, N_("Set the serial port stop bits."), 0, ARG_TYPE_INT}, - {0, 0, 0, 0, 0, 0} -}; - -/* Serial port settings. */ -struct serial_port -{ - grub_port_t port; - unsigned short divisor; - unsigned short word_len; - unsigned int parity; - unsigned short stop_bits; -}; - -/* Serial port settings. */ -static struct serial_port serial_settings; - -#ifdef GRUB_MACHINE_PCBIOS -static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; -#define GRUB_SERIAL_PORT_NUM 4 -#else -#include -static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS; -#define GRUB_SERIAL_PORT_NUM (ARRAY_SIZE(serial_hw_io_addr)) -#endif - -/* Return the port number for the UNITth serial device. */ -static inline grub_port_t -serial_hw_get_port (const unsigned int unit) -{ - if (unit < GRUB_SERIAL_PORT_NUM) - return serial_hw_io_addr[unit]; - else - return 0; -} - -/* Fetch a key. */ -static int -serial_hw_fetch (void) -{ - if (grub_inb (serial_settings.port + UART_LSR) & UART_DATA_READY) - return grub_inb (serial_settings.port + UART_RX); - - return -1; -} - -/* Put a character. */ -static void -serial_hw_put (const int c) -{ - unsigned int timeout = 100000; - - /* Wait until the transmitter holding register is empty. */ - while ((grub_inb (serial_settings.port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0) - { - if (--timeout == 0) - /* There is something wrong. But what can I do? */ - return; - } - - grub_outb (c, serial_settings.port + UART_TX); -} - -/* Convert speed to divisor. */ -static unsigned short -serial_get_divisor (unsigned int speed) -{ - unsigned int i; - - /* The structure for speed vs. divisor. */ - struct divisor - { - unsigned int speed; - unsigned short div; - }; - - /* The table which lists common configurations. */ - /* 1843200 / (speed * 16) */ - static struct divisor divisor_tab[] = - { - { 2400, 0x0030 }, - { 4800, 0x0018 }, - { 9600, 0x000C }, - { 19200, 0x0006 }, - { 38400, 0x0003 }, - { 57600, 0x0002 }, - { 115200, 0x0001 } - }; - - /* Set the baud rate. */ - for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++) - if (divisor_tab[i].speed == speed) - /* UART in Yeeloong runs twice the usual rate. */ -#ifdef GRUB_MACHINE_MIPS_YEELOONG - return 2 * divisor_tab[i].div; -#else - return divisor_tab[i].div; -#endif - return 0; -} - -/* Initialize a serial device. PORT is the port number for a serial device. - SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600, - 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used - for the device. Likewise, PARITY is the type of the parity and - STOP_BIT_LEN is the length of the stop bit. The possible values for - WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as - macros. */ -static grub_err_t -serial_hw_init (void) -{ - unsigned char status = 0; - - /* Turn off the interrupt. */ - grub_outb (0, serial_settings.port + UART_IER); - - /* Set DLAB. */ - grub_outb (UART_DLAB, serial_settings.port + UART_LCR); - - /* Set the baud rate. */ - grub_outb (serial_settings.divisor & 0xFF, serial_settings.port + UART_DLL); - grub_outb (serial_settings.divisor >> 8, serial_settings.port + UART_DLH); - - /* Set the line status. */ - status |= (serial_settings.parity - | serial_settings.word_len - | serial_settings.stop_bits); - grub_outb (status, serial_settings.port + UART_LCR); - - /* In Yeeloong serial port has only 3 wires. */ -#ifndef GRUB_MACHINE_MIPS_YEELOONG - /* Enable the FIFO. */ - grub_outb (UART_ENABLE_FIFO_TRIGGER1, serial_settings.port + UART_FCR); - - /* Turn on DTR and RTS. */ - grub_outb (UART_ENABLE_DTRRTS, serial_settings.port + UART_MCR); -#else - /* Enable the FIFO. */ - grub_outb (UART_ENABLE_FIFO_TRIGGER14, serial_settings.port + UART_FCR); - - /* Turn on DTR, RTS, and OUT2. */ - grub_outb (UART_ENABLE_DTRRTS | UART_ENABLE_OUT2, - serial_settings.port + UART_MCR); -#endif - - /* Drain the input buffer. */ - while (serial_hw_fetch () != -1); - - /* FIXME: should check if the serial terminal was found. */ - - return GRUB_ERR_NONE; -} - -static grub_uint16_t -grub_serial_getwh (struct grub_term_output *term __attribute__ ((unused))) -{ - const grub_uint8_t TEXT_WIDTH = 80; - const grub_uint8_t TEXT_HEIGHT = 24; - return (TEXT_WIDTH << 8) | TEXT_HEIGHT; -} - -struct grub_terminfo_input_state grub_serial_terminfo_input = - { - .readkey = serial_hw_fetch - }; - -struct grub_terminfo_output_state grub_serial_terminfo_output = - { - .put = serial_hw_put - }; - -static struct grub_term_input grub_serial_term_input = -{ - .name = "serial", - .init = grub_terminfo_input_init, - .checkkey = grub_terminfo_checkkey, - .getkey = grub_terminfo_getkey, - .data = &grub_serial_terminfo_input -}; - -static struct grub_term_output grub_serial_term_output = -{ - .name = "serial", - .putchar = grub_terminfo_putchar, - .getwh = grub_serial_getwh, - .getxy = grub_terminfo_getxy, - .gotoxy = grub_terminfo_gotoxy, - .cls = grub_terminfo_cls, - .setcolorstate = grub_terminfo_setcolorstate, - .setcursor = grub_terminfo_setcursor, - .flags = GRUB_TERM_CODE_TYPE_ASCII, - .data = &grub_serial_terminfo_output, - .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR, - .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR, -}; - - - -static grub_err_t -grub_cmd_serial (grub_extcmd_t cmd, - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - struct grub_arg_list *state = cmd->state; - struct serial_port backup_settings = serial_settings; - grub_err_t hwiniterr; - - if (state[0].set) - { - unsigned int unit; - - unit = grub_strtoul (state[0].arg, 0, 0); - serial_settings.port = serial_hw_get_port (unit); - if (!serial_settings.port) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad unit number"); - } - - if (state[1].set) - serial_settings.port = (grub_port_t) grub_strtoul (state[1].arg, 0, 0); - - if (state[2].set) - { - unsigned long speed; - - speed = grub_strtoul (state[2].arg, 0, 0); - serial_settings.divisor = serial_get_divisor ((unsigned int) speed); - if (serial_settings.divisor == 0) - { - serial_settings = backup_settings; - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); - } - } - - if (state[3].set) - { - if (! grub_strcmp (state[3].arg, "5")) - serial_settings.word_len = UART_5BITS_WORD; - else if (! grub_strcmp (state[3].arg, "6")) - serial_settings.word_len = UART_6BITS_WORD; - else if (! grub_strcmp (state[3].arg, "7")) - serial_settings.word_len = UART_7BITS_WORD; - else if (! grub_strcmp (state[3].arg, "8")) - serial_settings.word_len = UART_8BITS_WORD; - else - { - serial_settings = backup_settings; - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad word length"); - } - } - - if (state[4].set) - { - if (! grub_strcmp (state[4].arg, "no")) - serial_settings.parity = UART_NO_PARITY; - else if (! grub_strcmp (state[4].arg, "odd")) - serial_settings.parity = UART_ODD_PARITY; - else if (! grub_strcmp (state[4].arg, "even")) - serial_settings.parity = UART_EVEN_PARITY; - else - { - serial_settings = backup_settings; - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity"); - } - } - - if (state[5].set) - { - if (! grub_strcmp (state[5].arg, "1")) - serial_settings.stop_bits = UART_1_STOP_BIT; - else if (! grub_strcmp (state[5].arg, "2")) - serial_settings.stop_bits = UART_2_STOP_BITS; - else - { - serial_settings = backup_settings; - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits"); - } - } - - /* Initialize with new settings. */ - hwiniterr = serial_hw_init (); - - if (hwiniterr == GRUB_ERR_NONE) - { - /* Register terminal if not yet registered. */ - if (registered == 0) - { - grub_term_register_input ("serial", &grub_serial_term_input); - grub_term_register_output ("serial", &grub_serial_term_output); - grub_terminfo_output_register (&grub_serial_term_output, "vt100"); - registered = 1; - } - } - else - { - /* Initialization with new settings failed. */ - if (registered == 1) - { - /* If the terminal is registered, attempt to restore previous - settings. */ - serial_settings = backup_settings; - if (serial_hw_init () != GRUB_ERR_NONE) - { - /* If unable to restore settings, unregister terminal. */ - grub_term_unregister_input (&grub_serial_term_input); - grub_term_unregister_output (&grub_serial_term_output); - grub_terminfo_output_unregister (&grub_serial_term_output); - registered = 0; - } - } - } - - return hwiniterr; -} - -static grub_extcmd_t cmd; - -GRUB_MOD_INIT(serial) -{ - cmd = grub_register_extcmd ("serial", grub_cmd_serial, - GRUB_COMMAND_FLAG_BOTH, - N_("[OPTIONS...]"), - N_("Configure serial port."), options); - - /* Set default settings. */ - serial_settings.port = serial_hw_get_port (0); -#ifdef GRUB_MACHINE_MIPS_YEELOONG - serial_settings.divisor = serial_get_divisor (115200); -#else - serial_settings.divisor = serial_get_divisor (9600); -#endif - serial_settings.word_len = UART_8BITS_WORD; - serial_settings.parity = UART_NO_PARITY; - serial_settings.stop_bits = UART_1_STOP_BIT; - -#ifdef GRUB_MACHINE_MIPS_YEELOONG - { - grub_err_t hwiniterr; - hwiniterr = serial_hw_init (); - - if (hwiniterr == GRUB_ERR_NONE) - { - grub_term_register_input_active ("serial", &grub_serial_term_input); - grub_term_register_output_active ("serial", &grub_serial_term_output); - - registered = 1; - } - } -#endif -} - -GRUB_MOD_FINI(serial) -{ - grub_unregister_extcmd (cmd); - if (registered == 1) /* Unregister terminal only if registered. */ - { - grub_term_unregister_input (&grub_serial_term_input); - grub_term_unregister_output (&grub_serial_term_output); - grub_terminfo_output_unregister (&grub_serial_term_output); - } -} diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c deleted file mode 100644 index ae9c41035..000000000 --- a/term/usb_keyboard.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Support for the HID Boot Protocol. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 - * 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 - - -static char keyboard_map[128] = - { - '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '0', - '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[', - ']', '\\', '#', ';', '\'', '`', ',', '.', - '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT, - GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP - }; - -static char keyboard_map_shift[128] = - { - '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', - '#', '$', '%', '^', '&', '*', '(', ')', - '\n', '\0', '\0', '\0', ' ', '_', '+', '{', - '}', '|', '#', ':', '"', '`', '<', '>', - '?' - }; - -static grub_usb_device_t usbdev; - -/* Valid values for bmRequestType. See HID definition version 1.11 section - 7.2. */ -#define USB_HID_HOST_TO_DEVICE 0x21 -#define USB_HID_DEVICE_TO_HOST 0xA1 - -/* Valid values for bRequest. See HID definition version 1.11 section 7.2. */ -#define USB_HID_GET_REPORT 0x01 -#define USB_HID_GET_IDLE 0x02 -#define USB_HID_GET_PROTOCOL 0x03 -#define USB_HID_SET_REPORT 0x09 -#define USB_HID_SET_IDLE 0x0A -#define USB_HID_SET_PROTOCOL 0x0B - -static void -grub_usb_hid (void) -{ - struct grub_usb_desc_device *descdev; - - auto int usb_iterate (grub_usb_device_t dev); - int usb_iterate (grub_usb_device_t dev) - { - descdev = &dev->descdev; - - grub_dprintf ("usb_keyboard", "%x %x %x\n", - descdev->class, descdev->subclass, descdev->protocol); - -#if 0 - if (descdev->class != 0x09 - || descdev->subclass == 0x01 - || descdev->protocol != 0x02) - return 0; -#endif - - if (descdev->class != 0 || descdev->subclass != 0 || descdev->protocol != 0) - return 0; - - grub_printf ("HID found!\n"); - - usbdev = dev; - - return 1; - } - grub_usb_iterate (usb_iterate); - - /* Place the device in boot mode. */ - grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_PROTOCOL, - 0, 0, 0, 0); - - /* Reports every time an event occurs and not more often than that. */ - grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE, - 0<<8, 0, 0, 0); -} - -static grub_err_t -grub_usb_keyboard_getreport (grub_usb_device_t dev, grub_uint8_t *report) -{ - return grub_usb_control_msg (dev, USB_HID_DEVICE_TO_HOST, USB_HID_GET_REPORT, - 0, 0, 8, (char *) report); -} - - - -static int -grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - grub_uint8_t data[8]; - int key; - grub_err_t err; - grub_uint64_t currtime; - int timeout = 50; - - data[2] = 0; - currtime = grub_get_time_ms (); - do - { - /* Get_Report. */ - err = grub_usb_keyboard_getreport (usbdev, data); - - /* Implement a timeout. */ - if (grub_get_time_ms () > currtime + timeout) - break; - } - while (err || !data[2]); - - if (err || !data[2]) - return -1; - - grub_dprintf ("usb_keyboard", - "report: 0x%02x 0x%02x 0x%02x 0x%02x" - " 0x%02x 0x%02x 0x%02x 0x%02x\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7]); - - /* Check if the Control or Shift key was pressed. */ - if (data[0] & 0x01 || data[0] & 0x10) - key = keyboard_map[data[2]] - 'a' + 1; - else if (data[0] & 0x02 || data[0] & 0x20) - key = keyboard_map_shift[data[2]]; - else - key = keyboard_map[data[2]]; - - if (key == 0) - grub_printf ("Unknown key 0x%x detected\n", data[2]); - -#if 0 - /* Wait until the key is released. */ - while (!err && data[2]) - { - err = grub_usb_control_msg (usbdev, USB_HID_DEVICE_TO_HOST, - USB_HID_GET_REPORT, 0, 0, - sizeof (data), (char *) data); - grub_dprintf ("usb_keyboard", - "report2: 0x%02x 0x%02x 0x%02x 0x%02x" - " 0x%02x 0x%02x 0x%02x 0x%02x\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7]); - } -#endif - - grub_errno = GRUB_ERR_NONE; - - return key; -} - -typedef enum -{ - GRUB_HIDBOOT_REPEAT_NONE, - GRUB_HIDBOOT_REPEAT_FIRST, - GRUB_HIDBOOT_REPEAT -} grub_usb_keyboard_repeat_t; - -static int -grub_usb_keyboard_getkey (struct grub_term_input *term) -{ - int key; - grub_err_t err; - grub_uint8_t data[8]; - grub_uint64_t currtime; - int timeout; - static grub_usb_keyboard_repeat_t repeat = GRUB_HIDBOOT_REPEAT_NONE; - - again: - - do - { - key = grub_usb_keyboard_checkkey (term); - } while (key == -1); - - data[2] = !0; /* Or whatever. */ - err = 0; - - switch (repeat) - { - case GRUB_HIDBOOT_REPEAT_FIRST: - timeout = 500; - break; - case GRUB_HIDBOOT_REPEAT: - timeout = 50; - break; - default: - timeout = 100; - break; - } - - /* Wait until the key is released. */ - currtime = grub_get_time_ms (); - while (!err && data[2]) - { - /* Implement a timeout. */ - if (grub_get_time_ms () > currtime + timeout) - { - if (repeat == 0) - repeat = 1; - else - repeat = 2; - - grub_errno = GRUB_ERR_NONE; - return key; - } - - err = grub_usb_keyboard_getreport (usbdev, data); - } - - if (repeat) - { - repeat = 0; - goto again; - } - - repeat = 0; - - grub_errno = GRUB_ERR_NONE; - - return key; -} - -static int -grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) -{ - grub_uint8_t data[8]; - int mods = 0; - grub_err_t err; - grub_uint64_t currtime; - int timeout = 50; - - /* Set idle time to the minimum offered by the spec (4 milliseconds) so - that we can find out the current state. */ - grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE, - 0<<8, 0, 0, 0); - - currtime = grub_get_time_ms (); - do - { - /* Get_Report. */ - err = grub_usb_keyboard_getreport (usbdev, data); - - /* Implement a timeout. */ - if (grub_get_time_ms () > currtime + timeout) - break; - } - while (err || !data[0]); - - /* Go back to reporting every time an event occurs and not more often than - that. */ - grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE, - 0<<8, 0, 0, 0); - - /* We allowed a while for modifiers to show up in the report, but it is - not an error if they never did. */ - if (err) - return -1; - - grub_dprintf ("usb_keyboard", - "report: 0x%02x 0x%02x 0x%02x 0x%02x" - " 0x%02x 0x%02x 0x%02x 0x%02x\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7]); - - /* Check Shift, Control, and Alt status. */ - if (data[0] & 0x02 || data[0] & 0x20) - mods |= GRUB_TERM_STATUS_SHIFT; - if (data[0] & 0x01 || data[0] & 0x10) - mods |= GRUB_TERM_STATUS_CTRL; - if (data[0] & 0x04 || data[0] & 0x40) - mods |= GRUB_TERM_STATUS_ALT; - - grub_errno = GRUB_ERR_NONE; - - return mods; -} - -static struct grub_term_input grub_usb_keyboard_term = - { - .name = "usb_keyboard", - .checkkey = grub_usb_keyboard_checkkey, - .getkey = grub_usb_keyboard_getkey, - .getkeystatus = grub_usb_keyboard_getkeystatus, - .next = 0 - }; - -GRUB_MOD_INIT(usb_keyboard) -{ - grub_usb_hid (); - grub_term_register_input ("usb_keyboard", &grub_usb_keyboard_term); -} - -GRUB_MOD_FINI(usb_keyboard) -{ - grub_term_unregister_input (&grub_usb_keyboard_term); -} diff --git a/tests/grub_cmd_echo.in b/tests/grub_cmd_echo.in new file mode 100644 index 000000000..902696778 --- /dev/null +++ b/tests/grub_cmd_echo.in @@ -0,0 +1,41 @@ +#! @builddir@/grub-shell-tester +# +# 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 . + +echo +echo -n + +echo foo +echo foo bar + +echo -n foo + +echo -e "foo\nbar" + +echo -n -e "foo\nbar" + +echo foo -n +echo foo -n -e + +echo ------- + +if test -n "$grubshell"; then insmod regexp; fi + +echo '*' +echo "*" + +foo="*" +echo "$foo" diff --git a/tests/grub_cmd_regexp.in b/tests/grub_cmd_regexp.in new file mode 100644 index 000000000..43b479fec --- /dev/null +++ b/tests/grub_cmd_regexp.in @@ -0,0 +1,41 @@ +#! /bin/bash -e + +# Run GRUB script in a Qemu instance +# 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 . + +cmd='regexp -s version "vm-(.*)" vm-1.2.3; echo $version' +v=`echo "$cmd" | @builddir@/grub-shell` +if test "$v" != 1.2.3; then echo "error: $cmd" >&2; exit 1; fi + +cmd='regexp -s 1:version "vm-(.*)" vm-1.2.3; echo $version' +v=`echo "$cmd" | @builddir@/grub-shell` +if test "$v" != 1.2.3; then echo "error: $cmd" >&2; exit 1; fi + +cmd='regexp -s 0:match "vm-(.*)" vm-1.2.3; echo $match' +v=`echo "$cmd" | @builddir@/grub-shell` +if test "$v" != vm-1.2.3; then echo "error: $cmd" >&2; exit 1; fi + +cmd='regexp -s 2:match "vm-(.*)" vm-1.2.3; echo $match' +v=`echo "$cmd" | @builddir@/grub-shell` +if test -n "$v"; then echo "error: $cmd" >&2; exit 1; fi + +cmd='regexp -s match "\\\((.*)\\\)" (hd0,msdos1); echo $match' +v=`echo "$cmd" | @builddir@/grub-shell` +if test "$v" != "hd0,msdos1"; then echo "error: $cmd" >&2; exit 1; fi + +cmd='regexp -s match "hd([0-9]+)" hd0; echo $match' +v=`echo "$cmd" | @builddir@/grub-shell` +if test "$v" != "0"; then echo "error: $cmd" >&2; exit 1; fi diff --git a/tests/grub_script_blockarg.in b/tests/grub_script_blockarg.in new file mode 100644 index 000000000..2765b61ac --- /dev/null +++ b/tests/grub_script_blockarg.in @@ -0,0 +1,41 @@ +#! /bin/bash + +# Run GRUB script in a Qemu instance +# 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 . + +error_if_not () { + if test "$1" != "$2"; then + echo "[$1]" != "[$2]" + exit 1 + fi +} + +cmd='test_blockarg { true }' +v=`echo "$cmd" | @builddir@/grub-shell` +error_if_not "$v" '{ true }' + +tmp=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 +cmd='test_blockarg { test_blockarg { true } }' +echo "$cmd" | @builddir@/grub-shell >$tmp +error_if_not "`head -n1 $tmp|tail -n1`" '{ test_blockarg { true } }' +error_if_not "`head -n2 $tmp|tail -n1`" '{ true }' + +cmd='test_blockarg { test_blockarg { test_blockarg { true } }; test_blockarg { true } }' +echo "$cmd" | @builddir@/grub-shell >$tmp +error_if_not "`head -n1 $tmp|tail -n1`" '{ test_blockarg { test_blockarg { true } }; test_blockarg { true } }' +error_if_not "`head -n2 $tmp|tail -n1`" '{ test_blockarg { true } }' +error_if_not "`head -n3 $tmp|tail -n1`" '{ true }' +error_if_not "`head -n4 $tmp|tail -n1`" '{ true }' diff --git a/tests/grub_script_break.in b/tests/grub_script_break.in new file mode 100644 index 000000000..bf265e8b3 --- /dev/null +++ b/tests/grub_script_break.in @@ -0,0 +1,86 @@ +#! @builddir@/grub-shell-tester +# +# 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 . + +# break without any arguments +for i in 1 2 3 4 5 6 7 8 9 10 +do + echo $i + if test "$i" = 5 + then + break + fi +done + +# break with one +for i in 1 2 3 4 5 6 7 8 9 10 +do + echo $i + if test "$i" = 5 + then + break 1 + fi +done + +# break with loop count +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + echo "$i $j" + if test "$i" = 3 + then + if test "$j" = d + then + break 2 + fi + fi + done +done + +# break into middle loop +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + echo "$i $j" + if test "$i" = 3 + then + if test "$j" = d + then + break 1 + fi + fi + done +done + +# while and until loops +a= +while test "$a" != "aaaaaaa" +do + a="a$a" + for i in 1 2 3 4 + do + b= + until test "$b" = "bbbbb" + do + b="b$b" + echo "$a $i $b" + if test "$i" = 3; then echo "break 2"; break 2; fi + done + done +done + diff --git a/tests/grub_script_continue.in b/tests/grub_script_continue.in new file mode 100644 index 000000000..4c28ce404 --- /dev/null +++ b/tests/grub_script_continue.in @@ -0,0 +1,86 @@ +#! @builddir@/grub-shell-tester +# +# 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 . + +# continue without any arguments +for i in 1 2 3 4 5 6 7 8 9 10 +do + if test "$i" = 5 + then + continue + fi + echo $i +done + +# continue with one +for i in 1 2 3 4 5 6 7 8 9 10 +do + if test "$i" = 5 + then + continue 1 + fi + echo $i +done + +# continue with loop count +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + if test "$i" = 3 + then + if test "$j" = d + then + continue 2 + fi + echo "$i $j" + fi + done +done + +# continue into middle loop +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + if test "$i" = 3 + then + if test "$j" = d + then + continue 1 + fi + echo "$i $j" + fi + done +done + +# while and until loops +a= +while test "$a" != "aaaaaaa" +do + a="a$a" + for i in 1 2 3 4 + do + b= + until test "$b" = "bbbbb" + do + b="b$b" + if test "$i" = 3; then echo "continue 2"; continue 2; fi + echo "$a $i $b" + done + done +done + diff --git a/tests/grub_script_echo1.in b/tests/grub_script_echo1.in index 048907a76..9415a3f73 100644 --- a/tests/grub_script_echo1.in +++ b/tests/grub_script_echo1.in @@ -16,6 +16,33 @@ # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . +# simple arguments +echo one two three +echo "one two three" +echo 'one two three' + +# empty arguments +echo a "" b +echo a '' b + +echo a $foo b +echo a ${foo} b + +echo a "$foo" b +echo a "${foo}" b + +# multi-part arguments +echo one"two"three +echo one${two}three +echo one"two"$three + +echo one'two'three +echo one${two}three +echo one'two'$three + +echo one'two'three"four"five${six}seven$eight + + foo=bar echo $foo ${foo} echo "$foo" "${foo}" @@ -30,3 +57,45 @@ e"$foo"${bar}o hello world foo=echo $foo 1234 + +echo "one +" +echo "one +\"" +echo "one +two" + +echo one"two +"three +echo one"two +\""three +echo one"two +\"three\" +four" + + +echo 'one +' +echo 'one +\' +echo 'one +two' +echo one'two +' +echo one'two +\' +echo one'two +\'three + +# echo "one\ +# two" +# echo 'one\ +# two' +# echo foo\ +# bar +# \ +# echo foo +# echo "one +# +# two" + diff --git a/tests/grub_script_expansion.in b/tests/grub_script_expansion.in new file mode 100644 index 000000000..d1e8d55c9 --- /dev/null +++ b/tests/grub_script_expansion.in @@ -0,0 +1,42 @@ +#! /bin/bash -e + +# Run GRUB script in a Qemu instance +# 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 . + +disks=`echo ls | @builddir@/grub-shell` +other=`echo insmod regexp\; echo \* | @builddir@/grub-shell` +for d in $disks; do + if echo "$d" |grep ',' >/dev/null; then + if echo "$other" | grep "$d" >/dev/null; then + echo "$d should not occur in * expansion" >&2 + exit 1 + fi + else + if ! echo "$other" | grep "$d" >/dev/null; then + echo "$d missing from * expansion" >&2 + exit 1 + fi + fi +done + +other=`echo insmod regexp\; echo '(*)' | @builddir@/grub-shell` +for d in $disks; do + if ! echo "$other" | grep "$d" >/dev/null; then + echo "$d missing from (*) expansion" >&2 + exit 1 + fi +done + diff --git a/tests/grub_script_functions.in b/tests/grub_script_functions.in new file mode 100644 index 000000000..3e69014d6 --- /dev/null +++ b/tests/grub_script_functions.in @@ -0,0 +1,147 @@ +#! @builddir@/grub-shell-tester + +# Run GRUB script in a Qemu instance +# 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 . + +echo parameter count +function fcount { + echo fcount "$#" +} + +fcount +fcount a +fcount a b + +echo parameter count, with nesting +function ffcount { + echo ffcount "$#" + fcount + fcount a + fcount a b +} + +ffcount +ffcount 1 +ffcount 1 2 + +echo parameters +function fparam { + echo fparam 1 $1 + echo fparam 2 $2 + echo fparam 3 $3 +} + +fparam +fparam a +fparam a b + +echo parameters, with nesting +function ffparam { + echo ffparam 1 $1 + echo ffparam 2 $2 + echo ffparam 3 $3 + fparam + fparam a + fparam a b +} + +ffparam +ffparam 1 +ffparam 1 2 + +echo parameter expansion with specials +function fstar { + for f in $* + do + echo fstar $f + done + + for f in aaa$*bbb + do + echo fstar $f + done +} + +fstar +fstar a +fstar a "1 2" +fstar a "1 2" b + +function fdqstar { + for f in "$*" + do + echo fdqstar $f + done + + for f in aaa"$*"bbb + do + echo fdqstar $f + done + + for f in "aaa$*bbb" + do + echo fdqstar $f + done +} + +fdqstar +fdqstar a +fdqstar a "1 2" +fdqstar a "1 2" b + +function fat { + for f in $@ + do + echo fat $f + done + + for f in aaa$@bbb + do + echo fat $f + done +} + +fat +fat a +fat a "1 2" +fat a "1 2" b +fat a "1 2" b "c d" +fat a "1 2" b "c d" e + +function fdqat { + for f in "$@" + do + echo fdqat $f + done + + for f in aaa"$@"bbb + do + echo fdqat $f + done + + for f in "aaa$@bbb" + do + echo fdqat $f + done +} + +# fdqat # this case needs special handling, lets ignore till we really need it. +fdqat a +fdqat a "1 2" +fdqat a "1 2" b +fdqat a "1 2" b "c d" +fdqat a "1 2" b "c d" e + diff --git a/tests/grub_script_not.in b/tests/grub_script_not.in new file mode 100644 index 000000000..ff71039a6 --- /dev/null +++ b/tests/grub_script_not.in @@ -0,0 +1,62 @@ +#! @builddir@/grub-shell-tester +# +# 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 . + +true +echo $? + +! true +echo $? + +false +echo $? + +! false +echo $? + +# +# Negated forms (copied from grub_script_if.in) +# + +#basic if, execute +if ! true; then echo yes; fi + +#basic if, no execution +if ! false; then echo no; fi + +#if else, execute if path +if ! true; then echo yes; else echo no; fi + +#if else, execute else path +if ! false; then echo no; else echo yes; fi + +#if elif, execute elif +if ! false; then echo no; elif ! true; then echo yes; fi + +#if elif else, execute else +if ! false; then echo no; elif ! false; then echo no; else echo yes; fi + +#if elif(1) elif(2), execute elif(2) +if false; then echo no; elif ! false; then echo no; elif ! true; then echo yes; fi + +#if elif(1) elif(2) else, execute else +if false; then echo no; elif false; then echo no; elif ! false; then echo no; else echo yes; fi + +#if {if elif else}, execute elif +if true; then if false; then echo no; elif ! true; then echo yes; else echo no; fi; fi + +#if {if elif} else, execute elif. ofcourse no dangling-else problem due to "fi" +if true; then if ! false; then echo no; elif true; then echo yes; fi; else echo no; fi diff --git a/tests/grub_script_return.in b/tests/grub_script_return.in new file mode 100644 index 000000000..712d1dfcf --- /dev/null +++ b/tests/grub_script_return.in @@ -0,0 +1,134 @@ +#! @builddir@/grub-shell-tester + +# Run GRUB script in a Qemu instance +# 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 f1 { + return + echo one +} +f1 + +function f2 { + true + return + echo one +} +if f2; then echo true; else echo false; fi + +function f3 { + false + return + echo one +} +if f3; then echo true; else echo false; fi + +function f4 { + true + return 1; + echo one +} +if f4; then echo true; else echo false; fi + +function f5 { + false + return 0; + echo one +} +if f5; then echo true; else echo false; fi + +function f6 { + echo one + if true; then + echo two + return 0 + else + echo three + return 1 + fi + echo four +} +if f6; then echo true; else echo false; fi + +function f7 { + if return 1; then + echo one + else + echo no + fi +} +if f7; then echo true; else echo false; fi + +function f8 { + echo one + for v in 1 2 3 4 5; do + echo $v + if test $v = 3; then return 1; fi + done + echo two +} +if f8; then echo true; else echo false; fi + +function f9 { + x=1 + echo one + until test x = 11111111; do + echo $x + x="1$x" + if test $x = 1111; then return 0; fi + done + echo two +} +if f9; then echo true; else echo false; fi + +function f10 { + echo one + while return 0; do + echo two + done + echo three +} +if f10; then echo true; else echo false; fi + +function f11 { + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 +} +if f11; then echo true; else echo false; fi + +function f12 { + echo one + f11 + return 1 + echo two +} +if f12; then echo true; else echo false; fi + +function f13 { + echo one + f12 + echo two + return 0 +} +if f13; then echo true; else echo false; fi diff --git a/tests/grub_script_setparams.in b/tests/grub_script_setparams.in new file mode 100644 index 000000000..82d316813 --- /dev/null +++ b/tests/grub_script_setparams.in @@ -0,0 +1,59 @@ +#! @builddir@/grub-shell-tester + +# Run GRUB script in a Qemu instance +# 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 . + +if test x$grubshell = xyes; then cmd=setparams; else cmd=set; fi + +function f1 { + echo $# + echo "$#" + + echo $@ + echo "$@" + + echo $* + echo "$*" + + echo $1 $2 + for v in "$@"; do echo $v; done + shift + echo $1 $2 + for v in "$@"; do echo $v; done + + $cmd 1 2 3 4 + + echo $# + echo "$#" + + echo $@ + echo "$@" + + echo $* + echo "$*" + + echo $1 $2 + for v in "$@"; do echo $v; done + shift + echo $1 $2 + for v in "$@"; do echo $v; done +} +# f1 +# f1 a +f1 a b +f1 a b c +f1 a b c d +f1 a b c d e diff --git a/tests/grub_script_shift.in b/tests/grub_script_shift.in new file mode 100644 index 000000000..785b9c396 --- /dev/null +++ b/tests/grub_script_shift.in @@ -0,0 +1,85 @@ +#! @builddir@/grub-shell-tester + +# Run GRUB script in a Qemu instance +# 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 f1 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f1 $# $1 $2 $3 + shift + echo f1 '$@' $@ + echo f1 '$*' $* + echo f1 $# $1 $2 $3 +} + +f1 +f1 a +f1 a b +f1 a b c +f1 a b c d +f1 a b c d e + +function f2 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f2 $# $1 $2 $3 + shift 1 + echo f1 '$@' $@ + echo f1 '$*' $* + echo f2 $# $1 $2 $3 +} + +f2 +f2 a +f2 a b +f2 a b c +f2 a b c d +f2 a b c d e + +function f3 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f3 $# $1 $2 $3 + shift 3 + echo f1 '$@' $@ + echo f1 '$*' $* + echo f3 $# $1 $2 $3 +} + +f3 +f3 a +f3 a b +f3 a b c +f3 a b c d +f3 a b c d e + +function f4 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f4 $# $1 $2 $3 + shift 100 + echo f1 '$@' $@ + echo f1 '$*' $* + echo f4 $# $1 $2 $3 +} + +f4 +f4 a +f4 a b +f4 a b c +f4 a b c d +f4 a b c d e diff --git a/tests/grub_script_vars1.in b/tests/grub_script_vars1.in index 9ff897627..77b3cf298 100644 --- a/tests/grub_script_vars1.in +++ b/tests/grub_script_vars1.in @@ -28,7 +28,7 @@ foo=foo echo "" $foo echo $bar $foo - + bar="" echo $bar $foo diff --git a/tests/lib/unit_test.c b/tests/lib/unit_test.c index e8b97b1f4..a780d6862 100644 --- a/tests/lib/unit_test.c +++ b/tests/lib/unit_test.c @@ -23,7 +23,6 @@ #include #include -#include int main (int argc __attribute__ ((unused)), @@ -44,62 +43,3 @@ main (int argc __attribute__ ((unused)), exit (status); } - -/* Other misc. functions necessary for successful linking. */ - -void -grub_free (void *ptr) -{ - free (ptr); -} - -char * -grub_env_get (const char *name __attribute__ ((unused))) -{ - return NULL; -} - -grub_err_t -grub_error (grub_err_t n, const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - vfprintf (stderr, fmt, ap); - va_end (ap); - - return n; -} - -void * -grub_malloc (grub_size_t size) -{ - return malloc (size); -} - -void -grub_refresh (void) -{ - fflush (stdout); -} - -void -grub_putchar (int c) -{ - putchar (c); -} - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_exit (void) -{ - exit (1); -} - -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; diff --git a/tests/partmap_test.in b/tests/partmap_test.in new file mode 100644 index 000000000..5a9c1a93d --- /dev/null +++ b/tests/partmap_test.in @@ -0,0 +1,274 @@ +#! /bin/sh -e +# +# 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 . + +parted=/sbin/parted +grubshell=@builddir@/grub-shell + +create_disk_image () { + name=$1 + size=$2 + qemu-img create ${name} ${size} >/dev/null +} + +check_output () { + outfile=$1 + shift + + for disk in $@; do + if ! grep "($disk)" ${outfile} >/dev/null + then + echo "($disk): disk/partiton not found" + exit 1 + fi + done +} + +list_parts () { + mod=$1; + shift; + imgfile=$1 + shift + outfile=$1 + shift + + echo ls | ${grubshell} --boot=cd --qemu-opts="-hda ${imgfile}" \ + --modules=$mod | tr -d "\n\r" > ${outfile} + cat ${outfile} + echo +} + +imgfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 +outfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 + +# +# MSDOS partition types +# + +echo "Checking MSDOS partition types..." + +# 0 primary +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel msdos +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 primary +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 + +# 2 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 + +# 3 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart primary 20M 30M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 hd0,msdos3 + +# 4 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart primary 20M 30M mkpart primary 30M 40M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 hd0,msdos3 hd0,msdos4 + +# 1 primary, 1 extended +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 + +# 1 primary, 1 extended, 1 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 + +# 1 primary, 1 extended, 2 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 + +# 1 primary, 1 extended, 3 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M mkpart logical 40M 50M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 hd0,msdos7 + +# 1 primary, 1 extended, 4 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M mkpart logical 40M 50M mkpart logical 50M 60M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 hd0,msdos7 hd0,msdos8 + + +# +# GPT partition types +# + +echo "Checking GPT partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel gpt +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 4 20M 30M mkpart 5 30M 40M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M mkpart 4 30M 40M mkpart 5 40M 50M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 hd0,gpt5 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M mkpart 4 30M 40M mkpart 5 40M 50M mkpart 6 50M 60M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 hd0,gpt5 hd0,gpt6 + + +# +# SUN partition types +# +# It seems partition #3 is reserved for whole disk by parted. +# + +echo "Checking SUN partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel sun +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M mkpart 40M 50M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 hd0,sun6 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M mkpart 40M 50M mkpart 50M 60M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 hd0,sun6 hd0,sun7 + + +# +# Apple partition types +# +# Partition table itself is part of some partition, so there is always +# a partition by default. But I don't understand why GRUB displays +# two partitions by default :-( +# + +echo "Checking APPLE partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel mac +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple3 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple3 hd0,apple4 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M mkpart e 40M 50M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 hd0,apple7 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M mkpart e 40M 50M mkpart f 50M 60M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 hd0,apple7 hd0,apple8 diff --git a/tests/util/grub-shell-tester.in b/tests/util/grub-shell-tester.in index ed34a5e17..02e49d3a4 100644 --- a/tests/util/grub-shell-tester.in +++ b/tests/util/grub-shell-tester.in @@ -83,17 +83,17 @@ for option in "$@"; do done if [ "x${source}" = x ] ; then - tmpfile=`mktemp` + tmpfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 while read REPLY; do echo $REPLY >> ${tmpfile} done source=${tmpfile} fi -outfile1=`mktemp` +outfile1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 @builddir@/grub-shell --qemu-opts="${qemuopts}" --modules=${modules} ${source} >${outfile1} -outfile2=`mktemp` +outfile2=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 bash ${source} >${outfile2} if ! diff -q ${outfile1} ${outfile2} >/dev/null diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in index 2cd256131..fc14ca7b0 100644 --- a/tests/util/grub-shell.in +++ b/tests/util/grub-shell.in @@ -28,6 +28,7 @@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ +platform=@platform@ # Force build directory components PATH=${builddir}:$PATH @@ -42,9 +43,11 @@ Run GRUB script in a Qemu instance. -h, --help print this message and exit -v, --version print the version information and exit - --boot=[fd|hd|cd] boot method for Qemu instance + --boot=[fd|hd|cd|net] boot method for Qemu instance --modules=MODULES pre-load specified modules MODULES + --qemu=FILE Name of qemu binary --qemu-opts=OPTIONS extra options to pass to Qemu instance + --files=FILES add files to the image $0 runs input GRUB script or SOURCE file in a Qemu instance and prints its output. @@ -53,6 +56,9 @@ Report bugs to . EOF } +boot=hd +qemu=qemu-system-i386 + # Check the arguments. for option in "$@"; do case "$option" in @@ -65,14 +71,22 @@ for option in "$@"; do --modules=*) ms=`echo "$option" | sed -e 's/--modules=//' -e 's/,/ /g'` modules="$modules $ms" ;; + --files=*) + fls=`echo "$option" | sed -e 's/--files=//' -e 's/,/ /g'` + files="$files $fls" ;; + --qemu=*) + qemu=`echo "$option" | sed -e 's/--qemu=//' -e 's/,/ /g'`;; --qemu-opts=*) qs=`echo "$option" | sed -e 's/--qemu-opts=//'` qemuopts="$qemuopts $qs" ;; --boot=*) dev=`echo "$option" | sed -e 's/--boot=//'` - if [ "$dev" = "fd" ] ; then bootdev=a; - elif [ "$dev" = "hd" ] ; then bootdev=c; - elif [ "$dev" = "cd" ] ; then bootdev=d; + if [ "$dev" = "fd" ] ; then boot=fd; + elif [ "$dev" = "hd" ] ; then boot=hd; + elif [ "$dev" = "cd" ] ; then boot=cd; + elif [ "$dev" = "net" ] ; then boot=net; + elif [ "$dev" = "qemu" ] ; then boot=qemu; + elif [ "$dev" = "coreboot" ] ; then boot=coreboot; else echo "Unrecognized boot method \`$dev'" 1>&2 usage @@ -93,18 +107,14 @@ for option in "$@"; do done if [ "x${source}" = x ] ; then - tmpfile=`mktemp` + tmpfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 while read REPLY; do - echo $REPLY >> ${tmpfile} + echo "$REPLY" >> ${tmpfile} done source=${tmpfile} fi -if [ "x${bootdev}" = x ] ; then - bootdev=c # default is boot as disk image -fi - -cfgfile=`mktemp` +cfgfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 cat <${cfgfile} grubshell=yes insmod serial @@ -113,6 +123,8 @@ terminal_input serial terminal_output serial EOF +rom_directory=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 + for mod in ${modules} do echo "insmod ${mod}" >> ${cfgfile} @@ -123,24 +135,55 @@ source /boot/grub/testcase.cfg halt EOF -isofile=`mktemp` -grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} \ - --override-directory=${builddir} \ - /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ - >/dev/null 2>&1 +isofile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 +if [ x$boot != xnet ]; then + sh @builddir@/grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} --override-directory=${builddir}/grub-core \ + --rom-directory="${rom_directory}" \ + /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ + ${files} >/dev/null 2>&1 +fi +if [ x$boot = xhd ]; then + device=hda + bootdev="-boot c" +fi +if [ x$boot = xcd ]; then + device=cdrom + bootdev="-boot d" +fi +if [ x$boot = xfd ]; then + device=fda + bootdev="-boot a" +fi -hdafile=`mktemp` -cp ${isofile} ${hdafile} +if [ x$boot = xqemu ]; then + bootdev="-bios ${rom_directory}/qemu.img" + device=cdrom +fi -fdafile=`mktemp` -cp ${isofile} ${fdafile} +if [ x$boot = xcoreboot ]; then + imgfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 + cp "${GRUB_COREBOOT_ROM}" "${imgfile}" + "${GRUB_CBFSTOOL}" "${imgfile}" add-payload "${rom_directory}/coreboot.elf" fallback/payload + bootdev="-bios ${imgfile}" + device=cdrom +fi -outfile=`mktemp` -qemu-system-i386 ${qemuopts} -nographic -hda ${hdafile} -fda ${fdafile} -cdrom ${isofile} -boot ${bootdev} | tr -d "\r" >${outfile} +if [ x$boot = xnet ]; then + netdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 + sh @builddir@/grub-mknetdir --grub-mkimage=${builddir}/grub-mkimage --override-directory=${builddir}/grub-core --net-directory=$netdir + cp ${cfgfile} $netdir/boot/grub/grub.cfg + cp ${source} $netdir/boot/grub/testcase.cfg + ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -boot n -net user,tftp=$netdir,bootfile=/boot/grub/$target_cpu-$platform/core.0 -net nic | cat | tr -d "\r" +else + ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" +fi +rm -f "${isofile}" "${imgfile}" +rm -rf "${rom_directory}" +if [ x$boot = xcoreboot ]; then + rm -f "${imgfile}" +fi -cat $outfile - -rm -f ${tmpfile} ${outfile} ${cfgfile} ${isofile} ${hdafile} ${fdafile} +rm -f "${tmpfile}" "${cfgfile}" exit 0 diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am new file mode 100644 index 000000000..136287cf1 --- /dev/null +++ b/util/bash-completion.d/Makefile.am @@ -0,0 +1,13 @@ + +bash_completion_source = grub-completion.bash.in +bash_completion_script = grub + +EXTRA_DIST = $(bash_completion_source) + +CLEANFILES = $(bash_completion_script) config.log + +bashcompletiondir = $(sysconfdir)/bash_completion.d +bashcompletion_DATA = $(bash_completion_script) + +$(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in new file mode 100644 index 000000000..65cbb80ee --- /dev/null +++ b/util/bash-completion.d/grub-completion.bash.in @@ -0,0 +1,489 @@ +# +# Bash completion for grub +# +# 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 . +# bash completion for grub + +__grub_dir() { + local i c=1 boot_dir + + for (( c=1; c <= ${#COMP_WORDS[@]}; c++ )); do + i="${COMP_WORDS[c]}" + case "$i" in + --boot-directory) + c=$((++c)) + i="${COMP_WORDS[c]}" + boot_dir="${i##*=}"; + break + ;; + esac + done + boot_dir=${boot_dir-/@bootdirname@} + echo "${boot_dir%/}/@grubdirname@" +} + + +# This function generates completion reply with compgen +# - arg: accepts 1, 2, 3, or 4 arguments +# $1 wordlist separate by space, tab or newline +# $2 (optional) prefix to add +# $3 (optional) current word to complete +# $4 (optional) suffix to add +__grubcomp () { + local cur="${COMP_WORDS[COMP_CWORD]}" + if [ $# -gt 2 ]; then + cur="$3" + fi + case "$cur" in + --*=) + COMPREPLY=() + ;; + *) + local IFS=' '$'\t'$'\n' + COMPREPLY=($(compgen -P "${2-}" -W "${1-}" -S "${4-}" -- "$cur")) + ;; + esac +} + +# Function that return long options from the help of the command +# - arg: $1 (optional) command to get the long options from +__grub_get_options_from_help () { + local prog + + if [ $# -ge 1 ]; then + prog="$1" + else + prog="${COMP_WORDS[0]}" + fi + + local i IFS=" "$'\t'$'\n' + for i in $(LC_ALL=C $prog --help) + do + case $i in + --*) echo "${i%=*}";; + esac + done +} + +# Function that return long options from the usage of the command +# - arg: $1 (optional) command to get the long options from +__grub_get_options_from_usage () { + local prog + + if [ $# -ge 1 ]; then + prog="$1" + else + prog="${COMP_WORDS[0]}" + fi + + local i IFS=" "$'\t'$'\n' + for i in $(LC_ALL=C $prog --usage) + do + case $i in + \[--*\]) i=${i#[} # Remove leading [ + echo ${i%%?(=*)]} # Remove optional value and trailing ] + ;; + esac + done +} + +__grub_get_last_option () { + local i + for (( i=$COMP_CWORD-1; i > 0; i-- )); do + if [[ "${COMP_WORDS[i]}" == -* ]]; then + echo "${COMP_WORDS[i]}" + break; + fi + done +} + +__grub_list_menuentries () { + local cur="${COMP_WORDS[COMP_CWORD]}" + local config_file=$(__grub_dir)/grub.cfg + + if [ -f "$config_file" ];then + local IFS=$'\n' + COMPREPLY=( $(compgen \ + -W "$( awk -F "[\"']" '/menuentry/ { print $2 }' $config_file )" \ + -- "$cur" )) #'# Help emacs syntax highlighting + fi +} + +__grub_list_modules () { + local grub_dir=$(__grub_dir) + local IFS=$'\n' + COMPREPLY=( $( compgen -f -X '!*/*.mod' -- "${grub_dir}/$cur" | { + while read -r tmp; do + [ -n $tmp ] && { + tmp=${tmp##*/} + printf '%s\n' ${tmp%.mod} + } + done + } + )) +} + +# +# grub-set-default & grub-reboot +# +_grub_set_entry () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + --boot-directory) + _filedir -d + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a menuentry + __grub_list_menuentries + fi +} + +__grub_set_default_program=$( echo grub-set-default | sed "@program_transform_name@" ) +have ${__grub_set_default_program} && \ + complete -F _grub_set_entry -o filenames ${__grub_set_default_program} +unset __grub_set_default_program + +__grub_reboot_program=$( echo grub-reboot | sed "@program_transform_name@" ) +have ${__grub_reboot_program} && \ + complete -F _grub_set_entry -o filenames ${__grub_reboot_program} +unset __grub_reboot_program + + +# +# grub-editenv +# +_grub_editenv () { + local cur prev + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + case "$prev" in + create|list|set|unset) + COMPREPLY=( "" ) + return + ;; + esac + + __grubcomp "$(__grub_get_options_from_help) + create list set unset" +} + +__grub_editenv_program=$( echo grub-editenv | sed "@program_transform_name@" ) +have ${__grub_editenv_program} && \ + complete -F _grub_editenv -o filenames ${__grub_editenv_program} +unset __grub_editenv_program + + +# +# grub-mkconfig +# +_grub_mkconfig () { + local cur prev + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + _filedir + fi +} +__grub_mkconfig_program=$( echo grub-mkconfig | sed "@program_transform_name@" ) +have ${__grub_mkconfig_program} && \ + complete -F _grub_mkconfig -o filenames ${__grub_mkconfig_program} +unset __grub_mkconfig_program + + +# +# grub-setup +# +_grub_setup () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -d|--directory) + _filedir -d + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_setup_program=$( echo grub-setup | sed "@program_transform_name@" ) +have ${__grub_setup_program} && \ + complete -F _grub_setup -o filenames ${__grub_setup_program} +unset __grub_setup_program + + +# +# grub-install +# +_grub_install () { + local cur prev last split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + last=$(__grub_get_last_option) + + _split_longopt && split=true + + case "$prev" in + --boot-directory) + _filedir -d + return + ;; + --disk-module) + __grubcomp "biosdisk ata" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + case "$last" in + --modules) + __grub_list_modules + return + ;; + esac + + # Default complete with a filename + _filedir + fi +} +__grub_install_program=$( echo grub-install | sed "@program_transform_name@" ) +have ${__grub_install_program} && \ + complete -F _grub_install -o filenames ${__grub_install_program} +unset __grub_install_program + + +# +# grub-mkfont +# +_grub_mkfont () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkfont_program=$( echo grub-mkfont | sed "@program_transform_name@" ) +have ${__grub_mkfont_program} && \ + complete -F _grub_mkfont -o filenames ${__grub_mkfont_program} +unset __grub_mkfont_program + + +# +# grub-mkrescue +# +_grub_mkrescue () { + local cur prev last + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + last=$(__grub_get_last_option) + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + case "$last" in + --modules) + __grub_list_modules + return + ;; + esac + + # Default complete with a filename + _filedir + fi +} +__grub_mkrescue_program=$( echo grub-mkrescue | sed "@program_transform_name@" ) +have ${__grub_mkrescue_program} && \ + complete -F _grub_mkrescue -o filenames ${__grub_mkrescue_program} +unset __grub_mkrescue_program + + +# +# grub-mkimage +# +_grub_mkimage () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -d|--directory|-p|--prefix) + _filedir -d + return + ;; + -O|--format) + # Get available format from help + local prog=${COMP_WORDS[0]} + __grubcomp "$(LC_ALL=C $prog --help | \ + awk -F ":" '/available formats/ { print $2 }' | \ + sed 's/, / /g')" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkimage_program=$( echo grub-mkimage | sed "@program_transform_name@" ) +have ${__grub_mkimage_program} && \ + complete -F _grub_mkimage -o filenames ${__grub_mkimage_program} +unset __grub_mkimage_program + + +# +# grub-mkpasswd-pbkdf2 +# +_grub_mkpasswd-pbkdf2 () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkpasswd_pbkdf2_program=$( echo grub-mkpasswd-pbkdf2 | sed "@program_transform_name@" ) +have ${__grub_mkpasswd_pbkdf2_program} && \ + complete -F _grub_mkpasswd-pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program} +unset __grub_mkpasswd_pbkdf2_program + + +# +# grub-probe +# +_grub_probe () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -t|--target) + # Get target type from help + local prog=${COMP_WORDS[0]} + __grubcomp "$(LC_ALL=C $prog --help | \ + awk -F "[()]" '/--target=/ { print $2 }' | \ + sed 's/|/ /g')" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_probe_program=$( echo grub-probe | sed "@program_transform_name@" ) +have ${__grub_probe_program} && \ + complete -F _grub_probe -o filenames ${__grub_probe_program} +unset __grub_probe_program + + +# +# grub-script-check +# +_grub_script-check () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_script_check_program=$( echo grub-script-check | sed "@program_transform_name@" ) +have ${__grub_script_check_program} && \ + complete -F _grub_script-check -o filenames ${__grub_script_check_program} + + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/util/bin2h.c b/util/bin2h.c index e81ede8c6..ee1c7fd32 100644 --- a/util/bin2h.c +++ b/util/bin2h.c @@ -96,7 +96,7 @@ main (int argc, char *argv[]) if (b == EOF) goto abort; - printf ("/* THIS CHUNK OF BYTES IS AUTOMATICALY GENERATED */\n" + printf ("/* THIS CHUNK OF BYTES IS AUTOMATICALLY GENERATED */\n" "unsigned char %s[] =\n{\n", sym); while (1) diff --git a/util/deviceiter.c b/util/deviceiter.c index 1cf511934..34d34b7bb 100644 --- a/util/deviceiter.c +++ b/util/deviceiter.c @@ -601,7 +601,7 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), #endif /* __linux__ */ /* IDE disks. */ - for (i = 0; i < 26; i++) + for (i = 0; i < 96; i++) { char name[16]; @@ -655,7 +655,7 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), #endif /* __linux__ */ /* The rest is SCSI disks. */ - for (i = 0; i < 26; i++) + for (i = 0; i < 48; i++) { char name[16]; diff --git a/util/grub-editenv.c b/util/grub-editenv.c index 2cef2b8a8..519945411 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -27,73 +28,84 @@ #include #include #include -#include +#include #include "progname.h" #define DEFAULT_ENVBLK_SIZE 1024 +#define DEFAULT_ENVBLK_PATH DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG -void -grub_refresh (void) +static struct argp_option options[] = { + {0, 0, 0, OPTION_DOC, N_("Commands:"), 1}, + {"create", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Create a blank environment block file."), 0}, + {"list", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("List the current variables."), 0}, + {"set [name=value ...]", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Set variables."), 0}, + {"unset [name ....]", 0, 0, OPTION_DOC|OPTION_NO_USAGE, + N_("Delete variables."), 0}, + + {0, 0, 0, OPTION_DOC, N_("Options:"), -1}, + {"verbose", 'v', 0, 0, N_("Print verbose messages."), 0}, + + { 0, 0, 0, 0, 0, 0 } +}; + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) { - fflush (stdout); + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); } +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; -int -grub_getkey (void) +/* Set the bug report address */ +const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; + +error_t argp_parser (int key, char *arg, struct argp_state *state) { + switch (key) + { + case 'v': + verbosity++; + break; + + case ARGP_KEY_NO_ARGS: + fprintf (stderr, "%s", + _("You need to specify at least one command.\n")); + argp_usage (state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; } -void -grub_xputs_real (const char *str) +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) { - fputs (str, stdout); + switch (key) + { + case ARGP_KEY_HELP_POST_DOC: + return xasprintf(text, DEFAULT_ENVBLK_PATH); + + default: + return (char *) text; + } } -void (*grub_xputs) (const char *str) = grub_xputs_real; - -char * -grub_env_get (const char *name __attribute__ ((unused))) -{ - return NULL; -} - -static struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} +struct argp argp = { + options, argp_parser, N_("FILENAME COMMAND"), + "\n"N_("\ +Tool to edit environment block.") +"\v"N_("\ +If FILENAME is '-', the default value %s is used."), + NULL, help_filter, NULL }; -static void -usage (int status) -{ - if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - printf ("\ -Usage: %s [OPTIONS] [FILENAME] COMMAND\n\ -\n\ -Tool to edit environment block.\n\ -\nCommands:\n\ - create create a blank environment block file\n\ - list list the current variables\n\ - set [name=value ...] set variables\n\ - unset [name ....] delete variables\n\ -\nOptions:\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -If not given explicitly, FILENAME defaults to %s.\n\ -\n\ -Report bugs to <%s>.\n", -program_name, DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT); - - exit (status); -} - static void create_envblk_file (const char *name) { @@ -252,55 +264,32 @@ main (int argc, char *argv[]) { char *filename; char *command; + int index, arg_count; set_program_name (argv[0]); grub_util_init_nls (); - /* Check for options. */ - while (1) + /* Parse our arguments */ + if (argp_parse (&argp, argc, argv, 0, &index, 0) != 0) { - int c = getopt_long (argc, argv, "hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } - /* Obtain the filename. */ - if (optind >= argc) - { - fprintf (stderr, "no filename specified\n"); - usage (1); - } + arg_count = argc - index; - if (optind + 1 >= argc) + if (arg_count == 1) { - filename = DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG; - command = argv[optind]; + filename = DEFAULT_ENVBLK_PATH; + command = argv[index++]; } else { - filename = argv[optind]; - command = argv[optind + 1]; + filename = argv[index++]; + if (strcmp (filename, "-") == 0) + filename = DEFAULT_ENVBLK_PATH; + command = argv[index++]; } if (strcmp (command, "create") == 0) @@ -308,13 +297,16 @@ main (int argc, char *argv[]) else if (strcmp (command, "list") == 0) list_variables (filename); else if (strcmp (command, "set") == 0) - set_variables (filename, argc - optind - 2, argv + optind + 2); + set_variables (filename, argc - index, argv + index); else if (strcmp (command, "unset") == 0) - unset_variables (filename, argc - optind - 2, argv + optind + 2); + unset_variables (filename, argc - index, argv + index); else { - fprintf (stderr, "unknown command %s\n", command); - usage (1); + char *program = xstrdup(program_name); + fprintf (stderr, _("Unknown command `%s'.\n"), command); + argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); + free(program); + exit(1); } return 0; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index f1692c0a3..2fcde4ab0 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -29,39 +30,17 @@ #include #include #include -#include +#include #include #include -#include - #include #include #include #include -#include #include "progname.h" - -void -grub_xputs_real (const char *str) -{ - fputs (str, stdout); -} - -void (*grub_xputs) (const char *str) = grub_xputs_real; - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_refresh (void) -{ - fflush (stdout); -} +#include "argp.h" static grub_err_t execute_command (char *name, int n, char **args) @@ -70,7 +49,7 @@ execute_command (char *name, int n, char **args) cmd = grub_command_find (name); if (! cmd) - grub_util_error ("can\'t find command %s", name); + grub_util_error (_("can\'t find command %s"), name); return (cmd->func) (cmd, n, args); } @@ -99,7 +78,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) dev = grub_device_open (0); if ((! dev) || (! dev->disk)) - grub_util_error ("can\'t open device"); + grub_util_error (_("can\'t open device")); grub_util_info ("total sectors : %lld", (unsigned long long) dev->disk->total_sectors); @@ -114,7 +93,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) len = (leng > BUF_SIZE) ? BUF_SIZE : leng; if (grub_disk_read (dev->disk, 0, skip, len, buf)) - grub_util_error ("disk read fails at offset %lld, length %d", + grub_util_error (_("disk read fails at offset %lld, length %d"), skip, len); if (hook (skip, buf, len)) @@ -128,10 +107,11 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) return; } + grub_file_filter_disable_compression (); file = grub_file_open (pathname); if (!file) { - grub_util_error ("cannot open file %s", pathname); + grub_util_error (_("cannot open file %s"), pathname); return; } @@ -139,7 +119,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) if (skip > file->size) { - grub_util_error ("invalid skip value %lld", (unsigned long long) skip); + grub_util_error (_("invalid skip value %lld"), (unsigned long long) skip); return; } @@ -157,7 +137,8 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len); if (sz < 0) { - grub_util_error ("read error at offset %llu", ofs); + grub_util_error (_("read error at offset %llu: %s"), ofs, + grub_errmsg); break; } @@ -183,7 +164,7 @@ cmd_cp (char *src, char *dest) if ((int) fwrite (buf, 1, len, ff) != len) { - grub_util_error ("write error"); + grub_util_error (_("write error")); return 1; } @@ -193,7 +174,7 @@ cmd_cp (char *src, char *dest) ff = fopen (dest, "wb"); if (ff == NULL) { - grub_util_error ("open error"); + grub_util_error (_("open error")); return; } read_file (src, cp_hook); @@ -211,7 +192,7 @@ cmd_cmp (char *src, char *dest) { if ((int) fread (buf_1, 1, len, ff) != len) { - grub_util_error ("read error at offset %llu", ofs); + grub_util_error (_("read error at offset %llu: %s"), ofs, grub_errmsg); return 1; } @@ -222,7 +203,7 @@ cmd_cmp (char *src, char *dest) for (i = 0; i < len; i++, ofs++) if (buf_1[i] != buf[i]) { - grub_util_error ("compare fail at offset %llu", ofs); + grub_util_error (_("compare fail at offset %llu"), ofs); return 1; } } @@ -232,12 +213,12 @@ cmd_cmp (char *src, char *dest) ff = fopen (dest, "rb"); if (ff == NULL) { - grub_util_error ("open error"); + grub_util_error (_("open error")); return; } if ((skip) && (fseeko (ff, skip, SEEK_SET))) - grub_util_error ("seek error"); + grub_util_error (_("seek error")); read_file (src, cmp_hook); fclose (ff); @@ -259,33 +240,43 @@ cmd_hex (char *pathname) static void cmd_crc (char *pathname) { - grub_uint32_t crc = 0; + grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + GRUB_MD_CRC32->init(crc32_context); auto int crc_hook (grub_off_t ofs, char *buf, int len); int crc_hook (grub_off_t ofs, char *buf, int len) { (void) ofs; - crc = grub_getcrc32 (crc, buf, len); + GRUB_MD_CRC32->write(crc32_context, buf, len); return 0; } read_file (pathname, crc_hook); - printf ("%08x\n", crc); + GRUB_MD_CRC32->final(crc32_context); + printf ("%08x\n", + grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context))); } +static char *root = NULL; +static int args_count = 0; +static int nparm = 0; +static int num_disks = 1; +static char **images = NULL; +static int cmd = 0; +static char *debug_str = NULL; +static char **args = NULL; + static void -fstest (char **images, int num_disks, int cmd, int n, char **args) +fstest (int n, char **args) { char *host_file; char *loop_name; - char *argv[3]; int i; - argv[0] = "-p"; - for (i = 0; i < num_disks; i++) { + char *argv[2]; loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) grub_util_error (grub_errmsg); @@ -294,21 +285,23 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) if (!host_file) grub_util_error (grub_errmsg); - argv[1] = loop_name; - argv[2] = host_file; + argv[0] = loop_name; + argv[1] = host_file; - if (execute_command ("loopback", 3, argv)) - grub_util_error ("loopback command fails"); + if (execute_command ("loopback", 2, argv)) + grub_util_error (_("loopback command fails")); grub_free (loop_name); grub_free (host_file); } grub_lvm_fini (); - grub_mdraid_fini (); + grub_mdraid09_fini (); + grub_mdraid1x_fini (); grub_raid_fini (); grub_raid_init (); - grub_mdraid_init (); + grub_mdraid09_init (); + grub_mdraid1x_init (); grub_lvm_init (); switch (cmd) @@ -332,15 +325,16 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) execute_command ("blocklist", n, args); grub_printf ("\n"); } - - argv[0] = "-d"; - + for (i = 0; i < num_disks; i++) { + char *argv[2]; + loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) grub_util_error (grub_errmsg); + argv[0] = "-d"; argv[1] = loop_name; execute_command ("loopback", 2, argv); @@ -349,203 +343,175 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) } } -static struct option options[] = { - {"root", required_argument, 0, 'r'}, - {"skip", required_argument, 0, 's'}, - {"length", required_argument, 0, 'n'}, - {"diskcount", required_argument, 0, 'c'}, - {"debug", required_argument, 0, 'd'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} +static struct argp_option options[] = { + {0, 0, 0 , OPTION_DOC, N_("Commands:"), 1}, + {N_("ls PATH"), 0, 0 , OPTION_DOC, N_("List files in PATH."), 1}, + {N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1}, + {N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1}, + {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Hex dump FILE."), 1}, + {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1}, + {N_("blocklist FILE"), 0, 0, OPTION_DOC, N_("Display blocklist of FILE."), 1}, + + {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, + {"skip", 's', "N", 0, N_("Skip N bytes from output file."), 2}, + {"length", 'n', "N", 0, N_("Handle N bytes in output file."), 2}, + {"diskcount", 'c', "N", 0, N_("N input files."), 2}, + {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, + {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, + {0, 0, 0, 0, 0, 0} }; +/* Print the version information. */ static void -usage (int status) +print_version (FILE *stream, struct argp_state *state) { - if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - printf ("\ -Usage: %s [OPTION]... IMAGE_PATH COMMANDS\n\ -\n\ -Debug tool for filesystem driver.\n\ -\nCommands:\n\ - ls PATH list files in PATH\n\ - cp FILE LOCAL copy FILE to local file LOCAL\n\ - cmp FILE LOCAL compare FILE with local file LOCAL\n\ - hex FILE Hex dump FILE\n\ - crc FILE Get crc32 checksum of FILE\n\ - blocklist FILE display blocklist of FILE\n\ -\nOptions:\n\ - -r, --root=DEVICE_NAME set root device\n\ - -s, --skip=N skip N bytes from output file\n\ - -n, --length=N handle N bytes in output file\n\ - -c, --diskcount=N N input files\n\ - -d, --debug=S Set debug environment variable\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); - - exit (status); + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); } +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; -int -main (int argc, char *argv[]) +error_t +argp_parser (int key, char *arg, struct argp_state *state) { - char *debug_str = NULL, *root = NULL, *default_root, *alloc_root; - int i, cmd, num_opts, image_index, num_disks = 1; + char *p; - set_program_name (argv[0]); + switch (key) + { + case 'r': + root = arg; + return 0; - grub_util_init_nls (); + case 's': + skip = grub_strtoul (arg, &p, 0); + if (*p == 's') + skip <<= GRUB_DISK_SECTOR_BITS; + return 0; - /* Find the first non option entry. */ - for (num_opts = 1; num_opts < argc; num_opts++) - if (argv[num_opts][0] == '-') - { - if ((argv[num_opts][2] == 0) && (num_opts < argc - 1) && - ((argv[num_opts][1] == 'r') || - (argv[num_opts][1] == 's') || - (argv[num_opts][1] == 'n') || - (argv[num_opts][1] == 'c') || - (argv[num_opts][1] == 'd'))) - num_opts++; - } - else + case 'n': + leng = grub_strtoul (arg, &p, 0); + if (*p == 's') + leng <<= GRUB_DISK_SECTOR_BITS; + return 0; + + case 'c': + num_disks = grub_strtoul (arg, NULL, 0); + if (num_disks < 1) + { + fprintf (stderr, "%s", _("Invalid disk count.\n")); + argp_usage (state); + } + if (args_count != 0) + { + fprintf (stderr, "%s", _("Disk count must precede disks list.\n")); + argp_usage (state); + } + return 0; + + case 'd': + debug_str = arg; + return 0; + + case 'v': + verbosity++; + return 0; + + case ARGP_KEY_END: + if (args_count < num_disks) + { + fprintf (stderr, "%s", _("No command is specified.\n")); + argp_usage (state); + } + if (args_count - 1 - num_disks < nparm) + { + fprintf (stderr, "%s", _("Not enough parameters to command.\n")); + argp_usage (state); + } + return 0; + + case ARGP_KEY_ARG: break; - /* Check for options. */ - while (1) - { - int c = getopt_long (num_opts, argv, "r:s:n:c:d:hVv", options, 0); - char *p; - - if (c == -1) - break; - else - switch (c) - { - case 'r': - root = optarg; - break; - - case 's': - skip = grub_strtoul (optarg, &p, 0); - if (*p == 's') - skip <<= GRUB_DISK_SECTOR_BITS; - break; - - case 'n': - leng = grub_strtoul (optarg, &p, 0); - if (*p == 's') - leng <<= GRUB_DISK_SECTOR_BITS; - break; - - case 'c': - num_disks = grub_strtoul (optarg, NULL, 0); - if (num_disks < 1) - { - fprintf (stderr, "Invalid disk count.\n"); - usage (1); - } - break; - - case 'd': - debug_str = optarg; - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } + default: + return ARGP_ERR_UNKNOWN; } - /* Obtain PATH. */ - if (optind + num_disks - 1 >= argc) + if (args_count < num_disks) { - fprintf (stderr, "Not enough pathname.\n"); - usage (1); + if (arg[0] != '/') + { + fprintf (stderr, "%s", _("Must use absolute path.\n")); + argp_usage (state); + } + if (args_count == 0) + images = xmalloc (num_disks * sizeof (images[0])); + images[args_count] = xstrdup (arg); + args_count++; + return 0; } - image_index = optind; - for (i = 0; i < num_disks; i++, optind++) - if (argv[optind][0] != '/') - { - fprintf (stderr, "Must use absolute path.\n"); - usage (1); - } - - cmd = 0; - if (optind < argc) + if (args_count == num_disks) { - int nparm = 0; - - if (!grub_strcmp (argv[optind], "ls")) + if (!grub_strcmp (arg, "ls")) { cmd = CMD_LS; } - else if (!grub_strcmp (argv[optind], "cp")) + else if (!grub_strcmp (arg, "cp")) { cmd = CMD_CP; nparm = 2; } - else if (!grub_strcmp (argv[optind], "cmp")) + else if (!grub_strcmp (arg, "cmp")) { cmd = CMD_CMP; nparm = 2; } - else if (!grub_strcmp (argv[optind], "hex")) + else if (!grub_strcmp (arg, "hex")) { cmd = CMD_HEX; nparm = 1; } - else if (!grub_strcmp (argv[optind], "crc")) + else if (!grub_strcmp (arg, "crc")) { cmd = CMD_CRC; nparm = 1; } - else if (!grub_strcmp (argv[optind], "blocklist")) + else if (!grub_strcmp (arg, "blocklist")) { cmd = CMD_BLOCKLIST; nparm = 1; } else { - fprintf (stderr, "Invalid command %s.\n", argv[optind]); - usage (1); + fprintf (stderr, _("Invalid command %s.\n"), arg); + argp_usage (state); } - - if (optind + 1 + nparm > argc) - { - fprintf (stderr, "Invalid parameter for command %s.\n", - argv[optind]); - usage (1); - } - - optind++; - } - else - { - fprintf (stderr, "No command is specified.\n"); - usage (1); + args_count++; + return 0; } + args[args_count - 1 - num_disks] = xstrdup (arg); + args_count++; + return 0; +} + +struct argp argp = { + options, argp_parser, N_("IMAGE_PATH COMMANDS"), + N_("Debug tool for filesystem driver."), + NULL, NULL, NULL +}; + +int +main (int argc, char *argv[]) +{ + char *default_root, *alloc_root; + + set_program_name (argv[0]); + + grub_util_init_nls (); + + args = xmalloc (argc * sizeof (args[0])); + + argp_parse (&argp, argc, argv, 0, 0, 0); + /* Initialize all modules. */ grub_init_all (); @@ -573,7 +539,7 @@ main (int argc, char *argv[]) free (alloc_root); /* Do it. */ - fstest (argv + image_index, num_disks, cmd, argc - optind, argv + optind); + fstest (args_count - 1 - num_disks, args); /* Free resources. */ grub_fini_all (); diff --git a/util/grub-install.in b/util/grub-install.in index 4a5b5a1c3..00ad3fde4 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -19,30 +19,32 @@ # Initialize some variables. transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +bindir="@bindir@" +libdir="@libdir@" +sysconfdir="@sysconfdir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ platform=@platform@ host_os=@host_os@ -font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2 -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` -localedir=@datadir@/locale +pkglibdir="${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`" +localedir="@datadir@/locale" -self=`basename $0` +self="`basename $0`" -grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` +grub_setup="${sbindir}/`echo grub-setup | sed ${transform}`" +grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" +grub_mkdevicemap="${sbindir}/`echo grub-mkdevicemap | sed ${transform}`" +grub_probe="${sbindir}/`echo grub-probe | sed ${transform}`" +grub_editenv="${bindir}/`echo grub-editenv | sed ${transform}`" +grub_mkrelpath="${bindir}/`echo grub-mkrelpath | sed ${transform}`" rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` +bootdir= +grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`" modules= install_device= @@ -52,9 +54,27 @@ recheck=no debug=no debug_image= +update_nvram=yes + +ofpathname="`which ofpathname`" +nvsetenv="`which nvsetenv`" +efibootmgr="`which efibootmgr 2>/dev/null || true`" +removable=no +efi_quiet= + +# Get GRUB_DISTRIBUTOR. +if test -f "${sysconfdir}/default/grub" ; then + . "${sysconfdir}/default/grub" +fi + +bootloader_id="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)" +if test -z "$bootloader_id"; then + bootloader_id=grub +fi + if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk -elif [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then +elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then disk_module= else disk_module=ata @@ -63,20 +83,32 @@ fi # Usage: usage # Print the usage. usage () { +if [ "${target_cpu}-${platform}" = "i386-pc" ] \ + || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then cat <. EOF } argument () { - opt=$1 + opt="$1" shift if test $# -eq 0; then echo "$0: option requires an argument -- '$opt'" 1>&2 exit 1 fi - echo $1 + echo "$1" } +allow_floppy="" + # Check the arguments. while test $# -gt 0 do @@ -134,57 +171,82 @@ do --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; +# Accept and ignore for compatibility --font) - font=`argument $option "$@"`; shift;; + shift;; --font=*) - font=`echo "$option" | sed 's/--font=//'` ;; + ;; +# Accept for compatibility --root-directory) - rootdir=`argument $option "$@"`; shift;; + rootdir="`argument $option "$@"`"; shift;; --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + rootdir="`echo "$option" | sed 's/--root-directory=//'`" ;; + + --boot-directory) + bootdir="`argument $option "$@"`"; shift;; + --boot-directory=*) + bootdir="`echo "$option" | sed 's/--boot-directory=//'`" ;; --grub-setup) - grub_setup=`argument $option "$@"`; shift;; + grub_setup="`argument "$option" "$@"`"; shift;; --grub-setup=*) - grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;; + grub_setup="`echo "$option" | sed 's/--grub-setup=//'`" ;; + + --bootloader-id) + bootloader_id="`argument $option "$@"`"; shift;; + --bootloader-id=*) + bootloader_id="`echo "$option" | sed 's/--bootloader-id=//'`" ;; --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift;; + grub_mkimage="`argument $option "$@"`"; shift;; --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + grub_mkimage="`echo "$option" | sed 's/--grub-mkimage=//'`" ;; + + --grub-mkrelpath) + grub_mkrelpath="`argument "$option" "$@"`"; shift;; + --grub-mkimage=*) + grub_mkrelpath="`echo "$option" | sed 's/--grub-mkrelpath=//'`" ;; --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift;; + grub_mkdevicemap="`argument "$option" "$@"`"; shift;; --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; + grub_mkdevicemap="`echo "$option" | sed 's/--grub-mkdevicemap=//'`" ;; --grub-probe) - grub_probe=`argument $option "$@"`; shift;; + grub_probe="`argument "$option" "$@"`"; shift;; --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; + grub_probe="`echo "$option" | sed 's/--grub-probe=//'`" ;; --no-floppy) no_floppy="--no-floppy" ;; --recheck) recheck=yes ;; + --removable) + removable=yes ;; + + --allow-floppy) + allow_floppy="--allow-floppy" ;; --disk-module) if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then - disk_module=`argument $option "$@"`; shift; + disk_module="`argument "$option" "$@"`"; shift; fi ;; --disk-module=*) if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then - disk_module=`echo "$option" | sed 's/--disk-module=//'` + disk_module="`echo "$option" | sed 's/--disk-module=//'`" fi ;; + --no-nvram) + update_nvram=no ;; + # This is an undocumented feature... --debug) debug=yes ;; --debug-image) - debug_image=`argument $option "$@"`; shift;; + debug_image="`argument "$option" "$@"`"; shift;; --debug-image=*) - debug_image=`echo "$option" | sed 's/--debug-image=//'` ;; + debug_image="`echo "$option" | sed 's/--debug-image=//'`" ;; -f | --force) setup_force="--force" ;; @@ -204,10 +266,8 @@ do esac done -# for make_system_path_relative_to_its_root() -. ${libdir}/grub/grub-mkconfig_lib - -if test "x$install_device" = x && test "${target_cpu}-${platform}" != "mips-yeeloong"; then +if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \ + || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then echo "install_device not specified." 1>&2 usage exit 1 @@ -215,29 +275,25 @@ fi # If the debugging feature is enabled, print commands. setup_verbose= -if test $debug = yes; then +if test x"$debug" = xyes; then set -x setup_verbose="--verbose" + efi_quiet=-q fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir="/@bootdirname@" -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir="${rootdir}/@bootdirname@" + fi +fi + +grubdir="`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'`" +device_map="${grubdir}/device.map" -grub_probe="${grub_probe} --device-map=${device_map}" # Check if GRUB is installed. if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then @@ -250,7 +306,7 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" fi fi -set $grub_mkimage dummy +set "$grub_mkimage" dummy if test -f "$1"; then : else @@ -258,7 +314,7 @@ else exit 1 fi -set $grub_mkdevicemap dummy +set "$grub_mkdevicemap" dummy if test -f "$1"; then : else @@ -266,12 +322,93 @@ else exit 1 fi +if [ x"$platform" = xefi ]; then + # Find the EFI System Partition. + efidir= + if test -d "${bootdir}/efi"; then + install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}/efi"`" + # Is it a mount point? + if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then + efidir="${bootdir}/efi" + fi + elif test -n "$rootdir" && test "x$rootdir" != "x/"; then + # The EFI System Partition may have been given directly using + # --root-directory. + install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${rootdir}"`" + # Is it a mount point? + if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${rootdir}/.."`"; then + efidir="${rootdir}" + fi + fi + + if test -n "$efidir"; then + efi_fs=`"$grub_probe" --target=fs "--device-map=${device_map}" "${efidir}"` + if test "x$efi_fs" = xfat; then :; else + echo "${efidir} doesn't look like an EFI partition." 1>&2 + efidir= + fi + fi + + if test -n "$efidir"; then + # The EFI specification requires that an EFI System Partition must + # contain an "EFI" subdirectory, and that OS loaders are stored in + # subdirectories below EFI. Vendors are expected to pick names that do + # not collide with other vendors. To minimise collisions, we use the + # name of our distributor if possible. + efi_distributor="$bootloader_id" + if test $removable = yes; then + # The specification makes stricter requirements of removable + # devices, in order that only one image can be automatically loaded + # from them. The image must always reside under /EFI/BOOT, and it + # must have a specific file name depending on the architecture. + efi_distributor=BOOT + case "$target_cpu" in + i386) + efi_file=BOOTIA32.EFI ;; + x86-64) + efi_file=BOOTX64.EFI ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=BOOTIA64.EFI ;; + esac + else + # It is convenient for each architecture to have a different + # efi_file, so that different versions can be installed in parallel. + case "$target_cpu" in + i386) + efi_file=grubia32.efi ;; + x86-64) + efi_file=grubx64.efi ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=grubia64.efi ;; + *) + efi_file=grub.efi ;; + esac + # TODO: We should also use efibootmgr, if available, to add a Boot + # entry for ourselves. + fi + efidir="$efidir/EFI/$efi_distributor" + mkdir -p "$efidir" || exit 1 + else + # We don't know what's going on. Fall back to traditional + # (non-specification-compliant) behaviour. + efidir="$grubdir" + efi_distributor= + efi_file=grub.efi + fi +fi + # Create the GRUB directory if it is not present. mkdir -p "$grubdir" || exit 1 # If --recheck is specified, remove the device map, if present. if test $recheck = yes; then - rm -f $device_map + rm -f "$device_map" fi # Create the device map file if it is not present. @@ -281,11 +418,11 @@ else # Create a safe temporary file. test -n "$mklog" && log_file=`$mklog` - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 + "$grub_mkdevicemap" "--device-map=$device_map" $no_floppy || exit 1 fi # Make sure that there is no duplicated entry. -tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \ +tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' "$device_map" \ | sort | uniq -d | sed -n 1p` if test -n "$tmp"; then echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 @@ -293,42 +430,42 @@ if test -n "$tmp"; then fi # Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do - if test -f $file && [ "`basename $file`" != menu.lst ]; then - rm -f $file || exit 1 +for file in "${grubdir}"/*.mod "${grubdir}"/*.lst "${grubdir}"/*.img "${grubdir}"/efiemu??.o; do + if test -f "$file" && [ "`basename $file`" != menu.lst ]; then + rm -f "$file" || exit 1 fi done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do - cp -f $file ${grubdir} || exit 1 +for file in "${pkglibdir}"/*.mod "${pkglibdir}"/*.lst; do + cp -f "$file" "${grubdir}" || exit 1 done if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then - for file in ${pkglibdir}/*.img ${pkglibdir}/efiemu??.o; do - if test -f $file; then - cp -f $file ${grubdir} || exit 1 + for file in "${pkglibdir}"/*.img "${pkglibdir}"/efiemu??.o; do + if test -f "$file"; then + cp -f "$file" "${grubdir}" || exit 1 fi done fi # Copy gettext files -mkdir -p ${grubdir}/locale/ -for dir in ${localedir}/*; do +mkdir -p "${grubdir}"/locale/ +for dir in "${localedir}"/*; do if test -f "$dir/LC_MESSAGES/grub.mo"; then cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" fi done # Write device to a variable so we don't have to traverse /dev every time. -grub_device=`$grub_probe --target=device ${grubdir}` || exit 1 +grub_device="`"$grub_probe" --device-map="${device_map}" --target=device "${grubdir}"`" || exit 1 -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create +if ! test -f "${grubdir}"/grubenv; then + "$grub_editenv" "${grubdir}"/grubenv create fi # Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device ${grub_device}` -if test "x$fs_module" = x -a "x$modules" = x; then - echo "Auto-detection of a filesystem module failed." 1>&2 - echo "Please specify the module with the option \`--modules' explicitly." 1>&2 +fs_module="`"$grub_probe" --device-map="${device_map}" --target=fs --device "${grub_device}"`" +if test "x$fs_module" = x ; then + echo "Auto-detection of a filesystem of ${grub_device} failed." 1>&2 + echo "Please report this together with the output of \"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\" to " 1>&2 exit 1 fi @@ -336,18 +473,24 @@ fi # this command is allowed to fail (--target=fs already grants us that the # filesystem will be accessible). partmap_module= -for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; +for x in "`"$grub_probe" --device-map="${device_map}" --target=partmap --device "${grub_device}" 2> /dev/null`"; do + case "$x" in + netbsd | openbsd) + partmap_module="$partmap_module part_bsd";; + "") ;; + *) + partmap_module="$partmap_module part_$x";; + esac done # Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}` +devabstraction_module="`"$grub_probe" --device-map="${device_map}" --target=abstraction --device "${grub_device}"`" # The order in this list is critical. Be careful when modifying it. modules="$modules $disk_module" modules="$modules $fs_module $partmap_module $devabstraction_module" -relative_grubdir=`make_system_path_relative_to_its_root ${grubdir}` || exit 1 +relative_grubdir="`"$grub_mkrelpath" "${grubdir}"`" || exit 1 if [ "x${relative_grubdir}" = "x" ] ; then relative_grubdir=/ fi @@ -355,10 +498,10 @@ fi prefix_drive= config_opt= -rm -f ${grubdir}/load.cfg +rm -f "${grubdir}/load.cfg" if [ "x${debug_image}" != x ]; then - echo "set debug='${debug_image}'" >> ${grubdir}/load.cfg + echo "set debug='${debug_image}'" >> "${grubdir}/load.cfg" config_opt="-c ${grubdir}/load.cfg " fi @@ -367,27 +510,28 @@ if [ "x${devabstraction_module}" = "x" ] ; then if echo "${install_device}" | grep -qx "(.*)" ; then install_drive="${install_device}" else - install_drive="`$grub_probe --target=drive --device ${install_device}`" || exit 1 + install_drive="`"$grub_probe" --device-map="${device_map}" --target=drive --device "${install_device}"`" || exit 1 fi - install_drive="`echo ${install_drive} | sed -e s/,[a-z0-9,]*//g`" + install_drive="`echo "${install_drive}" | sed -e s/,[a-z0-9,]*//g`" fi - grub_drive="`$grub_probe --target=drive --device ${grub_device}`" || exit 1 + grub_drive="`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"`" || exit 1 # Strip partition number - grub_drive="`echo ${grub_drive} | sed -e s/,[a-z0-9,]*//g`" + grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`" + grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`" if [ "$disk_module" = ata ] ; then # generic method (used on coreboot and ata mod) - uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`" + uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`" if [ "x${uuid}" = "x" ] ; then echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 exit 1 fi - echo "search.fs_uuid ${uuid} root " >> ${grubdir}/load.cfg - echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg + echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg" + echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg" config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" elif [ "x${grub_drive}" != "x${install_drive}" ] ; then - uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`" + uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`" if [ "x${uuid}" = "x" ] ; then echo "You attempted a cross-disk install, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 exit 1 @@ -396,28 +540,117 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" + elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ]; then + # we need to hardcode the partition number in the core image's prefix. + if [ x"$grub_partition" = x ]; then + prefix_drive="()" + else + prefix_drive="(,$grub_partition)" + fi fi else - prefix_drive=`$grub_probe --target=drive --device ${grub_device}` || exit 1 + prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1 fi case "${target_cpu}-${platform}" in - i386-pc) mkimage_target=i386-pc ;; sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;; - *) mkimage_target=i386-coreboot; + *) mkimage_target="${target_cpu}-${platform}" ;; esac -if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then - $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +case "${target_cpu}-${platform}" in + i386-efi | x86_64-efi) imgext=efi ;; + mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \ + | powerpc-ieee1275) imgext=elf ;; + *) imgext=img ;; +esac + +"$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1 + +# Backward-compatibility kludges +if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then + cp "${grubdir}/core.${imgext}" "${bootdir}"/grub.elf +elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then + cp "${grubdir}/core.${imgext}" "${grubdir}/grub" +elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then + "$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/grub.efi" --prefix="" $modules || exit 1 +fi + + +# Perform the platform-dependent install +if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then # Now perform the installation. - $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ - ${install_device} || exit 1 -elif [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then - $grub_mkimage ${config_opt} -f ${font} -d ${pkglibdir} -O ${mkimage_target} --output=/boot/grub.elf --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 -else - $grub_mkimage -O ${mkimage_target} ${config_opt} -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 + "$grub_setup" ${allow_floppy} ${setup_verbose} ${setup_force} --directory="${grubdir}" \ + --device-map="${device_map}" "${install_device}" || exit 1 +elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then + if [ x"$update_nvram" = xyes ]; then + set "$ofpathname" dummy + if test -f "$1"; then + : + else + echo "$1: Not found." 1>&2 + exit 1 + fi + set "$nvsetenv" dummy + if test -f "$1"; then + : + else + echo "$1: Not found." 1>&2 + exit 1 + fi + # Get the Open Firmware device tree path translation. + dev="`echo $grub_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`" + partno="`echo $grub_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'`" + ofpath="`$ofpathname $dev`" || { + echo "Couldn't find Open Firmware device tree path for $dev." + echo "You will have to set boot-device manually." + exit 1 + } + + # Point boot-device at the new grub install + boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/core.${imgext}" | sed 's,/,\\\\,g'` + "$nvsetenv" boot-device "$boot_device" || { + echo "$nvsetenv failed." + echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" + echo " setenv boot-device $boot_device" + exit 1 + } + fi +elif [ x"$platform" = xefi ]; then + cp "${grubdir}/core.${imgext}" "${efidir}/${efi_file}" + + # Try to make this image bootable using the EFI Boot Manager, if available. + if test "$removable" = no && test -n "$efi_distributor" && \ + test -n "$efibootmgr"; then + # On Linux, we need the efivars kernel modules. + case "$host_os" in + linux*) + modprobe -q efivars 2>/dev/null || true ;; + esac + + # Delete old entries from the same distributor. + for bootnum in `efibootmgr | grep '^Boot[0-9]' | \ + fgrep -i " $efi_distributor" | cut -b5-8`; do + efibootmgr $efi_quiet -b "$bootnum" -B + done + + # Add a new entry for the image we just created. efibootmgr needs to be + # given the disk device and partition number separately, so we have to + # fiddle about with grub-probe to get hold of this reasonably reliably. + # Use fresh device map text to avoid any problems with stale data, since + # all we need here is a one-to-one mapping. + clean_devmap="$($grub_mkdevicemap --device-map=/dev/stdout)" + efidir_drive="$(echo "$clean_devmap" | "$grub_probe" --device-map="${device_map}" --target=drive --device-map=/dev/stdin "$efidir")" + if test -z "$efidir_drive"; then + echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2 + else + efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)" + efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')" + efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \ + -L "$GRUB_DISTRIBUTOR" -l "\\EFI\\$efi_distributor\\$efi_file" + fi + fi fi echo "Installation finished. No error reported." diff --git a/util/grub-kbdcomp.in b/util/grub-kbdcomp.in new file mode 100644 index 000000000..87b24bcdf --- /dev/null +++ b/util/grub-kbdcomp.in @@ -0,0 +1,6 @@ +#!/bin/sh + +grub_mklayout=${bindir}/`echo grub-mklayout | sed ${transform}` + +ckbcomp "$@" | $grub_mklayout -o "$1".gkb + diff --git a/util/grub-macho2img.c b/util/grub-macho2img.c index 8683587be..bce0a06d1 100644 --- a/util/grub-macho2img.c +++ b/util/grub-macho2img.c @@ -17,6 +17,8 @@ * along with GRUB. If not, see . */ +#include + #include #include #include @@ -79,7 +81,7 @@ main (int argc, char **argv) fclose (in); fclose (out); free (buf); - printf ("Invalid Mach-O fle\n"); + printf ("Invalid Mach-O file\n"); return 4; } curcmd = (struct grub_macho_segment32 *) (buf + sizeof (*head)); diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c new file mode 100644 index 000000000..e29c6b17c --- /dev/null +++ b/util/grub-menulst2cfg.c @@ -0,0 +1,122 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include + +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + FILE *in, *out; + char *entryname = NULL; + char *buf = NULL; + size_t bufsize = 0; + char *suffix = xstrdup (""); + int suffixlen = 0; + + if (argc >= 2 && argv[1][0] == '-') + { + fprintf (stdout, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); + return 0; + } + + if (argc >= 2) + { + in = fopen (argv[1], "r"); + if (!in) + { + fprintf (stderr, "Couldn't open %s for reading: %s\n", + argv[1], strerror (errno)); + return 1; + } + } + else + in = stdin; + + if (argc >= 3) + { + out = fopen (argv[2], "w"); + if (!out) + { + if (in != stdin) + fclose (in); + fprintf (stderr, "Couldn't open %s for writing: %s\n", + argv[2], strerror (errno)); + return 1; + } + } + else + out = stdout; + + while (1) + { + char *parsed; + + if (getline (&buf, &bufsize, in) < 0) + break; + + { + char *oldname = NULL; + char *newsuffix; + + oldname = entryname; + parsed = grub_legacy_parse (buf, &entryname, &newsuffix); + if (newsuffix) + { + suffixlen += strlen (newsuffix); + suffix = xrealloc (suffix, suffixlen + 1); + strcat (suffix, newsuffix); + } + if (oldname != entryname && oldname) + fprintf (out, "}\n\n"); + if (oldname != entryname) + { + char *escaped = grub_legacy_escape (entryname, strlen (entryname)); + fprintf (out, "menuentry \'%s\' {\n", escaped); + free (escaped); + free (oldname); + } + } + + if (parsed) + fprintf (out, "%s%s", entryname ? " " : "", parsed); + free (parsed); + parsed = NULL; + } + + if (entryname) + fprintf (out, "}\n\n"); + + fwrite (suffix, 1, suffixlen, out); + + free (buf); + free (suffix); + free (entryname); + + if (in != stdin) + fclose (in); + if (out != stdout) + fclose (out); + + return 0; +} diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 828b54bce..b041a38d7 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -22,6 +22,7 @@ transform="@program_transform_name@" prefix=@prefix@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ +bindir=@bindir@ libdir=@libdir@ sysconfdir=@sysconfdir@ PACKAGE_NAME=@PACKAGE_NAME@ @@ -35,8 +36,11 @@ grub_mkconfig_dir=${sysconfdir}/grub.d self=`basename $0` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` +grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed "${transform}"` +grub_probe=${sbindir}/`echo grub-probe | sed "${transform}"` +grub_script_check="${bindir}/`echo grub-script-check | sed "${transform}"`" + +GRUB_PREFIX=`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"` # Usage: usage # Print the usage. @@ -93,18 +97,6 @@ done . ${libdir}/grub/grub-mkconfig_lib -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - GRUB_PREFIX=`echo /grub | sed ${transform}` - ;; -*) - # Use /boot/grub by default. - GRUB_PREFIX=`echo /boot/grub | sed ${transform}` - ;; -esac - if [ "x$EUID" = "x" ] ; then EUID=`id -u` fi @@ -158,7 +150,7 @@ GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_u # Filesystem for the device containing our userland. Used for stuff like # choosing Hurd filesystem module. -GRUB_FS="`${grub_probe} --target=fs / 2> /dev/null || echo unknown`" +GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`" if test -f ${sysconfdir}/default/grub ; then . ${sysconfdir}/default/grub @@ -178,20 +170,6 @@ fi for x in ${GRUB_TERMINAL_OUTPUT}; do if [ "x${x}" = "xgfxterm" ]; then - # If this platform supports gfxterm, try to use it. - if ! test -e ${GRUB_PREFIX}/gfxterm.mod ; then - if [ "x$termoutdefault" != "x1" ]; then - echo "gfxterm isn't available on your platform" >&2 ; exit 1 - fi - GRUB_TERMINAL_OUTPUT= - break; - fi - if [ ! -s "${GRUB_PREFIX}/video.lst" ] ; then - if [ "x$termoutdefault" != "x1" ]; then - echo "No suitable backend could be found for gfxterm." >&2 ; exit 1 - fi - GRUB_TERMINAL_OUTPUT= - fi if [ -n "$GRUB_FONT" ] ; then if is_path_readable_by_grub ${GRUB_FONT} > /dev/null ; then GRUB_FONT_PATH=${GRUB_FONT} @@ -200,7 +178,7 @@ for x in ${GRUB_TERMINAL_OUTPUT}; do exit 1 fi else - for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do + for dir in ${pkgdatadir} ${GRUB_PREFIX} /usr/share/grub ; do for basename in unicode unifont ascii; do path="${dir}/${basename}.pf2" if is_path_readable_by_grub ${path} > /dev/null ; then @@ -255,6 +233,7 @@ export GRUB_DEFAULT \ GRUB_HIDDEN_TIMEOUT_BUTTON \ GRUB_TIMEOUT_BUTTON \ GRUB_BUTTON_CMOS_ADDRESS \ + GRUB_BUTTON_CMOS_CLEAN \ GRUB_DISTRIBUTOR \ GRUB_CMDLINE_LINUX \ GRUB_CMDLINE_LINUX_DEFAULT \ @@ -266,8 +245,7 @@ export GRUB_DEFAULT \ GRUB_TERMINAL_OUTPUT \ GRUB_SERIAL_COMMAND \ GRUB_DISABLE_LINUX_UUID \ - GRUB_DISABLE_LINUX_RECOVERY \ - GRUB_DISABLE_NETBSD_RECOVERY \ + GRUB_DISABLE_RECOVERY \ GRUB_VIDEO_BACKEND \ GRUB_GFXMODE \ GRUB_BACKGROUND \ @@ -314,8 +292,15 @@ for i in ${grub_mkconfig_dir}/* ; do done if test "x${grub_cfg}" != "x" ; then - # none of the children aborted with error, install the new grub.cfg - mv -f ${grub_cfg}.new ${grub_cfg} + if ! ${grub_script_check} ${grub_cfg}.new; then + echo "Syntax errors are detected in generated GRUB config file." >&2 + echo "Ensure that there are no errors in /etc/default/grub" >&2 + echo "and /etc/grub.d/* files or please file a bug report with" >&2 + echo "${grub_cfg}.new file attached." >&2 + else + # none of the children aborted with error, install the new grub.cfg + mv -f ${grub_cfg}.new ${grub_cfg} + fi fi echo "done" >&2 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 9a77d1bdf..41359975e 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -119,7 +119,7 @@ prepare_grub_to_access_device () # otherwise set root as per value in device.map. echo "set root='`${grub_probe} --device ${device} --target=drive`'" if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then - echo "search --no-floppy --fs-uuid --set ${fs_uuid}" + echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" fi } diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c index 6738f7136..bdecae4a3 100644 --- a/util/grub-mkdevicemap.c +++ b/util/grub-mkdevicemap.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -39,26 +40,6 @@ #include "progname.h" -void -grub_xputs_real (const char *str) -{ - fputs (str, stdout); -} - -void (*grub_xputs) (const char *str) = grub_xputs_real; - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_refresh (void) -{ - fflush (stdout); -} - static void make_device_map (const char *device_map, int floppy_disks) { diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 970cc4aca..3e24380d1 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index c89eddc32..53e867602 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,16 @@ #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) +#ifdef HAVE_LIBLZMA +#include +#endif + #define TARGET_NO_FIELD 0xffffffff + +typedef enum { + COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ +} grub_compression_t; + struct image_target_desc { const char *name; @@ -53,15 +63,17 @@ struct image_target_desc enum { IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, - IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH + IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, + IMAGE_I386_PC_PXE } id; enum { PLATFORM_FLAGS_NONE = 0, - PLATFORM_FLAGS_LZMA = 1 + PLATFORM_FLAGS_LZMA = 1, + PLATFORM_FLAGS_DECOMPRESSORS = 2 } flags; unsigned prefix; - unsigned data_end; + unsigned prefix_end; unsigned raw_size; unsigned total_module_size; unsigned kernel_image_size; @@ -73,6 +85,7 @@ struct image_target_desc unsigned install_dos_part, install_bsd_part; grub_uint64_t link_addr; unsigned mod_gap, mod_align; + grub_compression_t default_compression; }; struct image_target_desc image_targets[] = @@ -84,7 +97,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_I386_COREBOOT_PREFIX, - .data_end = GRUB_KERNEL_I386_COREBOOT_DATA_END, + .prefix_end = GRUB_KERNEL_I386_COREBOOT_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -105,8 +118,8 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_I386_COREBOOT_PREFIX, - .data_end = GRUB_KERNEL_I386_COREBOOT_DATA_END, + .prefix = GRUB_KERNEL_I386_MULTIBOOT_PREFIX, + .prefix_end = GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -128,7 +141,25 @@ struct image_target_desc image_targets[] = .id = IMAGE_I386_PC, .flags = PLATFORM_FLAGS_LZMA, .prefix = GRUB_KERNEL_I386_PC_PREFIX, - .data_end = GRUB_KERNEL_I386_PC_DATA_END, + .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END, + .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, + .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, + .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE, + .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, + .install_bsd_part = GRUB_KERNEL_I386_PC_INSTALL_BSD_PART, + .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR + }, + { + .name = "i386-pc-pxe", + .voidp_sizeof = 4, + .bigendian = 0, + .id = IMAGE_I386_PC_PXE, + .flags = PLATFORM_FLAGS_LZMA, + .prefix = GRUB_KERNEL_I386_PC_PREFIX, + .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END, .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE, @@ -146,7 +177,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_I386_EFI_PREFIX, - .data_end = GRUB_KERNEL_I386_EFI_DATA_END, + .prefix_end = GRUB_KERNEL_I386_EFI_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -168,7 +199,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_I386_IEEE1275, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_I386_IEEE1275_PREFIX, - .data_end = GRUB_KERNEL_I386_IEEE1275_DATA_END, + .prefix_end = GRUB_KERNEL_I386_IEEE1275_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -190,7 +221,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_QEMU, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_I386_QEMU_PREFIX, - .data_end = GRUB_KERNEL_I386_QEMU_DATA_END, + .prefix_end = GRUB_KERNEL_I386_QEMU_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, @@ -208,7 +239,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_X86_64_EFI_PREFIX, - .data_end = GRUB_KERNEL_X86_64_EFI_DATA_END, + .prefix_end = GRUB_KERNEL_X86_64_EFI_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -228,40 +259,42 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, - .flags = PLATFORM_FLAGS_NONE, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, - .data_end = GRUB_KERNEL_MIPS_YEELOONG_DATA_END, - .raw_size = GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE, + .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, + .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE, - .kernel_image_size = GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN + .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .default_compression = COMPRESSION_NONE }, { .name = "mipsel-yeeloong-elf", .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_ELF, - .flags = PLATFORM_FLAGS_NONE, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, - .data_end = GRUB_KERNEL_MIPS_YEELOONG_DATA_END, - .raw_size = GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE, + .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, + .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE, - .kernel_image_size = GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN + .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .default_compression = COMPRESSION_NONE }, { .name = "powerpc-ieee1275", @@ -270,7 +303,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_PPC, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX, - .data_end = GRUB_KERNEL_POWERPC_IEEE1275_DATA_END, + .prefix_end = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -292,7 +325,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_SPARC64_RAW, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX, - .data_end = GRUB_KERNEL_SPARC64_IEEE1275_DATA_END, + .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END, .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE, @@ -310,7 +343,7 @@ struct image_target_desc image_targets[] = .id = IMAGE_SPARC64_AOUT, .flags = PLATFORM_FLAGS_NONE, .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX, - .data_end = GRUB_KERNEL_SPARC64_IEEE1275_DATA_END, + .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END, .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE, @@ -473,9 +506,66 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, *core_size += raw_size; } +#ifdef HAVE_LIBLZMA +static void +compress_kernel_xz (char *kernel_img, size_t kernel_size, + char **core_img, size_t *core_size, size_t raw_size) +{ + lzma_stream strm = LZMA_STREAM_INIT; + lzma_ret xzret; + lzma_options_lzma lzopts = { + .dict_size = 1 << 16, + .preset_dict = NULL, + .preset_dict_size = 0, + .lc = 3, + .lp = 0, + .pb = 2, + .mode = LZMA_MODE_NORMAL, + .nice_len = 64, + .mf = LZMA_MF_BT4, + .depth = 0, + }; + lzma_filter fltrs[] = { + { .id = LZMA_FILTER_LZMA2, .options = &lzopts}, + { .id = LZMA_VLI_UNKNOWN, .options = NULL} + }; + + if (kernel_size < raw_size) + grub_util_error (_("the core image is too small")); + + xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE); + if (xzret != LZMA_OK) + grub_util_error (_("cannot compress the kernel image")); + + *core_img = xmalloc (kernel_size); + memcpy (*core_img, kernel_img, raw_size); + + *core_size = kernel_size - raw_size; + strm.next_in = (unsigned char *) kernel_img + raw_size; + strm.avail_in = kernel_size - raw_size; + strm.next_out = (unsigned char *) *core_img + raw_size; + strm.avail_out = *core_size; + + while (1) + { + xzret = lzma_code (&strm, LZMA_FINISH); + if (xzret == LZMA_OK) + continue; + if (xzret == LZMA_STREAM_END) + break; + grub_util_error (_("cannot compress the kernel image")); + } + + *core_size -= strm.avail_out; + + *core_size += raw_size; +} +#endif + static void compress_kernel (struct image_target_desc *image_target, char *kernel_img, - size_t kernel_size, char **core_img, size_t *core_size) + size_t kernel_size, char **core_img, size_t *core_size, + grub_compression_t comp) { if (image_target->flags & PLATFORM_FLAGS_LZMA) { @@ -484,6 +574,20 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img, return; } +#ifdef HAVE_LIBLZMA + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS + && (comp == COMPRESSION_XZ)) + { + compress_kernel_xz (kernel_img, kernel_size, core_img, + core_size, image_target->raw_size); + return; + } +#endif + + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS + && (comp != COMPRESSION_NONE)) + grub_util_error ("unknown compression %d\n", comp); + *core_img = xmalloc (kernel_size); memcpy (*core_img, kernel_img, kernel_size); *core_size = kernel_size; @@ -506,12 +610,13 @@ struct fixup_block_list static void generate_image (const char *dir, char *prefix, FILE *out, char *mods[], - char *memdisk_path, char *font_path, char *config_path, - struct image_target_desc *image_target, int note) + char *memdisk_path, char *config_path, + struct image_target_desc *image_target, int note, + grub_compression_t comp) { char *kernel_img, *core_img; size_t kernel_size, total_module_size, core_size, exec_size; - size_t memdisk_size = 0, font_size = 0, config_size = 0, config_size_pure = 0; + size_t memdisk_size = 0, config_size = 0, config_size_pure = 0; char *kernel_path; size_t offset; struct grub_util_path_list *path_list, *p, *next; @@ -519,6 +624,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_uint64_t start_address; void *rel_section; grub_size_t reloc_size, align; + + if (comp == COMPRESSION_AUTO) + comp = image_target->default_compression; + path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); kernel_path = grub_util_get_path (dir, "kernel.img"); @@ -535,12 +644,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], total_module_size += memdisk_size + sizeof (struct grub_module_header); } - if (font_path) - { - font_size = ALIGN_ADDR (grub_util_get_image_size (font_path)); - total_module_size += font_size + sizeof (struct grub_module_header); - } - if (config_path) { config_size_pure = grub_util_get_image_size (config_path) + 1; @@ -564,7 +667,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], total_module_size, &start_address, &rel_section, &reloc_size, &align, image_target); - if (image_target->prefix + strlen (prefix) + 1 > image_target->data_end) + if (image_target->prefix + strlen (prefix) + 1 > image_target->prefix_end) grub_util_error (_("prefix is too long")); strcpy (kernel_img + image_target->prefix, prefix); @@ -624,20 +727,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += memdisk_size; } - if (font_path) - { - struct grub_module_header *header; - - header = (struct grub_module_header *) (kernel_img + offset); - memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_host_to_target32 (OBJ_TYPE_FONT); - header->size = grub_host_to_target32 (font_size + sizeof (*header)); - offset += sizeof (*header); - - grub_util_load_image (font_path, kernel_img + offset); - offset += font_size; - } - if (config_path) { struct grub_module_header *header; @@ -653,13 +742,19 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += config_size; } + if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + && (image_target->total_module_size != TARGET_NO_FIELD)) + *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) + = grub_host_to_target32 (total_module_size); + grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); compress_kernel (image_target, kernel_img, kernel_size + total_module_size, - &core_img, &core_size); + &core_img, &core_size, comp); grub_util_info ("the core size is 0x%x", core_size); - if (image_target->total_module_size != TARGET_NO_FIELD) + if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + && image_target->total_module_size != TARGET_NO_FIELD) *((grub_uint32_t *) (core_img + image_target->total_module_size)) = grub_host_to_target32 (total_module_size); if (image_target->kernel_image_size != TARGET_NO_FIELD) @@ -680,9 +775,57 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], = grub_host_to_target32 (-2); } + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + { + char *full_img; + size_t full_size; + char *decompress_path, *decompress_img; + size_t decompress_size; + const char *name; + + switch (comp) + { + case COMPRESSION_XZ: + name = "xz_decompress.img"; + break; + case COMPRESSION_NONE: + name = "none_decompress.img"; + break; + default: + grub_util_error ("unknown compression %d\n", comp); + } + + decompress_path = grub_util_get_path (dir, name); + decompress_size = grub_util_get_image_size (decompress_path); + decompress_img = grub_util_read_image (decompress_path); + + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE)) + = grub_host_to_target32 (core_size); + + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE)) + = grub_host_to_target32 (kernel_size + total_module_size); + + full_size = core_size + decompress_size; + + full_img = xmalloc (full_size); + memset (full_img, 0, full_size); + + memcpy (full_img, decompress_img, decompress_size); + + memcpy (full_img + decompress_size, core_img, core_size); + + memset (full_img + decompress_size + core_size, 0, + full_size - (decompress_size + core_size)); + + free (core_img); + core_img = full_img; + core_size = full_size; + } + switch (image_target->id) { case IMAGE_I386_PC: + case IMAGE_I386_PC_PXE: { unsigned num; char *boot_path, *boot_img; @@ -697,6 +840,20 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (num > 0xffff) grub_util_error (_("the core image is too big")); + if (image_target->id == IMAGE_I386_PC_PXE) + { + char *pxeboot_path, *pxeboot_img; + size_t pxeboot_size; + + pxeboot_path = grub_util_get_path (dir, "pxeboot.img"); + pxeboot_size = grub_util_get_image_size (pxeboot_path); + pxeboot_img = grub_util_read_image (pxeboot_path); + + grub_util_write_image (pxeboot_img, pxeboot_size, out); + free (pxeboot_img); + free (pxeboot_path); + } + boot_path = grub_util_get_path (dir, "diskboot.img"); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) @@ -1203,6 +1360,7 @@ static struct option options[] = {"output", required_argument, 0, 'o'}, {"note", no_argument, 0, 'n'}, {"format", required_argument, 0, 'O'}, + {"compression", required_argument, 0, 'C'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, @@ -1240,12 +1398,12 @@ Make a bootable image of GRUB.\n\ -d, --directory=DIR use images and modules under DIR [default=%s/@platform@]\n\ -p, --prefix=DIR set grub_prefix directory [default=%s]\n\ -m, --memdisk=FILE embed FILE as a memdisk image\n\ - -f, --font=FILE embed FILE as a boot font\n\ -c, --config=FILE embed FILE as boot config\n\ -n, --note add NOTE segment for CHRP Open Firmware\n\ -o, --output=FILE output a generated image to FILE [default=stdout]\n\ -O, --format=FORMAT generate an image in format\n\ available formats: %s\n\ + -C, --compression=(xz|none|auto) choose the compression to use\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ @@ -1272,6 +1430,7 @@ main (int argc, char *argv[]) FILE *fp = stdout; int note = 0; struct image_target_desc *image_target = NULL; + grub_compression_t comp = COMPRESSION_AUTO; set_program_name (argv[0]); @@ -1279,7 +1438,7 @@ main (int argc, char *argv[]) while (1) { - int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:hVvn", options, 0); + int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:C:hVvn", options, 0); if (c == -1) break; @@ -1329,13 +1488,6 @@ main (int argc, char *argv[]) prefix = xstrdup ("(memdisk)/boot/grub"); break; - case 'f': - if (font) - free (font); - - font = xstrdup (optarg); - break; - case 'c': if (config) free (config); @@ -1343,6 +1495,22 @@ main (int argc, char *argv[]) config = xstrdup (optarg); break; + case 'C': + if (grub_strcmp (optarg, "xz") == 0) + { +#ifdef HAVE_LIBLZMA + comp = COMPRESSION_XZ; +#else + grub_util_error ("grub-mkimage is compiled without XZ support", + optarg); +#endif + } + else if (grub_strcmp (optarg, "none") == 0) + comp = COMPRESSION_NONE; + else + grub_util_error ("Unknown compression format %s", optarg); + break; + case 'h': usage (0); break; @@ -1400,8 +1568,8 @@ main (int argc, char *argv[]) } generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, - argv + optind, memdisk, font, config, - image_target, note); + argv + optind, memdisk, config, + image_target, note, comp); fclose (fp); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 4a257e329..ce51f2fbc 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -555,7 +555,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_text_section) (s, image_target)) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) current_address = ALIGN_UP (current_address + image_target->vaddr_offset, @@ -577,7 +577,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_data_section) (s, image_target)) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) @@ -641,7 +641,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, /* Relocate sections then symbols in the virtual address space. */ s = (Elf_Shdr *) ((char *) sections + grub_host_to_target16 (e->e_shstrndx) * section_entsize); - strtab = (char *) e + grub_host_to_target32 (s->sh_offset); + strtab = (char *) e + grub_host_to_target_addr (s->sh_offset); section_addresses = SUFFIX (locate_sections) (sections, section_entsize, num_sections, strtab, @@ -662,7 +662,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c new file mode 100644 index 000000000..e90d955ff --- /dev/null +++ b/util/grub-mklayout.c @@ -0,0 +1,500 @@ +/* + * GRUB -- GRand Unified Bootloader + * 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 . + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "progname.h" + +#define CKBCOMP "ckbcomp" + +static struct option options[] = { + {"output", required_argument, 0, 'o'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} +}; + +struct console_grub_equivalence +{ + char *layout; + grub_uint32_t grub; +}; + +static struct console_grub_equivalence console_grub_equivalences_shift[] = { + {"KP_0", '0'}, + {"KP_1", '1'}, + {"KP_2", '2'}, + {"KP_3", '3'}, + {"KP_4", '4'}, + {"KP_5", '5'}, + {"KP_6", '6'}, + {"KP_7", '7'}, + {"KP_8", '8'}, + {"KP_9", '9'}, + {"KP_Period", '.'}, +}; + +static struct console_grub_equivalence console_grub_equivalences_unshift[] = { + {"KP_0", GRUB_TERM_KEY_INSERT}, + {"KP_1", GRUB_TERM_KEY_END}, + {"KP_2", GRUB_TERM_KEY_DOWN}, + {"KP_3", GRUB_TERM_KEY_NPAGE}, + {"KP_4", GRUB_TERM_KEY_LEFT}, + {"KP_5", GRUB_TERM_KEY_CENTER}, + {"KP_6", GRUB_TERM_KEY_RIGHT}, + {"KP_7", GRUB_TERM_KEY_HOME}, + {"KP_8", GRUB_TERM_KEY_UP}, + {"KP_9", GRUB_TERM_KEY_PPAGE}, + {"KP_Period", GRUB_TERM_KEY_DC}, +}; + +static struct console_grub_equivalence console_grub_equivalences_common[] = { + {"Escape", GRUB_TERM_ESC}, + {"Tab", GRUB_TERM_TAB}, + {"Delete", GRUB_TERM_BACKSPACE}, + + {"KP_Enter", '\n'}, + {"Return", '\n'}, + + {"KP_Multiply", '*'}, + {"KP_Subtract", '-'}, + {"KP_Add", '+'}, + {"KP_Divide", '/'}, + + {"F1", GRUB_TERM_KEY_F1}, + {"F2", GRUB_TERM_KEY_F2}, + {"F3", GRUB_TERM_KEY_F3}, + {"F4", GRUB_TERM_KEY_F4}, + {"F5", GRUB_TERM_KEY_F5}, + {"F6", GRUB_TERM_KEY_F6}, + {"F7", GRUB_TERM_KEY_F7}, + {"F8", GRUB_TERM_KEY_F8}, + {"F9", GRUB_TERM_KEY_F9}, + {"F10", GRUB_TERM_KEY_F10}, + {"F11", GRUB_TERM_KEY_F11}, + {"F12", GRUB_TERM_KEY_F12}, + {"F13", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT}, + {"F14", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT}, + {"F15", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT}, + {"F16", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT}, + {"F17", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT}, + {"F18", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT}, + {"F19", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT}, + {"F20", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT}, + {"F21", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT}, + {"F22", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT}, + {"F23", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT}, + {"F24", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT}, + {"Console_13", GRUB_TERM_KEY_F1 | GRUB_TERM_ALT}, + {"Console_14", GRUB_TERM_KEY_F2 | GRUB_TERM_ALT}, + {"Console_15", GRUB_TERM_KEY_F3 | GRUB_TERM_ALT}, + {"Console_16", GRUB_TERM_KEY_F4 | GRUB_TERM_ALT}, + {"Console_17", GRUB_TERM_KEY_F5 | GRUB_TERM_ALT}, + {"Console_18", GRUB_TERM_KEY_F6 | GRUB_TERM_ALT}, + {"Console_19", GRUB_TERM_KEY_F7 | GRUB_TERM_ALT}, + {"Console_20", GRUB_TERM_KEY_F8 | GRUB_TERM_ALT}, + {"Console_21", GRUB_TERM_KEY_F9 | GRUB_TERM_ALT}, + {"Console_22", GRUB_TERM_KEY_F10 | GRUB_TERM_ALT}, + {"Console_23", GRUB_TERM_KEY_F11 | GRUB_TERM_ALT}, + {"Console_24", GRUB_TERM_KEY_F12 | GRUB_TERM_ALT}, + {"Console_25", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_26", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_27", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_28", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_29", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_30", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_31", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_32", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_33", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_34", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_35", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_36", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + + {"Insert", GRUB_TERM_KEY_INSERT}, + {"Down", GRUB_TERM_KEY_DOWN}, + {"Up", GRUB_TERM_KEY_UP}, + {"Home", GRUB_TERM_KEY_HOME}, + {"End", GRUB_TERM_KEY_END}, + {"Right", GRUB_TERM_KEY_RIGHT}, + {"Left", GRUB_TERM_KEY_LEFT}, + {"Next", GRUB_TERM_KEY_NPAGE}, + {"Prior", GRUB_TERM_KEY_PPAGE}, + {"Remove", GRUB_TERM_KEY_DC}, + {"VoidSymbol", 0}, + + /* "Undead" keys since no dead key support in GRUB. */ + {"dead_acute", '\''}, + {"dead_circumflex", '^'}, + {"dead_grave", '`'}, + {"dead_tilde", '~'}, + {"dead_diaeresis", '"'}, + + /* Following ones don't provide any useful symbols for shell. */ + {"dead_cedilla", 0}, + {"dead_ogonek", 0}, + {"dead_caron", 0}, + {"dead_breve", 0}, + {"dead_doubleacute", 0}, + + /* Unused in GRUB. */ + {"Pause", 0}, + {"Scroll_Forward", 0}, + {"Scroll_Backward", 0}, + {"Hex_0", 0}, + {"Hex_1", 0}, + {"Hex_2", 0}, + {"Hex_3", 0}, + {"Hex_4", 0}, + {"Hex_5", 0}, + {"Hex_6", 0}, + {"Hex_7", 0}, + {"Hex_8", 0}, + {"Hex_9", 0}, + {"Hex_A", 0}, + {"Hex_B", 0}, + {"Hex_C", 0}, + {"Hex_D", 0}, + {"Hex_E", 0}, + {"Hex_F", 0}, + {"Scroll_Lock", 0}, + {"Show_Memory", 0}, + {"Show_Registers", 0}, + {"Control_backslash", 0}, + {"Compose", 0}, + + {NULL, '\0'} +}; + +static grub_uint8_t linux_to_usb_map[128] = { + /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, + /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, + /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, + /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, + /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, + /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, + /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, + /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, + /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, + /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, + /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, + /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, + /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, + /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, + /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, + /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, + /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, + /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, + /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, + /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, + /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, + /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, + /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, + /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, + /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, + /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, + /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, + /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, + /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, + /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, + /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, + /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, + /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, + /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, + /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, + /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, + /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, + /* 0x54 */ 0, 0, + /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, + /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, + /* 0x5a */ 0, 0, + /* 0x5c */ 0, 0, + /* 0x5e */ 0, 0, + /* 0x60 */ GRUB_KEYBOARD_KEY_NUMENTER, GRUB_KEYBOARD_KEY_RIGHT_CTRL, + /* 0x62 */ GRUB_KEYBOARD_KEY_NUMSLASH, 0, + /* 0x64 */ GRUB_KEYBOARD_KEY_RIGHT_ALT, 0, + /* 0x66 */ GRUB_KEYBOARD_KEY_HOME, GRUB_KEYBOARD_KEY_UP, + /* 0x68 */ GRUB_KEYBOARD_KEY_PPAGE, GRUB_KEYBOARD_KEY_LEFT, + /* 0x6a */ GRUB_KEYBOARD_KEY_RIGHT, GRUB_KEYBOARD_KEY_END, + /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_NPAGE, + /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE +}; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + else + printf ("\ +Usage: %s [OPTIONS] LAYOUT\n\ + -o, --output set output base name file. Default is LAYOUT.gkb\n\ + -h, --help display this message and exit.\n\ + -V, --version print version information and exit.\n\ + -v, --verbose print verbose messages.\n\ +\n\ +Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); + + exit (status); +} + +static void +add_special_keys (struct grub_keyboard_layout *layout) +{ + (void) layout; +} + +static unsigned +lookup (char *code, int shift) +{ + int i; + struct console_grub_equivalence *pr; + + if (shift) + pr = console_grub_equivalences_shift; + else + pr = console_grub_equivalences_unshift; + + for (i = 0; pr[i].layout != NULL; i++) + if (strcmp (code, pr[i].layout) == 0) + return pr[i].grub; + + for (i = 0; console_grub_equivalences_common[i].layout != NULL; i++) + if (strcmp (code, console_grub_equivalences_common[i].layout) == 0) + return console_grub_equivalences_common[i].grub; + + fprintf (stderr, "Unknown key %s\n", code); + + return '\0'; +} + +static unsigned int +get_grub_code (char *layout_code, int shift) +{ + unsigned int code; + + if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0) + sscanf (layout_code, "U+%x", &code); + else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0) + sscanf (layout_code, "+U+%x", &code); + else + code = lookup (layout_code, shift); + return code; +} + +static void +write_file (FILE *out, struct grub_keyboard_layout *layout) +{ + grub_uint32_t version; + unsigned i; + + version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++) + layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift); i++) + layout->keyboard_map_shift[i] + = grub_cpu_to_le32(layout->keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_l3); i++) + layout->keyboard_map_l3[i] + = grub_cpu_to_le32(layout->keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift_l3); i++) + layout->keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->keyboard_map_shift_l3[i]); + + fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, out); + fwrite (&version, sizeof (version), 1, out); + fwrite (layout, 1, sizeof (*layout), out); +} + +static void +write_keymaps (FILE *in, FILE *out) +{ + struct grub_keyboard_layout layout; + char line[2048]; + int ok; + + memset (&layout, 0, sizeof (layout)); + + /* Process the ckbcomp output and prepare the layouts. */ + ok = 0; + while (fgets (line, sizeof (line), in)) + { + if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) + { + unsigned keycode_linux; + unsigned keycode_usb; + char normal[64]; + char shift[64]; + char normalalt[64]; + char shiftalt[64]; + + sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_linux, + normal, shift, normalalt, shiftalt); + + /* Not used. */ + if (keycode_linux == 0x77 /* Pause */ + /* Some obscure keys */ + || keycode_linux == 0x63 || keycode_linux == 0x7d + || keycode_linux == 0x7e) + continue; + + /* Not remappable. */ + if (keycode_linux == 0x1d /* Left CTRL */ + || keycode_linux == 0x61 /* Right CTRL */ + || keycode_linux == 0x2a /* Left Shift. */ + || keycode_linux == 0x36 /* Right Shift. */ + || keycode_linux == 0x38 /* Left ALT. */ + || keycode_linux == 0x64 /* Right ALT. */ + || keycode_linux == 0x3a /* CapsLock. */ + || keycode_linux == 0x45 /* NumLock. */ + || keycode_linux == 0x46 /* ScrollLock. */) + continue; + + keycode_usb = linux_to_usb_map[keycode_linux]; + if (keycode_usb == 0 + || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + fprintf (stderr, "Unknown keycode 0x%02x\n", keycode_linux); + continue; + } + if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + layout.keyboard_map[keycode_usb] = get_grub_code (normal, 0); + layout.keyboard_map_shift[keycode_usb] = get_grub_code (shift, 1); + layout.keyboard_map_l3[keycode_usb] + = get_grub_code (normalalt, 0); + layout.keyboard_map_shift_l3[keycode_usb] + = get_grub_code (shiftalt, 1); + ok = 1; + } + } + } + + if (ok == 0) + { + fprintf (stderr, "ERROR: no keycodes found. Check output of %s.\n", + CKBCOMP); + exit (1); + } + + add_special_keys (&layout); + + write_file (out, &layout); +} + +int +main (int argc, char *argv[]) +{ + int verbosity; + char *infile_name = NULL; + char *outfile_name = NULL; + FILE *in, *out; + + set_program_name (argv[0]); + + verbosity = 0; + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "o:i:hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'i': + infile_name = optarg; + break; + + case 'o': + outfile_name = optarg; + break; + + case 'V': + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, + PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + if (infile_name) + in = fopen (infile_name, "r"); + else + in = stdin; + + if (!in) + grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); + + if (outfile_name) + out = fopen (outfile_name, "wb"); + else + out = stdout; + + if (!out) + { + if (in != stdin) + fclose (in); + grub_util_error ("Couldn't open output file: %s\n", strerror (errno)); + } + + write_keymaps (in, out); + + if (in != stdin) + fclose (in); + + if (out != stdout) + fclose (out); + + return 0; +} diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in new file mode 100644 index 000000000..b353e98b9 --- /dev/null +++ b/util/grub-mknetdir.in @@ -0,0 +1,230 @@ +#! /bin/sh + +# Install GRUB on your drive. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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 . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +sbindir=@sbindir@ +bindir=@bindir@ +libdir=@libdir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ +platform=@platform@ +host_os=@host_os@ +pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +localedir=@datadir@/locale +native_platform=@platform@ +pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" + +self=`basename $0` + +grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +rootdir=/srv/tftp +grub_prefix=`echo /boot/grub | sed ${transform}` +modules= + +install_device= +no_floppy= +recheck=no +debug=no +debug_image= +subdir=`echo /boot/grub | sed ${transform}` +pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + +# Check the arguments. +while test $# -gt 0 +do + option=$1 + shift + + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" + exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + + --net-directory) + rootdir=`argument $option "$@"`; shift;; + --net-directory=*) + rootdir=`echo "$option" | sed 's/--net-directory=//'` ;; + + --subdir) + subdir=`argument $option "$@"`; shift;; + --subdir=*) + subdir=`echo "$option" | sed 's/--subdir=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + # This is an undocumented feature... + --debug) + debug=yes ;; + --debug-image) + debug_image=`argument $option "$@"`; shift;; + --debug-image=*) + debug_image=`echo "$option" | sed 's/--debug-image=//'` ;; + + # Intentionally undocumented + --override-directory) + override_dir=`argument $option "$@"` + shift + PATH=${override_dir}:$PATH + export PATH + ;; + --override-directory=*) + override_dir=`echo "${option}/" | sed 's/--override-directory=//'` + PATH=${override_dir}:$PATH + export PATH + ;; + + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$install_device" != x; then + echo "More than one install_devices?" 1>&2 + usage + exit 1 + fi + install_device="${option}" ;; + esac +done + +set $grub_mkimage dummy +if test -f "$1"; then + : +else + echo "$1: Not found." 1>&2 + exit 1 +fi + +# Create the GRUB directory if it is not present. +mkdir -p "${rootdir}/${subdir}" || exit 1 + +process_input_dir () +{ + input_dir="$1" + platform="$2" + grubdir="${rootdir}/${subdir}/${platform}" + config_opt= + mkdir -p "$grubdir" || exit 1 + + for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do + if test -f $file && [ "`basename $file`" != menu.lst ]; then + rm -f $file || exit 1 + fi + done + for file in ${input_dir}/*.mod; do + if test -f "$file"; then + cp -f "$file" "$grubdir/" + fi + done + for file in ${pkglib_DATA}; do + if test -f "${input_dir}/${file}"; then + cp -f "${input_dir}/${file}" "$grubdir/" + fi + done + + mkdir -p "$grubdir/locale" + for file in ${input_dir}/po/*.mo; do + if test -f "$file"; then + cp -f "$file" "$grubdir/locale/" + fi + done + + rm -f ${grubdir}/load.cfg + + if [ "x${debug_image}" != x ]; then + echo "set debug='${debug_image}'" >> ${grubdir}/load.cfg + config_opt="-c ${grubdir}/load.cfg " + fi + + case "${platform}" in + i386-pc) mkimage_target=i386-pc-pxe; + netmodules="pxe"; + prefix="(pxe)/${subdir}/${platform}"; + ext=0 ;; + *) echo Unsupported platform ${platform}; + exit 1;; + esac + + cat << EOF > ${grubdir}/grub.cfg +source ${subdir}/grub.cfg +EOF + + $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1 + echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext" +} + +if [ "${override_dir}" = "" ] ; then + if test -e "${pc_dir}" ; then + process_input_dir ${pc_dir} i386-pc + fi +else + process_input_dir ${override_dir} ${target_cpu}-${native_platform} +fi + + +# Bye. +exit 0 diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index 944c6c46a..fe1887f8f 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -16,8 +16,11 @@ * along with GRUB. If not, see . */ +#include + #include #include +#include #include #include @@ -30,37 +33,6 @@ #include "progname.h" -/* Few functions to make crypto happy. */ -void * -grub_memmove (void *dest, const void *src, grub_size_t n) -{ - return memmove (dest, src, n); -} - -void * -grub_memset (void *s, int c, grub_size_t n) -{ - return memset (s, c, n); -} - -int -grub_vprintf (const char *fmt, va_list args) -{ - return vprintf (fmt, args); -} - -int -grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list args) -{ - return vsnprintf (str, n, fmt, args); -} - -void -grub_abort (void) -{ - abort (); -} - static struct option options[] = { {"iteration_count", required_argument, 0, 'c'}, diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c index eccb49cdc..3fe3fe698 100644 --- a/util/grub-mkrelpath.c +++ b/util/grub-mkrelpath.c @@ -17,6 +17,8 @@ * along with GRUB. If not, see . */ +#include + #include #include #include diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index b7d9eb4eb..690bddb30 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -2,7 +2,7 @@ set -e # Make GRUB rescue image -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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 @@ -29,7 +29,7 @@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ native_platform=@platform@ -pkglib_DATA="@pkglib_DATA@" +pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" self=`basename $0` @@ -62,7 +62,8 @@ Make GRUB rescue image. $self generates a bootable rescue image with specified source files, source directories, or mkisofs options listed by: xorriso -as mkisofs -help -Option -- switches to native xorriso command mode. or directories. + +Option -- switches to native xorriso command mode. Report bugs to . Mail xorriso support requests to . @@ -151,15 +152,7 @@ else exit 1 fi -if test "x$TMP" != x; then - MKTEMP_TEMPLATE="$TMP/grub-mkrescue.XXXXXXXXXX" -elif test "x$TEMP" != x; then - MKTEMP_TEMPLATE="$TEMP/grub-mkrescue.XXXXXXXXXX" -else - MKTEMP_TEMPLATE="/tmp/grub-mkrescue.XXXXXXXXXX" -fi - -iso9660_dir=`mktemp -d "$MKTEMP_TEMPLATE"` +iso9660_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 mkdir -p ${iso9660_dir}/boot/grub process_input_dir () @@ -196,12 +189,12 @@ make_image () echo "Enabling $2 support ..." - memdisk_img=`mktemp "$MKTEMP_TEMPLATE"` - memdisk_dir=`mktemp -d "$MKTEMP_TEMPLATE"` + memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 + memdisk_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 mkdir -p ${memdisk_dir}/boot/grub cat << EOF > ${memdisk_dir}/boot/grub/grub.cfg -search --fs-uuid --set ${iso_uuid} +search --fs-uuid --set=root ${iso_uuid} set prefix=(\${root})/boot/grub/${platform} source \$prefix/grub.cfg EOF @@ -262,12 +255,12 @@ grub_mkisofs_arguments="${grub_mkisofs_arguments} --modification-date=$(echo ${i # build BIOS core.img if test -e "${pc_dir}" ; then echo "Enabling BIOS support ..." - core_img=`mktemp "$MKTEMP_TEMPLATE"` + core_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 $grub_mkimage -O i386-pc -d ${pc_dir}/ -o ${core_img} --prefix=/boot/grub/i386-pc \ iso9660 biosdisk cat ${pc_dir}/cdboot.img ${core_img} > ${iso9660_dir}/boot/grub/i386-pc/eltorito.img - embed_img=`mktemp "$MKTEMP_TEMPLATE"` + embed_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 cat ${pc_dir}/boot.img ${core_img} > ${embed_img} rm -f ${core_img} @@ -286,7 +279,7 @@ fi make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "ata at_keyboard" if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then - efi_dir=`mktemp -d "$MKTEMP_TEMPLATE"` + efi_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 mkdir -p "${efi_dir}/efi/boot" # build bootx64.efi diff --git a/util/grub-probe.c b/util/grub-probe.c index 56cbc5592..1d00a7db3 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -34,8 +35,6 @@ #include #include -#include - #include #include #include @@ -60,26 +59,6 @@ enum { int print = PRINT_FS; static unsigned int argument_is_device = 0; -void -grub_xputs_real (const char *str) -{ - fputs (str, stdout); -} - -void (*grub_xputs) (const char *str) = grub_xputs_real; - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_refresh (void) -{ - fflush (stdout); -} - static void probe_partmap (grub_disk_t disk) { @@ -196,7 +175,8 @@ probe (const char *path, char *device_name) printf ("raid5rec "); if (is_raid6) printf ("raid6rec "); - printf ("mdraid "); + if (dev->disk->dev->raidname) + printf ("%s ", dev->disk->dev->raidname (dev->disk)); } if (is_lvm) @@ -247,48 +227,16 @@ probe (const char *path, char *device_name) if (print == PRINT_FS) { - if (path) - { - struct stat st; - - stat (path, &st); - - if (S_ISREG (st.st_mode)) - { - /* Regular file. Verify that we can read it properly. */ - - grub_file_t file; - char *rel_path; - grub_util_info ("reading %s via OS facilities", path); - filebuf_via_sys = grub_util_read_image (path); - - rel_path = grub_make_system_path_relative_to_its_root (path); - grub_path = xasprintf ("(%s)%s", drive_name, rel_path); - free (rel_path); - grub_util_info ("reading %s via GRUB facilities", grub_path); - file = grub_file_open (grub_path); - if (! file) - grub_util_error ("cannot open %s via GRUB facilities", grub_path); - filebuf_via_grub = xmalloc (file->size); - grub_file_read (file, filebuf_via_grub, file->size); - - grub_util_info ("comparing"); - - if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size)) - grub_util_error ("files differ"); - } - } - printf ("%s\n", fs->name); } - - if (print == PRINT_FS_UUID) + else if (print == PRINT_FS_UUID) { char *uuid; if (! fs->uuid) grub_util_error ("%s does not support UUIDs", fs->name); - fs->uuid (dev, &uuid); + if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); printf ("%s\n", uuid); } @@ -298,7 +246,8 @@ probe (const char *path, char *device_name) if (! fs->label) grub_util_error ("%s does not support labels", fs->name); - fs->label (dev, &label); + if (fs->label (dev, &label) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); printf ("%s\n", label); } @@ -442,6 +391,15 @@ main (int argc, char *argv[]) /* Initialize all modules. */ grub_init_all (); + grub_lvm_fini (); + grub_mdraid09_fini (); + grub_mdraid1x_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid09_init (); + grub_mdraid1x_init (); + grub_lvm_init (); + /* Do it. */ if (argument_is_device) probe (NULL, argument); diff --git a/util/grub-reboot.in b/util/grub-reboot.in index e7a41f68f..929cf5202 100644 --- a/util/grub-reboot.in +++ b/util/grub-reboot.in @@ -29,6 +29,8 @@ self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` # Usage: usage # Print the usage. @@ -39,8 +41,8 @@ Set the default boot entry for GRUB, for the next boot only. -h, --help print this message and exit -v, --version print the version information and exit - --root-directory=DIR expect GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory ENTRY is a number or a menu item title. @@ -73,11 +75,17 @@ do echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -99,21 +107,17 @@ if test "x$entry" = x; then exit 1 fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` prev_saved_entry=`$grub_editenv ${grubdir}/grubenv list | sed -n 's/^saved_entry=//p'` if [ "$prev_saved_entry" ]; then diff --git a/util/grub-script-check.c b/util/grub-script-check.c index 5e2f37dab..a872a0400 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -37,77 +38,6 @@ #include "progname.h" -void -grub_xputs_real (const char *str) -{ - fputs (str, stdout); -} - -void (*grub_xputs) (const char *str) = grub_xputs_real; - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_refresh (void) -{ - fflush (stdout); -} - -char * -grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute_cmdline (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute_cmdblock (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute_cmdif (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute_cmdfor (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute_cmdwhile (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - -grub_err_t -grub_script_execute (struct grub_script *script) -{ - if (script == 0 || script->cmd == 0) - return 0; - - return script->cmd->exec (script->cmd); -} - static struct option options[] = { {"help", no_argument, 0, 'h'}, diff --git a/util/grub-set-default.in b/util/grub-set-default.in index 389c504c7..b09727de2 100644 --- a/util/grub-set-default.in +++ b/util/grub-set-default.in @@ -29,6 +29,8 @@ self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` # Usage: usage # Print the usage. @@ -39,8 +41,8 @@ Set the default boot entry for GRUB. -h, --help print this message and exit -v, --version print the version information and exit - --root-directory=DIR expect GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory ENTRY is a number or a menu item title. @@ -73,11 +75,17 @@ do echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -99,21 +107,17 @@ if test "x$entry" = x; then exit 1 fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` $grub_editenv ${grubdir}/grubenv unset prev_saved_entry $grub_editenv ${grubdir}/grubenv set saved_entry="$entry" diff --git a/util/grub-setup.c b/util/grub-setup.c new file mode 100644 index 000000000..fa95f94aa --- /dev/null +++ b/util/grub-setup.c @@ -0,0 +1,994 @@ +/* grub-setup.c - make GRUB usable */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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 +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GRUB_MACHINE_IEEE1275 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "progname.h" +#include + +#define _GNU_SOURCE 1 +#include + +/* On SPARC this program fills in various fields inside of the 'boot' and 'core' + * image files. + * + * The 'boot' image needs to know the OBP path name of the root + * device. It also needs to know the initial block number of + * 'core' (which is 'diskboot' concatenated with 'kernel' and + * all the modules, this is created by grub-mkimage). This resulting + * 'boot' image is 512 bytes in size and is placed in the second block + * of a partition. + * + * The initial 'diskboot' block acts as a loader for the actual GRUB + * kernel. It contains the loading code and then a block list. + * + * The block list of 'core' starts at the end of the 'diskboot' image + * and works it's way backwards towards the end of the code of 'diskboot'. + * + * We patch up the images with the necessary values and write out the + * result. + */ + +#define DEFAULT_BOOT_FILE "boot.img" +#define DEFAULT_CORE_FILE "core.img" + +#ifdef GRUB_MACHINE_SPARC64 +#define grub_target_to_host16(x) grub_be_to_cpu16(x) +#define grub_target_to_host32(x) grub_be_to_cpu32(x) +#define grub_target_to_host64(x) grub_be_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_be16(x) +#define grub_host_to_target32(x) grub_cpu_to_be32(x) +#define grub_host_to_target64(x) grub_cpu_to_be64(x) +#elif defined (GRUB_MACHINE_PCBIOS) +#define grub_target_to_host16(x) grub_le_to_cpu16(x) +#define grub_target_to_host32(x) grub_le_to_cpu32(x) +#define grub_target_to_host64(x) grub_le_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_le16(x) +#define grub_host_to_target32(x) grub_cpu_to_le32(x) +#define grub_host_to_target64(x) grub_cpu_to_le64(x) +#else +#error Complete this +#endif + +static void +write_rootdev (char *core_img, grub_device_t root_dev, + char *boot_img, grub_uint64_t first_sector) +{ +#ifdef GRUB_MACHINE_PCBIOS + { + grub_int32_t *install_dos_part, *install_bsd_part; + grub_int32_t dos_part, bsd_part; + grub_uint8_t *boot_drive; + grub_disk_addr_t *kernel_sector; + boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); + kernel_sector = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_MACHINE_KERNEL_SECTOR); + + + install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); + install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); + + /* If we hardcoded drive as part of prefix, we don't want to + override the current setting. */ + if (*install_dos_part != -2) + { + /* Embed information about the installed location. */ + if (root_dev->disk->partition) + { + if (root_dev->disk->partition->parent) + { + if (root_dev->disk->partition->parent->parent) + grub_util_error ("Installing on doubly nested partitions is " + "not supported"); + dos_part = root_dev->disk->partition->parent->number; + bsd_part = root_dev->disk->partition->number; + } + else + { + dos_part = root_dev->disk->partition->number; + bsd_part = -1; + } + } + else + dos_part = bsd_part = -1; + } + else + { + dos_part = grub_le_to_cpu32 (*install_dos_part); + bsd_part = grub_le_to_cpu32 (*install_bsd_part); + } + + grub_util_info ("dos partition is %d, bsd partition is %d", + dos_part, bsd_part); + + *install_dos_part = grub_cpu_to_le32 (dos_part); + *install_bsd_part = grub_cpu_to_le32 (bsd_part); + + /* FIXME: can this be skipped? */ + *boot_drive = 0xFF; + + *kernel_sector = grub_cpu_to_le64 (first_sector); + } +#endif +#ifdef GRUB_MACHINE_IEEE1275 + { + grub_disk_addr_t *kernel_byte; + kernel_byte = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_KERNEL_BYTE); + *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); + } +#endif +} + +#ifdef GRUB_MACHINE_IEEE1275 +#define BOOT_SECTOR 1 +#else +#define BOOT_SECTOR 0 +#endif + +static void +setup (const char *dir, + const char *boot_file, const char *core_file, + const char *root, const char *dest, int must_embed, int force, + int fs_probe, int allow_floppy) +{ + char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; + char *boot_img, *core_img; + size_t boot_size, core_size; + grub_uint16_t core_sectors; + grub_device_t root_dev, dest_dev; + struct grub_boot_blocklist *first_block, *block; + char *tmp_img; + int i; + grub_disk_addr_t first_sector; +#ifdef GRUB_MACHINE_PCBIOS + grub_uint16_t current_segment + = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); +#endif + grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; + grub_file_t file; + FILE *fp; + + auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length); + auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length); + + void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length) + { + grub_util_info ("the first sector is <%llu,%u,%u>", + sector, offset, length); + + if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the first sector of the core file is not sector-aligned")); + + first_sector = sector; + } + + void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length) + { + struct grub_boot_blocklist *prev = block + 1; + + grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); + + if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("non-sector-aligned data is found in the core file")); + + if (block != first_block + && (grub_target_to_host64 (prev->start) + + grub_target_to_host16 (prev->len)) == sector) + prev->len = grub_host_to_target16 (grub_target_to_host16 (prev->len) + 1); + else + { + block->start = grub_host_to_target64 (sector); + block->len = grub_host_to_target16 (1); +#ifdef GRUB_MACHINE_PCBIOS + block->segment = grub_host_to_target16 (current_segment); +#endif + + block--; + if (block->len) + grub_util_error (_("the sectors of the core file are too fragmented")); + } + + last_length = length; +#ifdef GRUB_MACHINE_PCBIOS + current_segment += GRUB_DISK_SECTOR_SIZE >> 4; +#endif + } + + /* Read the boot image by the OS service. */ + boot_path = grub_util_get_path (dir, boot_file); + boot_size = grub_util_get_image_size (boot_path); + if (boot_size != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is not %u"), + boot_path, GRUB_DISK_SECTOR_SIZE); + boot_img = grub_util_read_image (boot_path); + free (boot_path); + + core_path = grub_util_get_path (dir, core_file); + core_size = grub_util_get_image_size (core_path); + core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS); + if (core_size < GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too small"), core_path); +#ifdef GRUB_MACHINE_PCBIOS + if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too large"), core_path); +#endif + + core_img = grub_util_read_image (core_path); + + /* Have FIRST_BLOCK to point to the first blocklist. */ + first_block = (struct grub_boot_blocklist *) (core_img + + GRUB_DISK_SECTOR_SIZE + - sizeof (*block)); + grub_util_info ("root is `%s', dest is `%s'", root, dest); + + /* Open the root device and the destination device. */ + grub_util_info ("Opening root"); + root_dev = grub_device_open (root); + if (! root_dev) + grub_util_error ("%s", grub_errmsg); + + grub_util_info ("Opening dest"); + dest_dev = grub_device_open (dest); + if (! dest_dev) + grub_util_error ("%s", grub_errmsg); + + grub_util_info ("setting the root device to `%s'", root); + if (grub_env_set ("root", root) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); + +#ifdef GRUB_MACHINE_PCBIOS + /* Read the original sector from the disk. */ + tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); + if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) + grub_util_error ("%s", grub_errmsg); +#endif + +#ifdef GRUB_MACHINE_PCBIOS + { + grub_uint16_t *boot_drive_check; + boot_drive_check = (grub_uint16_t *) (boot_img + + GRUB_BOOT_MACHINE_DRIVE_CHECK); + /* Copy the possible DOS BPB. */ + memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, + tmp_img + GRUB_BOOT_MACHINE_BPB_START, + GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); + + /* If DEST_DRIVE is a hard disk, enable the workaround, which is + for buggy BIOSes which don't pass boot drive correctly. Instead, + they pass 0x00 or 0x01 even when booted from 0x80. */ + if (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)) + /* Replace the jmp (2 bytes) with double nop's. */ + *boot_drive_check = 0x9090; + } +#endif + +#ifdef GRUB_MACHINE_PCBIOS + { + grub_partition_map_t dest_partmap = NULL; + grub_partition_t container = dest_dev->disk->partition; + int multiple_partmaps = 0; + grub_err_t err; + grub_disk_addr_t *sectors; + int i; + grub_fs_t fs; + unsigned int nsec; + + /* Unlike root_dev, with dest_dev we're interested in the partition map even + if dest_dev itself is a whole disk. */ + auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) + { + if (p->parent != container) + return 0; + if (dest_partmap == NULL) + { + dest_partmap = p->partmap; + return 0; + } + if (dest_partmap == p->partmap) + return 0; + multiple_partmaps = 1; + return 1; + } + + grub_partition_iterate (dest_dev->disk, identify_partmap); + + fs = grub_fs_probe (dest_dev); + if (!fs) + grub_errno = GRUB_ERR_NONE; + +#ifdef GRUB_MACHINE_PCBIOS + if (fs_probe) + { + if (!fs && !dest_partmap) + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), + dest_dev->disk->name); + if (fs && !fs->reserved_first_sector) + grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, fs->name); + + if (dest_partmap && strcmp (dest_partmap->name, "msdos") != 0 + && strcmp (dest_partmap->name, "gpt") != 0 + && strcmp (dest_partmap->name, "bsd") != 0 + && strcmp (dest_partmap->name, "netbsd") != 0 + && strcmp (dest_partmap->name, "openbsd") != 0 + && strcmp (dest_partmap->name, "sunpc") != 0) + grub_util_error (_("%s appears to contain a %s partition map which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name); + } +#endif + + if (! dest_partmap) + { + grub_util_warn (_("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); + goto unable_to_embed; + } + if (multiple_partmaps || fs) + { + grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); + goto unable_to_embed; + } + + /* Copy the partition table. */ + if (dest_partmap) + memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); + + free (tmp_img); + + if (!dest_partmap->embed) + { + grub_util_warn ("Partition style '%s' doesn't support embeding", + dest_partmap->name); + goto unable_to_embed; + } + + nsec = core_sectors; + err = dest_partmap->embed (dest_dev->disk, &nsec, + GRUB_EMBED_PCBIOS, §ors); + if (nsec > 2 * core_sectors) + nsec = 2 * core_sectors; + + if (err) + { + grub_util_warn ("%s", grub_errmsg); + grub_errno = GRUB_ERR_NONE; + goto unable_to_embed; + } + + /* Clean out the blocklists. */ + block = first_block; + while (block->len) + { + grub_memset (block, 0, sizeof (block)); + + block--; + + if ((char *) block <= core_img) + grub_util_error ("No terminator in the core image"); + } + + save_first_sector (sectors[0] + grub_partition_get_start (container), + 0, GRUB_DISK_SECTOR_SIZE); + + block = first_block; + for (i = 1; i < nsec; i++) + save_blocklists (sectors[i] + grub_partition_get_start (container), + 0, GRUB_DISK_SECTOR_SIZE); + + write_rootdev (core_img, root_dev, boot_img, first_sector); + + core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE); + first_block = (struct grub_boot_blocklist *) (core_img + + GRUB_DISK_SECTOR_SIZE + - sizeof (*block)); + + *(grub_uint32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY) + = grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size); + + grub_reed_solomon_add_redundancy (core_img + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + GRUB_DISK_SECTOR_SIZE, + core_size - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - GRUB_DISK_SECTOR_SIZE, + nsec * GRUB_DISK_SECTOR_SIZE + - core_size); + + /* Make sure that the second blocklist is a terminator. */ + block = first_block - 1; + block->start = 0; + block->len = 0; + block->segment = 0; + + /* Write the core image onto the disk. */ + for (i = 0; i < nsec; i++) + grub_disk_write (dest_dev->disk, sectors[i], 0, + GRUB_DISK_SECTOR_SIZE, + core_img + i * GRUB_DISK_SECTOR_SIZE); + + grub_free (sectors); + + goto finish; + } +#endif + +unable_to_embed: + + if (must_embed) + grub_util_error (_("embedding is not possible, but this is required when " + "the root device is on a RAID array or LVM volume")); + +#ifdef GRUB_MACHINE_PCBIOS + if (dest_dev->disk->id != root_dev->disk->id) + grub_util_error (_("embedding is not possible, but this is required for " + "cross-disk install")); +#endif + + grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this " + "setup by using blocklists. However, blocklists are UNRELIABLE and " + "their use is discouraged.")); + if (! force) + grub_util_error (_("if you really want blocklists, use --force")); + + /* The core image must be put on a filesystem unfortunately. */ + grub_util_info ("will leave the core image on the filesystem"); + + /* Make sure that GRUB reads the identical image as the OS. */ + tmp_img = xmalloc (core_size); + core_path_dev_full = grub_util_get_path (dir, core_file); + core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full); + free (core_path_dev_full); + + /* It is a Good Thing to sync two times. */ + sync (); + sync (); + +#define MAX_TRIES 5 + + for (i = 0; i < MAX_TRIES; i++) + { + grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB") + : _("attempting to read the core image `%s' from GRUB again"), + core_path_dev); + + grub_disk_cache_invalidate_all (); + + grub_file_filter_disable_compression (); + file = grub_file_open (core_path_dev); + if (file) + { + if (grub_file_size (file) != core_size) + grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", + (int) grub_file_size (file), (int) core_size); + else if (grub_file_read (file, tmp_img, core_size) + != (grub_ssize_t) core_size) + grub_util_info ("succeeded in opening the core image but cannot read %d bytes", + (int) core_size); + else if (memcmp (core_img, tmp_img, core_size) != 0) + { +#if 0 + FILE *dump; + FILE *dump2; + + dump = fopen ("dump.img", "wb"); + if (dump) + { + fwrite (tmp_img, 1, core_size, dump); + fclose (dump); + } + + dump2 = fopen ("dump2.img", "wb"); + if (dump2) + { + fwrite (core_img, 1, core_size, dump2); + fclose (dump2); + } + +#endif + grub_util_info ("succeeded in opening the core image but the data is different"); + } + else + { + grub_file_close (file); + break; + } + + grub_file_close (file); + } + else + grub_util_info ("couldn't open the core image"); + + if (grub_errno) + grub_util_info ("error message = %s", grub_errmsg); + + grub_errno = GRUB_ERR_NONE; + sync (); + sleep (1); + } + + if (i == MAX_TRIES) + grub_util_error (_("cannot read `%s' correctly"), core_path_dev); + + /* Clean out the blocklists. */ + block = first_block; + while (block->len) + { + block->start = 0; + block->len = 0; +#ifdef GRUB_MACHINE_PCBIOS + block->segment = 0; +#endif + + block--; + + if ((char *) block <= core_img) + grub_util_error (_("no terminator in the core image")); + } + + /* Now read the core image to determine where the sectors are. */ + grub_file_filter_disable_compression (); + file = grub_file_open (core_path_dev); + if (! file) + grub_util_error ("%s", grub_errmsg); + + file->read_hook = save_first_sector; + if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) + != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("failed to read the first sector of the core image")); + + block = first_block; + file->read_hook = save_blocklists; + if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) + != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("failed to read the rest sectors of the core image")); + +#ifdef GRUB_MACHINE_IEEE1275 + { + char *boot_devpath; + boot_devpath = (char *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_BOOT_DEVPATH); + if (file->device->disk->id != dest_dev->disk->id) + { + const char *dest_ofpath; + dest_ofpath + = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); + grub_util_info ("dest_ofpath is `%s'", dest_ofpath); + strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); + boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; + } + else + { + grub_util_info ("non cross-disk install"); + memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH); + } + grub_util_info ("boot device path %s", boot_devpath); + } +#endif + + grub_file_close (file); + + free (core_path_dev); + free (tmp_img); + + write_rootdev (core_img, root_dev, boot_img, first_sector); + + /* Write the first two sectors of the core image onto the disk. */ + grub_util_info ("opening the core image `%s'", core_path); + fp = fopen (core_path, "r+b"); + if (! fp) + grub_util_error (_("cannot open `%s'"), core_path); + + grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); + fclose (fp); + + finish: + + /* Write the boot image onto the disk. */ + if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, + 0, GRUB_DISK_SECTOR_SIZE, boot_img)) + grub_util_error ("%s", grub_errmsg); + + + /* Sync is a Good Thing. */ + sync (); + + free (core_path); + free (core_img); + free (boot_img); + grub_device_close (dest_dev); + grub_device_close (root_dev); +} + +static struct argp_option options[] = { + {"boot-image", 'b', N_("FILE"), 0, + N_("Use FILE as the boot image [default=%s]"), 0}, + {"core-image", 'c', N_("FILE"), 0, + N_("Use FILE as the core image [default=%s]"), 0}, + {"directory", 'd', N_("DIR"), 0, + N_("Use GRUB files in the directory DIR [default=%s]"), 0}, + {"device-map", 'm', N_("FILE"), 0, + N_("Use FILE as the device map [default=%s]"), 0}, + {"root-device", 'r', N_("DEV"), 0, + N_("Use DEV as the root device [default=guessed]"), 0}, + {"force", 'f', 0, 0, + N_("Install even if problems are detected"), 0}, + {"skip-fs-probe",'s',0, 0, + N_("Do not probe for filesystems in DEVICE"), 0}, + {"verbose", 'v', 0, 0, + N_("Print verbose messages."), 0}, + {"allow-floppy", 'a', 0, 0, + N_("Make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0}, + + { 0, 0, 0, 0, 0, 0 } +}; + +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) +{ + switch (key) + { + case 'b': + return xasprintf (text, DEFAULT_BOOT_FILE); + + case 'c': + return xasprintf (text, DEFAULT_CORE_FILE); + + case 'd': + return xasprintf (text, DEFAULT_DIRECTORY); + + case 'm': + return xasprintf (text, DEFAULT_DEVICE_MAP); + + default: + return (char *) text; + } +} + +struct arguments +{ + char *boot_file; + char *core_file; + char *dir; + char *dev_map; + char *root_dev; + int force; + int fs_probe; + int allow_floppy; + char *device; +}; + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); +} +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Set the bug report address */ +const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + char *p; + + switch (key) + { + case 'a': + arguments->allow_floppy = 1; + break; + + case 'b': + if (arguments->boot_file) + free (arguments->boot_file); + + arguments->boot_file = xstrdup (arg); + break; + + case 'c': + if (arguments->core_file) + free (arguments->core_file); + + arguments->core_file = xstrdup (arg); + break; + + case 'd': + if (arguments->dir) + free (arguments->dir); + + arguments->dir = xstrdup (arg); + break; + + case 'm': + if (arguments->dev_map) + free (arguments->dev_map); + + arguments->dev_map = xstrdup (arg); + break; + + case 'r': + if (arguments->root_dev) + free (arguments->root_dev); + + arguments->root_dev = xstrdup (arg); + break; + + case 'f': + arguments->force = 1; + break; + + case 's': + arguments->fs_probe = 0; + break; + + case 'v': + verbosity++; + break; + + case ARGP_KEY_ARG: + if (state->arg_num == 0) + arguments->device = xstrdup(arg); + else + { + /* Too many arguments. */ + fprintf (stderr, _("Unknown extra argument `%s'.\n"), arg); + argp_usage (state); + } + break; + + case ARGP_KEY_NO_ARGS: + fprintf (stderr, "%s", _("No device is specified.\n")); + argp_usage (state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { + options, argp_parser, N_("DEVICE"), + "\n"N_("\ +Set up images to boot from DEVICE.\n\ +\n\ +You should not normally run this program directly. Use grub-install instead.") +"\v"N_("\ +DEVICE must be an OS device (e.g. /dev/sda)."), + NULL, help_filter, NULL +}; + +static char * +get_device_name (char *dev) +{ + size_t len = strlen (dev); + + if (dev[0] != '(' || dev[len - 1] != ')') + return 0; + + dev[len - 1] = '\0'; + return dev + 1; +} + +int +main (int argc, char *argv[]) +{ + char *root_dev = NULL; + char *dest_dev = NULL; + int must_embed = 0; + struct arguments arguments; + + set_program_name (argv[0]); + + grub_util_init_nls (); + + /* Default option values. */ + memset (&arguments, 0, sizeof (struct arguments)); + arguments.fs_probe = 1; + + /* Parse our arguments */ + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) + { + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); + } + +#ifdef GRUB_MACHINE_IEEE1275 + arguments.force = 1; +#endif + + if (verbosity > 1) + grub_env_set ("debug", "all"); + + /* Initialize the emulated biosdisk driver. */ + grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP); + + /* Initialize all modules. */ + grub_init_all (); + + grub_lvm_fini (); + grub_mdraid09_fini (); + grub_mdraid1x_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid09_init (); + grub_mdraid1x_init (); + grub_lvm_init (); + + dest_dev = get_device_name (arguments.device); + if (! dest_dev) + { + /* Possibly, the user specified an OS device file. */ + dest_dev = grub_util_get_grub_dev (arguments.device); + if (! dest_dev) + { + char *program = xstrdup(program_name); + fprintf (stderr, _("Invalid device `%s'.\n"), arguments.device); + argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); + free(program); + exit(1); + } + grub_util_info ("transformed OS device `%s' into GRUB device `%s'", + arguments.device, dest_dev); + } + else + { + /* For simplicity. */ + dest_dev = xstrdup (dest_dev); + grub_util_info ("Using `%s' as GRUB device", dest_dev); + } + + if (arguments.root_dev) + { + root_dev = get_device_name (arguments.root_dev); + + if (! root_dev) + grub_util_error (_("invalid root device `%s'"), arguments.root_dev); + + root_dev = xstrdup (root_dev); + } + else + { + char *root_device = + grub_guess_root_device (arguments.dir ? : DEFAULT_DIRECTORY); + + root_dev = grub_util_get_grub_dev (root_device); + if (! root_dev) + { + grub_util_info ("guessing the root device failed, because of `%s'", + grub_errmsg); + grub_util_error (_("cannot guess the root device. Specify the option " + "`--root-device'")); + } + grub_util_info ("guessed root device `%s' and root_dev `%s' from " + "dir `%s'", root_device, root_dev, + arguments.dir ? : DEFAULT_DIRECTORY); + } + +#ifdef __linux__ + if (grub_util_lvm_isvolume (root_dev)) + must_embed = 1; + + if (root_dev[0] == 'm' && root_dev[1] == 'd' + && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/')) + { + /* FIXME: we can avoid this on RAID1. */ + must_embed = 1; + } + + if (dest_dev[0] == 'm' && dest_dev[1] == 'd' + && ((dest_dev[2] >= '0' && dest_dev[2] <= '9') || dest_dev[2] == '/')) + { + char **devicelist; + int i; + + devicelist = grub_util_raid_getmembers (dest_dev); + + for (i = 0; devicelist[i]; i++) + { + setup (arguments.dir ? : DEFAULT_DIRECTORY, + arguments.boot_file ? : DEFAULT_BOOT_FILE, + arguments.core_file ? : DEFAULT_CORE_FILE, + root_dev, grub_util_get_grub_dev (devicelist[i]), 1, + arguments.force, arguments.fs_probe, + arguments.allow_floppy); + } + } + else +#endif + /* Do the real work. */ + setup (arguments.dir ? : DEFAULT_DIRECTORY, + arguments.boot_file ? : DEFAULT_BOOT_FILE, + arguments.core_file ? : DEFAULT_CORE_FILE, + root_dev, dest_dev, must_embed, arguments.force, + arguments.fs_probe, arguments.allow_floppy); + + /* Free resources. */ + grub_fini_all (); + grub_util_biosdisk_fini (); + + free (arguments.boot_file); + free (arguments.core_file); + free (arguments.dir); + free (arguments.root_dev); + free (arguments.dev_map); + free (arguments.device); + free (root_dev); + free (dest_dev); + + return 0; +} diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 2f39650e9..9ed3fc3a1 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -247,6 +247,12 @@ else make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}" fi +if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ] && [ "x$GRUB_BUTTON_CMOS_CLEAN" = "xyes" ]; then + cat < /dev/null + fi + fi + + if [ -z "${prepare_module_dir_cache}" ]; then + prepare_module_dir_cache="$(prepare_grub_to_access_device $(grub-probe -t device "${module_dir}") | sed -e "s/^/\t/")" + fi + + printf '%s\n' "${prepare_module_dir_cache}" + cat << EOF + kfreebsd_module_elf ${module_dir_rel}/${mod}.ko +EOF +} + kfreebsd_entry () { os="$1" version="$2" - recovery="$3" # not used yet - args="$4" # not used yet - title="$(gettext_quoted "%s, with kFreeBSD %s")" + recovery="$3" + args="$4" + if ${recovery} ; then + title="$(gettext_quoted "%s, with kFreeBSD %s (recovery mode)")" + else + title="$(gettext_quoted "%s, with kFreeBSD %s")" + fi printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}" - save_default_entry | sed -e "s/^/\t/" + if ! ${recovery} ; then + save_default_entry | sed -e "s/^/\t/" + fi if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi - if [ -z "${prepare_module_dir_cache}" ]; then - prepare_module_dir_cache="$(prepare_grub_to_access_device $(grub-probe -t device "${module_dir}") | sed -e "s/^/\t/")" - fi printf '%s\n' "${prepare_boot_cache}" cat << EOF echo '$(printf "$(gettext_quoted "Loading kernel of FreeBSD %s ...")" ${version})' - kfreebsd ${rel_dirname}/${basename} + kfreebsd ${rel_dirname}/${basename} ${args} EOF if test -n "${devices}" ; then @@ -67,25 +95,13 @@ EOF EOF fi - if test -e "${module_dir}/acpi.ko" ; then - printf '%s\n' "${prepare_module_dir_cache}" - cat << EOF - kfreebsd_module_elf ${module_dir_rel}/acpi.ko -EOF - fi + load_kfreebsd_module acpi true case "${kfreebsd_fs}" in zfs) - test -e "${module_dir}/opensolaris.ko" - test -e "${module_dir}/zfs.ko" - test -e "${dirname}/zfs/zpool.cache" - - printf '%s\n' "${prepare_module_dir_cache}" - cat << EOF - kfreebsd_module_elf ${module_dir_rel}/opensolaris.ko - kfreebsd_module_elf ${module_dir_rel}/zfs.ko -EOF + load_kfreebsd_module opensolaris false + ls "${dirname}/zfs/zpool.cache" > /dev/null printf '%s\n' "${prepare_boot_cache}" cat << EOF kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache @@ -93,6 +109,8 @@ EOF ;; esac + load_kfreebsd_module ${kfreebsd_fs} false + cat << EOF set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${kfreebsd_device} set kFreeBSD.vfs.root.mountfrom.options=rw @@ -120,13 +138,28 @@ while [ "x$list" != "x" ] ; do fi case ${GRUB_FS} in - ufs1 | ufs2) kfreebsd_fs=ufs ;; - *) kfreebsd_fs=${GRUB_FS} ;; + ufs1 | ufs2) kfreebsd_fs=ufs ;; + ext2) kfreebsd_fs=ext2fs ;; + *) kfreebsd_fs=${GRUB_FS} ;; esac case ${GRUB_FS} in - zfs) kfreebsd_device=$(grub-probe -t label --device ${GRUB_DEVICE}) ;; - *) kfreebsd_device=${GRUB_DEVICE} ;; + zfs) + # zpool name + kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE}) + # filesystem name (empty string for the main filesystem) + kfreebsd_device="${kfreebsd_device}$(grub-mkrelpath / | sed -e "s,/*@$,,")" + ;; + *) + kfreebsd_device=${kfreebsd_fs}id/${GRUB_DEVICE_UUID} + # Debian GNU/kFreeBSD can't remount root if it's supplied as UUID but + # as an UUID + if [ "x${GRUB_DISTRIBUTOR}" = "xDebian" ] \ + && ! (cat /etc/fstab | awk '!/^[[:space:]]*#/ && $2=="/" { print $1; }' \ + | grep "${kfreebsd_fs}id/${GRUB_DEVICE_UUID}" > /dev/null); then + kfreebsd_device=${GRUB_DEVICE} + fi + ;; esac version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"` @@ -145,7 +178,10 @@ while [ "x$list" != "x" ] ; do module_dir_rel=$(make_system_path_relative_to_its_root $module_dir) fi - kfreebsd_entry "${OS}" "${version}" + kfreebsd_entry "${OS}" "${version}" false + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then + kfreebsd_entry "${OS}" "${version}" true "-s" + fi list=`echo $list | tr ' ' '\n' | grep -vx $kfreebsd | tr '\n' ' '` done diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 14b85c7f1..7650ac9fa 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -63,7 +63,9 @@ linux_entry () title="$(gettext_quoted "%s, with Linux %s")" fi printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}" - save_default_entry | sed -e "s/^/\t/" + if ! ${recovery} ; then + save_default_entry | sed -e "s/^/\t/" + fi # Use ELILO's generic "efifb" when it's known to be available. # FIXME: We need an interface to select vesafb in case efifb can't be used. @@ -78,6 +80,11 @@ EOF EOF fi else + if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then + cat << EOF + load_video +EOF + fi cat << EOF set gfxpayload=$GRUB_GFXPAYLOAD_LINUX EOF @@ -102,7 +109,7 @@ EOF EOF } -list=`for i in /boot/vmlinu[zx]-* /vmlinu[zx]-* ; do +list=`for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* ; do if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi done` prepare_boot_cache= @@ -127,16 +134,26 @@ while [ "x$list" != "x" ] ; do break fi done + + initramfs= + for i in "config-${version}" "config-${alt_version}"; do + if test -e "${dirname}/${i}" ; then + initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${dirname}/${i}" | cut -f2 -d= | tr -d \"` + break + fi + done + if test -n "${initrd}" ; then echo "Found initrd image: ${dirname}/${initrd}" >&2 - else - # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here. + elif test -z "${initramfs}" ; then + # "UUID=" magic is parsed by initrd or initramfs. Since there's + # no initrd or builtin initramfs, it can't work here. linux_root_device_thisversion=${GRUB_DEVICE} fi linux_entry "${OS}" "${version}" false \ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then linux_entry "${OS}" "${version}" true \ "single ${GRUB_CMDLINE_LINUX}" fi diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in index 1a8c4eb36..13f9d923a 100644 --- a/util/grub.d/10_netbsd.in +++ b/util/grub.d/10_netbsd.in @@ -80,7 +80,7 @@ for k in $(ls -t /netbsd*) ; do echo "Found NetBSD kernel: $k" >&2 netbsd_entry "knetbsd" "$k" false "${GRUB_CMDLINE_NETBSD_DEFAULT}" netbsd_entry "multiboot" "$k" false "${GRUB_CMDLINE_NETBSD_DEFAULT}" - if [ "x${GRUB_DISABLE_NETBSD_RECOVERY}" != "xtrue" ]; then + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then netbsd_entry "knetbsd" "$k" true "-s" netbsd_entry "multiboot" "$k" true "-s" fi diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index e631c0a4a..649ae85dd 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -65,7 +65,9 @@ linux_entry () title="$(gettext_quoted "%s, with Linux %s and XEN %s")" fi printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}" "${xen_version}" - save_default_entry | sed -e "s/^/\t/" + if ! ${recovery} ; then + save_default_entry | sed -e "s/^/\t/" + fi if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" @@ -104,6 +106,7 @@ while [ "x${xen_list}" != "x" ] ; do xen_dirname=`dirname ${current_xen}` rel_xen_dirname=`make_system_path_relative_to_its_root $xen_dirname` xen_version=`echo $xen_basename | sed -e "s,.gz$,,g;s,^xen-,,g"` + echo "submenu \"Xen ${xen_version}\" {" while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` echo "Found linux image: $linux" >&2 @@ -132,12 +135,13 @@ while [ "x${xen_list}" != "x" ] ; do linux_entry "${OS}" "${version}" "${xen_version}" false \ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}" - if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then + if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then linux_entry "${OS}" "${version}" "${xen_version}" true \ "single ${GRUB_CMDLINE_LINUX}" "${GRUB_CMDLINE_XEN}" fi list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` done + echo "}" xen_list=`echo $xen_list | tr ' ' '\n' | grep -vx $current_xen | tr '\n' ' '` done diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index ecd87bb1c..728ac2378 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -40,7 +40,7 @@ fi osx_entry() { cat << EOF -menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" { +menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" --class osx --class darwin --class os { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" @@ -105,7 +105,7 @@ for OS in ${OSPROBED} ; do chain) cat << EOF -menuentry "${LONGNAME} (on ${DEVICE})" { +menuentry "${LONGNAME} (on ${DEVICE})" --class windows --class os { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" @@ -147,7 +147,7 @@ EOF fi cat << EOF -menuentry "${LLABEL} (on ${DEVICE})" { +menuentry "${LLABEL} (on ${DEVICE})" --class gnu-linux --class gnu --class os { EOF save_default_entry | sed -e "s/^/\t/" if [ -z "${prepare_boot_cache}" ]; then @@ -174,12 +174,12 @@ EOF ;; hurd) cat << EOF -menuentry "${LONGNAME} (on ${DEVICE})" { +menuentry "${LONGNAME} (on ${DEVICE})" --class hurd --class gnu --class os { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" grub_device="`${grub_probe} --device ${DEVICE} --target=drive`" - mach_device="`echo "${grub_device}" | tr -d '()' | tr , s`" + mach_device="`echo "${grub_device}" | sed -e 's/(\(hd.*\),msdos\(.*\))/\1s\2/'`" grub_fs="`${grub_probe} --device ${DEVICE} --target=fs`" case "${grub_fs}" in *fs) hurd_fs="${grub_fs}" ;; diff --git a/util/i386/efi/grub-install.in b/util/i386/efi/grub-install.in deleted file mode 100644 index d8554a328..000000000 --- a/util/i386/efi/grub-install.in +++ /dev/null @@ -1,261 +0,0 @@ -#! /bin/sh - -# Install GRUB on your EFI partition. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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 . - -# Initialize some variables. -transform="@program_transform_name@" - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -host_os=@host_os@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` -localedir=@datadir@/locale - -self=`basename $0` - -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` -rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` -modules= - -no_floppy= -force_lba= -recheck=no -debug=no - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 - exit 1 - fi - echo $1 -} - -# Check the arguments. -while test $# -gt 0 -do - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - - --modules) - modules=`argument $option "$@"`; shift ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - - --root-directory) - rootdir=`argument $option "$@"`; shift ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - - --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - - --grub-probe) - grub_probe=`argument $option "$@"`; shift ;; - --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; - - --no-floppy) - no_floppy="--no-floppy" ;; - --recheck) - recheck=yes ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - *) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - esac -done - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac - -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map - -# Check if GRUB is installed. -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -set $grub_mkdevicemap dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 - -# If --recheck is specified, remove the device map, if present. -if test $recheck = yes; then - rm -f $device_map -fi - -# Create the device map file if it is not present. -if test -f "$device_map"; then - : -else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 -fi - -# Make sure that there is no duplicated entry. -tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \ - | sort | uniq -d | sed -n 1p` -if test -n "$tmp"; then - echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 - exit 1 -fi - -# Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst; do - if test -f $file && [ "`basename $file`" != menu.lst ]; then - rm -f $file || exit 1 - fi -done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do - cp -f $file ${grubdir} || exit 1 -done - -# Copy gettext files -mkdir -p ${grubdir}/locale/ -for dir in ${localedir}/*; do - if test -f "$dir/LC_MESSAGES/grub.mo"; then - cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" - fi -done - -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}` -if test "x$fs_module" = xfat; then :; else - echo "${grubdir} doesn't look like an EFI partition." 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` - -# The order in this list is critical. Be careful when modifying it. -modules="$modules $fs_module $partmap_module $devabstraction_module" - -$grub_mkimage -p "" -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1 - -# Prompt the user to check if the device map is correct. -echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`$self'." -echo - -cat $device_map - -# Bye. -exit 0 diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c deleted file mode 100644 index 524572fad..000000000 --- a/util/i386/pc/grub-setup.c +++ /dev/null @@ -1,857 +0,0 @@ -/* grub-setup.c - make GRUB usable */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "progname.h" - -#define _GNU_SOURCE 1 -#include - -#define DEFAULT_BOOT_FILE "boot.img" -#define DEFAULT_CORE_FILE "core.img" - -#define grub_target_to_host16(x) grub_le_to_cpu16(x) -#define grub_target_to_host32(x) grub_le_to_cpu32(x) -#define grub_target_to_host64(x) grub_le_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_le16(x) -#define grub_host_to_target32(x) grub_cpu_to_le32(x) -#define grub_host_to_target64(x) grub_cpu_to_le64(x) - -void -grub_xputs_real (const char *str) -{ - fputs (str, stdout); -} - -void (*grub_xputs) (const char *str) = grub_xputs_real; - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_refresh (void) -{ - fflush (stdout); -} - -static void -setup (const char *dir, - const char *boot_file, const char *core_file, - const char *root, const char *dest, int must_embed, int force, int fs_probe) -{ - char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; - char *boot_img, *core_img; - size_t boot_size, core_size; - grub_uint16_t core_sectors; - grub_device_t root_dev, dest_dev; - const char *dest_partmap; - int multiple_partmaps; - grub_uint8_t *boot_drive; - grub_disk_addr_t *kernel_sector; - grub_uint16_t *boot_drive_check; - struct grub_boot_blocklist *first_block, *block; - grub_int32_t *install_dos_part, *install_bsd_part; - grub_int32_t dos_part, bsd_part; - char *install_prefix; - char *prefix = NULL; - char *tmp_img; - int i; - grub_disk_addr_t first_sector; - grub_uint16_t current_segment - = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); - grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; - grub_file_t file; - FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; - - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length); - - auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - /* There's always an embed region, and it starts right after the MBR. */ - embed_region.start = 1; - - if (embed_region.end > grub_partition_get_start (p)) - embed_region.end = grub_partition_get_start (p); - - return 0; - } - - auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - struct grub_gpt_partentry gptdata; - - disk->partition = p->parent; - if (grub_disk_read (disk, p->offset, p->index, - sizeof (gptdata), &gptdata)) - return 0; - - /* If there's an embed region, it is in a dedicated partition. */ - if (! memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) - { - embed_region.start = grub_partition_get_start (p); - embed_region.end = grub_partition_get_start (p) + grub_partition_get_len (p); - - return 1; - } - return 0; - } - - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - grub_util_info ("the first sector is <%llu,%u,%u>", - sector, offset, length); - - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the first sector of the core file is not sector-aligned")); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - struct grub_boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x", - sector, offset, length, (unsigned) current_segment); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("non-sector-aligned data is found in the core file")); - - if (block != first_block - && (grub_le_to_cpu64 (prev->start) - + grub_le_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_le64 (sector); - block->len = grub_cpu_to_le16 (1); - block->segment = grub_cpu_to_le16 (current_segment); - - block--; - if (block->len) - grub_util_error (_("the sectors of the core file are too fragmented")); - } - - last_length = length; - current_segment += GRUB_DISK_SECTOR_SIZE >> 4; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is not %u"), - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); - kernel_sector = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_MACHINE_KERNEL_SECTOR); - boot_drive_check = (grub_uint16_t *) (boot_img - + GRUB_BOOT_MACHINE_DRIVE_CHECK); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too small"), core_path); - else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too large"), core_path); - - core_img = grub_util_read_image (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct grub_boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); - install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); - install_prefix = (char *) (core_img + GRUB_DISK_SECTOR_SIZE + - GRUB_KERNEL_MACHINE_PREFIX); - - /* Open the root device and the destination device. */ - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* Read the original sector from the disk. */ - tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); - if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) - grub_util_error ("%s", grub_errmsg); - - if (dest_dev->disk->partition && fs_probe) - { - grub_fs_t fs; - fs = grub_fs_probe (dest_dev); - if (! fs) - grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), - dest_dev->disk->name); - - if (! fs->reserved_first_sector) - grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, fs->name); - } - - /* Copy the possible DOS BPB. */ - memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, - tmp_img + GRUB_BOOT_MACHINE_BPB_START, - GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); - - /* Copy the possible partition table. */ - if (dest_dev->disk->has_partitions) - memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - - free (tmp_img); - - /* If DEST_DRIVE is a hard disk, enable the workaround, which is - for buggy BIOSes which don't pass boot drive correctly. Instead, - they pass 0x00 or 0x01 even when booted from 0x80. */ - if (dest_dev->disk->id & 0x80) - /* Replace the jmp (2 bytes) with double nop's. */ - *boot_drive_check = 0x9090; - - /* If we hardcoded drive as part of prefix, we don't want to - override the current setting. */ - if (*install_dos_part != -2) - { - /* Embed information about the installed location. */ - if (root_dev->disk->partition) - { - if (root_dev->disk->partition->parent) - { - if (root_dev->disk->partition->parent->parent) - grub_util_error ("Installing on doubly nested partitions is " - "not supported"); - dos_part = root_dev->disk->partition->parent->number; - bsd_part = root_dev->disk->partition->number; - } - else - { - dos_part = root_dev->disk->partition->number; - bsd_part = -1; - } - - if (install_prefix[0] != '(') - { - char *root_part_name; - - root_part_name = - grub_partition_get_name (root_dev->disk->partition); - prefix = xasprintf ("(,%s)%s", root_part_name, install_prefix); - free (root_part_name); - } - } - else - dos_part = bsd_part = -1; - } - else - { - dos_part = grub_le_to_cpu32 (*install_dos_part); - bsd_part = grub_le_to_cpu32 (*install_bsd_part); - } - - grub_util_info ("dos partition is %d, bsd partition is %d", - dos_part, bsd_part); - - if (! dest_dev->disk->has_partitions) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - - if (dest_dev->disk->partition) - { - grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); - goto unable_to_embed; - } - - /* Unlike root_dev, with dest_dev we're interested in the partition map even - if dest_dev itself is a whole disk. */ - auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - if (p->parent) - return 0; - if (dest_partmap == NULL) - dest_partmap = p->partmap->name; - else if (strcmp (dest_partmap, p->partmap->name) != 0) - { - multiple_partmaps = 1; - return 1; - } - return 0; - } - dest_partmap = 0; - multiple_partmaps = 0; - grub_partition_iterate (dest_dev->disk, identify_partmap); - - if (! dest_partmap) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - if (multiple_partmaps) - { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); - goto unable_to_embed; - } - - if (strcmp (dest_partmap, "msdos") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); - else if (strcmp (dest_partmap, "gpt") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); - else - grub_util_error (_("No DOS-style partitions found")); - - if (embed_region.end <= embed_region.start) - { - if (! strcmp (dest_partmap, "msdos")) - grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); - else - grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); - goto unable_to_embed; - } - - if ((unsigned long) core_sectors > embed_region.end - embed_region.start) - { - if (core_sectors > 62) - grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); - else /* embed_region.end - embed_region.start < 62 */ - grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); - goto unable_to_embed; - } - - - grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); - - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); - if (prefix) - strcpy (install_prefix, prefix); - - /* The first blocklist contains the whole sectors. */ - first_block->start = grub_cpu_to_le64 (embed_region.start + 1); - - /* These are filled elsewhere. Verify them just in case. */ - assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); - assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG - + (GRUB_DISK_SECTOR_SIZE >> 4))); - - /* Make sure that the second blocklist is a terminator. */ - block = first_block - 1; - block->start = 0; - block->len = 0; - block->segment = 0; - - /* Write the core image onto the disk. */ - if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) - grub_util_error ("%s", grub_errmsg); - - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *kernel_sector = grub_cpu_to_le64 (embed_region.start); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, - boot_img)) - grub_util_error ("%s", grub_errmsg); - - goto finish; - -unable_to_embed: - - if (must_embed) - grub_util_error (_("embedding is not possible, but this is required when " - "the root device is on a RAID array or LVM volume")); - - grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this " - "setup by using blocklists. However, blocklists are UNRELIABLE and " - "their use is discouraged.")); - if (! force) - grub_util_error (_("if you really want blocklists, use --force")); - - /* Make sure that GRUB reads the identical image as the OS. */ - tmp_img = xmalloc (core_size); - core_path_dev_full = grub_util_get_path (dir, core_file); - core_path_dev = grub_make_system_path_relative_to_its_root (core_path_dev_full); - free (core_path_dev_full); - - /* It is a Good Thing to sync two times. */ - sync (); - sync (); - -#define MAX_TRIES 5 - - for (i = 0; i < MAX_TRIES; i++) - { - grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB") - : _("attempting to read the core image `%s' from GRUB again"), - core_path_dev); - - grub_disk_cache_invalidate_all (); - - file = grub_file_open (core_path_dev); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { -#if 0 - FILE *dump; - FILE *dump2; - - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } - - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } - -#endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } - - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); - - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); - - grub_errno = GRUB_ERR_NONE; - sync (); - sleep (1); - } - - if (i == MAX_TRIES) - grub_util_error (_("cannot read `%s' correctly"), core_path_dev); - - /* Clean out the blocklists. */ - block = first_block; - while (block->len) - { - block->start = 0; - block->len = 0; - block->segment = 0; - - block--; - - if ((char *) block <= core_img) - grub_util_error (_("no terminator in the core image")); - } - - /* Now read the core image to determine where the sectors are. */ - file = grub_file_open (core_path_dev); - if (! file) - grub_util_error ("%s", grub_errmsg); - - file->read_hook = save_first_sector; - if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("failed to read the first sector of the core image")); - - block = first_block; - file->read_hook = save_blocklists; - if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) - != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("failed to read the rest sectors of the core image")); - - grub_file_close (file); - - free (core_path_dev); - free (tmp_img); - - *kernel_sector = grub_cpu_to_le64 (first_sector); - - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); - if (prefix) - strcpy (install_prefix, prefix); - - /* Write the first two sectors of the core image onto the disk. */ - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "r+b"); - if (! fp) - grub_util_error (_("cannot open `%s'"), core_path); - - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); - fclose (fp); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - - finish: - - /* Sync is a Good Thing. */ - sync (); - - free (prefix); - free (core_path); - free (core_img); - free (boot_img); - grub_device_close (dest_dev); - grub_device_close (root_dev); -} - -static struct option options[] = - { - {"boot-image", required_argument, 0, 'b'}, - {"core-image", required_argument, 0, 'c'}, - {"directory", required_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"root-device", required_argument, 0, 'r'}, - {"force", no_argument, 0, 'f'}, - {"skip-fs-probe", no_argument, 0, 's'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) -{ - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [OPTION]... DEVICE\n\ -\n\ -Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -\n\ -You should not normally run %s directly. Use grub-install instead.\n\ -\n\ - -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ - -c, --core-image=FILE use FILE as the core image [default=%s]\n\ - -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ - -f, --force install even if problems are detected\n\ - -s, --skip-fs-probe do not probe for filesystems in DEVICE\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -"), - program_name, program_name, - DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); - - exit (status); -} - -static char * -get_device_name (char *dev) -{ - size_t len = strlen (dev); - - if (dev[0] != '(' || dev[len - 1] != ')') - return 0; - - dev[len - 1] = '\0'; - return dev + 1; -} - -int -main (int argc, char *argv[]) -{ - char *boot_file = 0; - char *core_file = 0; - char *dir = 0; - char *dev_map = 0; - char *root_dev = 0; - char *dest_dev; - int must_embed = 0, force = 0, fs_probe = 1; - - set_program_name (argv[0]); - - grub_util_init_nls (); - - /* Check for options. */ - while (1) - { - int c = getopt_long (argc, argv, "b:c:d:m:r:hVvf", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - if (boot_file) - free (boot_file); - - boot_file = xstrdup (optarg); - break; - - case 'c': - if (core_file) - free (core_file); - - core_file = xstrdup (optarg); - break; - - case 'd': - if (dir) - free (dir); - - dir = xstrdup (optarg); - break; - - case 'm': - if (dev_map) - free (dev_map); - - dev_map = xstrdup (optarg); - break; - - case 'r': - if (root_dev) - free (root_dev); - - root_dev = xstrdup (optarg); - break; - - case 'f': - force = 1; - break; - - case 's': - fs_probe = 0; - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } - - if (verbosity > 1) - grub_env_set ("debug", "all"); - - /* Obtain DEST_DEV. */ - if (optind >= argc) - { - fprintf (stderr, _("No device is specified.\n")); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); - usage (1); - } - - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP); - - /* Initialize all modules. */ - grub_init_all (); - - dest_dev = get_device_name (argv[optind]); - if (! dest_dev) - { - /* Possibly, the user specified an OS device file. */ - dest_dev = grub_util_get_grub_dev (argv[optind]); - if (! dest_dev) - { - fprintf (stderr, _("Invalid device `%s'.\n"), argv[optind]); - usage (1); - } - } - else - /* For simplicity. */ - dest_dev = xstrdup (dest_dev); - - if (root_dev) - { - char *tmp = get_device_name (root_dev); - - if (! tmp) - grub_util_error (_("invalid root device `%s'"), root_dev); - - tmp = xstrdup (tmp); - free (root_dev); - root_dev = tmp; - } - else - { - root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : DEFAULT_DIRECTORY)); - if (! root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error (_("cannot guess the root device. Specify the option `--root-device'")); - } - } - -#ifdef __linux__ - if (grub_util_lvm_isvolume (root_dev)) - must_embed = 1; - - if (root_dev[0] == 'm' && root_dev[1] == 'd' - && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/')) - { - /* FIXME: we can avoid this on RAID1. */ - must_embed = 1; - } - - if (dest_dev[0] == 'm' && dest_dev[1] == 'd' - && ((dest_dev[2] >= '0' && dest_dev[2] <= '9') || dest_dev[2] == '/')) - { - char **devicelist; - int i; - - devicelist = grub_util_raid_getmembers (dest_dev); - - for (i = 0; devicelist[i]; i++) - { - setup (dir ? : DEFAULT_DIRECTORY, - boot_file ? : DEFAULT_BOOT_FILE, - core_file ? : DEFAULT_CORE_FILE, - root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force, fs_probe); - } - } - else -#endif - /* Do the real work. */ - setup (dir ? : DEFAULT_DIRECTORY, - boot_file ? : DEFAULT_BOOT_FILE, - core_file ? : DEFAULT_CORE_FILE, - root_dev, dest_dev, must_embed, force, fs_probe); - - /* Free resources. */ - grub_fini_all (); - grub_util_biosdisk_fini (); - - free (boot_file); - free (core_file); - free (dir); - free (dev_map); - free (root_dev); - free (dest_dev); - - return 0; -} diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in deleted file mode 100644 index 98de5f348..000000000 --- a/util/ieee1275/grub-install.in +++ /dev/null @@ -1,273 +0,0 @@ -#! /bin/sh - -# Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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 . - -# This script uses `ofpathname', which is downloadable from -# http://ppc64-utils.ozlabs.org . - -# Initialize some variables. -transform="@program_transform_name@" - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` - -self=`basename $0` - -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` -rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` -modules= - -install_device= -debug=no -update_nvram=yes - -ofpathname=`which ofpathname` -nvsetenv=`which nvsetenv` - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 - exit 1 - fi - echo $1 -} - -# Check the arguments. -while test $# -gt 0 -do - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - - --modules) - modules=`argument $option "$@"`; shift ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - - --root-directory) - rootdir=`argument $option "$@"`; shift ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - - --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - - --grub-probe) - grub_probe=`argument $option "$@"`; shift ;; - --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; - - --no-nvram) - update_nvram=no ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - *) - if test "x$install_device" != x; then - echo "More than one install_devices?" 1>&2 - usage - exit 1 - fi - install_device="${option}" ;; - esac -done - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -bootdir=${rootdir}/boot -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map - -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -# Find the partition at the right mount point. -install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${grubdir}` - -if test "x$install_device" = "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then - echo "$grubdir must be a mount point." - exit 1 -fi -# XXX warn on firmware-unreadable filesystems? - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 - -# Create the device map file if it is not present. -if test -f "$device_map"; then - : -else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 -fi - -# Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst ; do - if test -f $file; then - rm -f $file || exit 1 - fi -done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst ; do - cp -f $file ${grubdir} || exit 1 -done - -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}` -if test "x$fs_module" = x -a "x$modules" = x; then - echo "Auto-detection of a filesystem module failed." 1>&2 - echo "Please specify the module with the option \`--modules' explicitly." 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` - -modules="$modules $fs_module $partmap_module $devabstraction_module" - -# Now perform the installation. -"$grub_mkimage" -O ${target_cpu}-ieee1275 --directory=${pkglibdir} --output=${grubdir}/grub $modules || exit 1 - -if test $update_nvram = yes; then - set $ofpathname dummy - if test -f "$1"; then - : - else - echo "$1: Not found." 1>&2 - exit 1 - fi - - set $nvsetenv dummy - if test -f "$1"; then - : - else - echo "$1: Not found." 1>&2 - exit 1 - fi - - # Get the Open Firmware device tree path translation. - dev=`echo $install_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'` - partno=`echo $install_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'` - ofpath=`$ofpathname $dev` || { - echo "Couldn't find Open Firmware device tree path for $dev." - echo "You will have to set boot-device manually." - exit 1 - } - - # Point boot-device at the new grub install - boot_device="$ofpath:$partno,\\grub" - "$nvsetenv" boot-device "$boot_device" || { - echo "$nvsetenv failed." - echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" - echo " setenv boot-device $boot_device" - exit 1 - } -fi - -# Prompt the user to check if the device map is correct. -echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`$self'." -echo - -cat $device_map - -# Bye. -exit 0 diff --git a/util/import_gcry.py b/util/import_gcry.py index b9c3edcde..494a4ae7b 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -40,8 +40,8 @@ except: print ("WARNING: %s already exists" % cipher_dir_out) cipher_files = os.listdir (cipher_dir_in) -conf = open (os.path.join (outdir, "conf", "gcry.rmk"), "w") -conf.write ("# -*- makefile -*-\n\n") +conf = open (os.path.join ("grub-core", "Makefile.gcry.def"), "w") +conf.write ("AutoGen definitions Makefile.tpl;\n\n") chlog = "" # Strictly speaking CRC32/CRC24 work on bytes so this value should be 1 @@ -62,7 +62,6 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64, "_gcry_digest_spec_whirlpool" : 64} cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w") -conf.write ("MAINTAINER_CLEANFILES += $(srcdir)/conf/gcry.rmk $(srcdir)/lib/libgcrypt-grub/cipher/ChangeLog $(srcdir)/lib/libgcrypt-grub/cipher/cipher.h $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst $(srcdir)/lib/libgcrypt-grub/cipher/g10lib.h $(srcdir)/lib/libgcrypt-grub/cipher/memory.h $(srcdir)/lib/libgcrypt-grub/cipher/types.h\n"); # rijndael is the only cipher using aliases. So no need for mangling, just # hardcode it @@ -88,7 +87,6 @@ for cipher_file in cipher_files: continue nch = False if re.match (".*\.[ch]$", cipher_file): - conf.write ("MAINTAINER_CLEANFILES += $(srcdir)/lib/libgcrypt-grub/cipher/" + cipher_file + "\n"); isc = re.match (".*\.c$", cipher_file) f = open (infile, "r") fw = open (outfile, "w") @@ -276,11 +274,13 @@ for cipher_file in cipher_files: chlognew = "%s\n %s" % (chlognew, chmsg) fw.write (" grub_md_unregister (&%s);\n" % mdname) fw.write ("}\n") - conf.write ("pkglib_MODULES += %s.mod\n" % modname) - conf.write ("%s_mod_SOURCES = %s\n" %\ - (modname, modfiles)) - conf.write ("%s_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap\n" % modname) - conf.write ("%s_mod_LDFLAGS = $(COMMON_LDFLAGS)\n\n" % modname) + conf.write ("module = {\n") + conf.write (" name = %s;\n" % modname) + for src in modfiles.split(): + conf.write (" common = %s;\n" % src) + conf.write (" cflags = '$(CFLAGS_GCRY)';\n"); + conf.write (" cppflags = '$(CPPFLAGS_GCRY)';\n"); + conf.write ("};\n\n") elif isc and cipher_file != "camellia.c": print ("WARNING: C file isn't a module: %s" % cipher_file) f.close () diff --git a/util/lvm.c b/util/lvm.c index 0a0916344..bb2c19fe3 100644 --- a/util/lvm.c +++ b/util/lvm.c @@ -19,7 +19,7 @@ /* We only support LVM on Linux. */ #ifdef __linux__ - +#include #include #include diff --git a/util/misc.c b/util/misc.c index 21dd211e1..cfbae609b 100644 --- a/util/misc.c +++ b/util/misc.c @@ -35,11 +35,13 @@ #include #include #include +#include #include #include #include #include #include +#include #define ENABLE_RELOCATABLE 0 #include "progname.h" @@ -178,6 +180,97 @@ grub_util_write_image (const char *img, size_t size, FILE *out) grub_util_error ("write failed"); } +char * +grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdline (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdlist (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdif (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdfor (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdwhile (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute (struct grub_script *script) +{ + if (script == 0 || script->cmd == 0) + return 0; + + return script->cmd->exec (script->cmd); +} + +void +grub_putchar (int c) +{ + putchar (c); +} + +int +grub_getkey (void) +{ + return -1; +} + +void +grub_refresh (void) +{ + fflush (stdout); +} + +static void +grub_xputs_real (const char *str) +{ + fputs (str, stdout); +} + +void (*grub_xputs) (const char *str) = grub_xputs_real; + +int +grub_dl_ref (grub_dl_t mod) +{ + (void) mod; + return 0; +} + +int +grub_dl_unref (grub_dl_t mod) +{ + (void) mod; + return 0; +} + /* Some functions that we don't use. */ void grub_mm_init_region (void *addr __attribute__ ((unused)), @@ -185,12 +278,10 @@ grub_mm_init_region (void *addr __attribute__ ((unused)), { } -#if GRUB_NO_MODULES void grub_register_exported_symbols (void) { } -#endif #ifdef __MINGW32__ @@ -214,14 +305,6 @@ grub_millisleep (grub_uint32_t ms) #endif -#if !(defined (__i386__) || defined (__x86_64__)) && GRUB_NO_MODULES -void -grub_arch_sync_caches (void *address __attribute__ ((unused)), - grub_size_t len __attribute__ ((unused))) -{ -} -#endif - #ifdef __MINGW32__ void sync (void) @@ -293,19 +376,4 @@ grub_util_init_nls (void) textdomain (PACKAGE); #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ } - -#endif /* GRUB_UTIL */ - -int -grub_dl_ref (grub_dl_t mod) -{ - (void) mod; - return 0; -} - -int -grub_dl_unref (grub_dl_t mod) -{ - (void) mod; - return 0; -} +#endif diff --git a/util/powerpc/ieee1275/grub-mkrescue.in b/util/powerpc/ieee1275/grub-mkrescue.in index aefedff3f..d688431c3 100644 --- a/util/powerpc/ieee1275/grub-mkrescue.in +++ b/util/powerpc/ieee1275/grub-mkrescue.in @@ -121,13 +121,13 @@ if [ "x${modules}" = "x" ] ; then modules=`cd ${input_dir}/ && ls *.mod` fi -map_file=`mktemp` +map_file=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 cat >${map_file} < #include #include +#include #include #include #include #include +#include #include #include #include #include -static char * -grub_util_getdiskname (int major, int minor) -{ - char *name = xmalloc (15); - - if (major == LOOP_MAJOR) - sprintf (name, "/dev/loop%d", minor); - else if (major == IDE0_MAJOR) - sprintf (name, "/dev/hd%c", 'a' + minor / 64); - else if (major == IDE1_MAJOR) - sprintf (name, "/dev/hd%c", 'c' + minor / 64); - else if (major == IDE2_MAJOR) - sprintf (name, "/dev/hd%c", 'e' + minor / 64); - else if (major == IDE3_MAJOR) - sprintf (name, "/dev/hd%c", 'g' + minor / 64); - else if (major == SCSI_DISK0_MAJOR) - sprintf (name, "/dev/sd%c", 'a' + minor / 16); - else - grub_util_error ("unknown device number: %d, %d", major, minor); - - return name; -} - char ** grub_util_raid_getmembers (char *name) { @@ -99,7 +79,8 @@ grub_util_raid_getmembers (char *name) if (disk.state & (1 << MD_DISK_ACTIVE)) { - devicelist[j] = grub_util_getdiskname (disk.major, disk.minor); + devicelist[j] = grub_find_device (NULL, + makedev (disk.major, disk.minor)); j++; } } diff --git a/util/resolve.c b/util/resolve.c index 8b33beba0..63bd7ccb2 100644 --- a/util/resolve.c +++ b/util/resolve.c @@ -16,13 +16,16 @@ * along with GRUB. If not, see . */ +#include + #include #include #include #include -#include +#include #include +#include /* Module. */ struct mod_list diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c deleted file mode 100644 index a0d487623..000000000 --- a/util/sparc64/ieee1275/grub-setup.c +++ /dev/null @@ -1,656 +0,0 @@ -/* grub-setup.c - make GRUB usable */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _GNU_SOURCE 1 -#include - -#include "progname.h" - -/* This program fills in various fields inside of the 'boot' and 'core' - * image files. - * - * The 'boot' image needs to know the OBP path name of the root - * device. It also needs to know the initial block number of - * 'core' (which is 'diskboot' concatenated with 'kernel' and - * all the modules, this is created by grub-mkimage). This resulting - * 'boot' image is 512 bytes in size and is placed in the second block - * of a partition. - * - * The initial 'diskboot' block acts as a loader for the actual GRUB - * kernel. It contains the loading code and then a block list. - * - * The block list of 'core' starts at the end of the 'diskboot' image - * and works it's way backwards towards the end of the code of 'diskboot'. - * - * We patch up the images with the necessary values and write out the - * result. - */ - -#define DEFAULT_BOOT_FILE "boot.img" -#define DEFAULT_CORE_FILE "core.img" - -#define grub_target_to_host16(x) grub_be_to_cpu16(x) -#define grub_target_to_host32(x) grub_be_to_cpu32(x) -#define grub_target_to_host64(x) grub_be_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_be16(x) -#define grub_host_to_target32(x) grub_cpu_to_be32(x) -#define grub_host_to_target64(x) grub_cpu_to_be64(x) - -/* This is the blocklist used in the diskboot image. */ -struct boot_blocklist -{ - grub_uint64_t start; - grub_uint32_t len; -} __attribute__ ((packed)); - -void -grub_xputs_real (const char *str) -{ - fputs (str, stdout); -} - -void (*grub_xputs) (const char *str) = grub_xputs_real; - -int -grub_getkey (void) -{ - return -1; -} - -void -grub_refresh (void) -{ - fflush (stdout); -} - -static void -setup (const char *prefix, const char *dir, - const char *boot_file, const char *core_file, - const char *root, const char *dest) -{ - char *boot_path, *core_path; - char *boot_img, *core_img; - size_t boot_size, core_size; - grub_uint16_t core_sectors; - grub_device_t root_dev, dest_dev; - char *boot_devpath; - grub_disk_addr_t *kernel_byte; - struct boot_blocklist *first_block, *block; - char *tmp_img; - int i; - grub_disk_addr_t first_sector; - grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; - grub_file_t file; - FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; - - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the first sector of the core file " - "is not sector-aligned"); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - struct boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("non-sector-aligned data is found in the core file"); - - if (block != first_block - && (grub_be_to_cpu64 (prev->start) - + grub_be_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_be64 (sector); - block->len = grub_cpu_to_be16 (1); - - block--; - if (block->len) - grub_util_error ("the sectors of the core file are too fragmented"); - } - - last_length = length; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is not %d", - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_devpath = (char *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_BOOT_DEVPATH); - kernel_byte = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_KERNEL_BYTE); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is too small", core_path); - - core_img = grub_util_read_image (core_path); - free (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - grub_util_info ("root is `%s', dest is `%s'", root, dest); - - /* Open the root device and the destination device. */ - grub_util_info ("Opening root"); - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("Opening dest"); - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* The core image must be put on a filesystem unfortunately. */ - grub_util_info ("will leave the core image on the filesystem"); - - /* Make sure that GRUB reads the identical image as the OS. */ - tmp_img = xmalloc (core_size); - core_path = grub_util_get_path (prefix, core_file); - - /* It is a Good Thing to sync two times. */ - sync (); - sync (); - -#define MAX_TRIES 5 - - for (i = 0; i < MAX_TRIES; i++) - { - grub_util_info ("attempting to read the core image `%s' from GRUB%s", - core_path, (i == 0) ? "" : " again"); - - grub_disk_cache_invalidate_all (); - - file = grub_file_open (core_path); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { -#if 0 - FILE *dump; - FILE *dump2; - - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } - - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } - -#endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } - - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); - - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); - - grub_errno = GRUB_ERR_NONE; - sync (); - sleep (1); - } - - if (i == MAX_TRIES) - grub_util_error ("cannot read `%s' correctly", core_path); - - /* Clean out the blocklists. */ - block = first_block; - while (block->len) - { - block->start = 0; - block->len = 0; - - block--; - - if ((char *) block <= core_img) - grub_util_error ("no terminator in the core image"); - } - - /* Now read the core image to determine where the sectors are. */ - file = grub_file_open (core_path); - if (! file) - grub_util_error ("%s", grub_errmsg); - - file->read_hook = save_first_sector; - if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the first sector of the core image"); - - block = first_block; - file->read_hook = save_blocklists; - if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) - != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the rest sectors of the core image"); - - if (file->device->disk->id != dest_dev->disk->id) - { - const char *dest_ofpath; - dest_ofpath - = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); - grub_util_info ("dest_ofpath is `%s'", dest_ofpath); - strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); - boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; - } - else - { - grub_util_info ("non cross-disk install"); - memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH); - } - - grub_file_close (file); - - free (core_path); - free (tmp_img); - - *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); - - grub_util_info ("boot device path %s, prefix is %s, dest is %s", - boot_devpath, prefix, dest); - - /* Write the first two sectors of the core image onto the disk. */ - core_path = grub_util_get_path (dir, core_file); - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "r+b"); - if (! fp) - grub_util_error ("cannot open `%s'", core_path); - - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp); - fclose (fp); - free (core_path); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - - /* Sync is a Good Thing. */ - sync (); - - free (core_img); - free (boot_img); - grub_device_close (dest_dev); - grub_device_close (root_dev); -} - -static struct option options[] = - { - {"boot-image", required_argument, 0, 'b'}, - {"core-image", required_argument, 0, 'c'}, - {"directory", required_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"root-device", required_argument, 0, 'r'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) -{ - if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - printf ("\ -Usage: %s [OPTION]... DEVICE\n\ -\n\ -Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -\n\ -You should not normally run %s directly. Use grub-install instead.\n\ -\n\ - -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ - -c, --core-image=FILE use FILE as the core image [default=%s]\n\ - -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -", program_name, program_name, - DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); - - exit (status); -} - -struct grub_setup_info -{ - char *boot_file; - char *core_file; - char *dir; - char *dev_map; - char *root_dev; - char *prefix; - char *dest_dev; -}; - -static void -init_info (struct grub_setup_info *gp) -{ - gp->boot_file = NULL; - gp->core_file = NULL; - gp->dir = NULL; - gp->dev_map = NULL; - gp->root_dev = NULL; - gp->prefix = NULL; - gp->dest_dev = NULL; -} - -static int -parse_options (struct grub_setup_info *gp, int argc, char *argv[]) -{ - while (1) - { - int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - if (gp->boot_file) - free (gp->boot_file); - - gp->boot_file = xstrdup (optarg); - break; - - case 'c': - if (gp->core_file) - free (gp->core_file); - - gp->core_file = xstrdup (optarg); - break; - - case 'd': - if (gp->dir) - free (gp->dir); - - gp->dir = xstrdup (optarg); - break; - - case 'm': - if (gp->dev_map) - free (gp->dev_map); - - gp->dev_map = xstrdup (optarg); - break; - - case 'r': - if (gp->root_dev) - free (gp->root_dev); - - gp->root_dev = xstrdup (optarg); - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } - - if (verbosity > 1) - grub_env_set ("debug", "all"); - - if (optind >= argc) - { - fprintf (stderr, "No device is specified.\n"); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); - usage (1); - } - return 1; -} - -static char * -get_device_name (char *dev) -{ - size_t len = strlen (dev); - - if (dev[0] != '(' || dev[len - 1] != ')') - return 0; - - dev[len - 1] = '\0'; - return dev + 1; -} - -static void -find_dest_dev (struct grub_setup_info *gp, char *argv[]) -{ - gp->dest_dev = get_device_name (argv[optind]); - if (! gp->dest_dev) - { - /* Possibly, the user specified an OS device file. */ - gp->dest_dev = grub_util_get_grub_dev (argv[optind]); - if (! gp->dest_dev) - { - fprintf (stderr, "Invalid device `%s'.\n", argv[optind]); - usage (1); - } - grub_util_info ("transformed OS device `%s' into GRUB device `%s'", - argv[optind], gp->dest_dev); - } - else - { - /* For simplicity. */ - gp->dest_dev = xstrdup (gp->dest_dev); - grub_util_info ("Using `%s' as GRUB device", gp->dest_dev); - } -} - -static void -check_root_dev (struct grub_setup_info *gp) -{ - if (gp->root_dev) - { - char *tmp = get_device_name (gp->root_dev); - - if (! tmp) - grub_util_error ("invalid root device `%s'", gp->root_dev); - - tmp = xstrdup (tmp); - free (gp->root_dev); - gp->root_dev = tmp; - } - else - { - char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY; - char *root_device = grub_guess_root_device (dir); - - gp->root_dev = grub_util_get_grub_dev (root_device); - if (! gp->root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error ("cannot guess the root device. " - "Specify the option `--root-device'"); - } - grub_util_info ("guessed root device `%s' and root_dev `%s' from " - "dir `%s'", root_device, gp->root_dev, dir); - } -} - -static void -free_memory (struct grub_setup_info *gp) -{ - free (gp->boot_file); - free (gp->core_file); - free (gp->dir); - free (gp->dev_map); - free (gp->root_dev); - free (gp->prefix); - free (gp->dest_dev); -} - -int -main (int argc, char *argv[]) -{ - struct grub_setup_info ginfo; - - set_program_name (argv[0]); - - grub_util_init_nls (); - - init_info (&ginfo); - if (!parse_options (&ginfo, argc, argv)) - return 0; - - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP); - - /* Initialize all modules. */ - grub_init_all (); - - find_dest_dev (&ginfo, argv); - - ginfo.prefix = grub_make_system_path_relative_to_its_root (ginfo.dir ? - : DEFAULT_DIRECTORY); - - check_root_dev (&ginfo); - - /* Do the real work. */ - setup (ginfo.prefix, - ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY, - ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE, - ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE, - ginfo.root_dev, ginfo.dest_dev); - - /* Free resources. */ - grub_fini_all (); - - free_memory (&ginfo); - - return 0; -} diff --git a/video/sm712.c b/video/sm712.c deleted file mode 100644 index a58032c42..000000000 --- a/video/sm712.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,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 . - */ - -#define grub_video_render_target grub_video_fbrender_target - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sm712_init.c" - -#define GRUB_SM712_TOTAL_MEMORY_SPACE 0x700400 - -static struct -{ - struct grub_video_mode_info mode_info; - struct grub_video_render_target *render_target; - - grub_uint8_t *ptr; - int mapped; - grub_uint32_t base; - grub_pci_device_t dev; -} framebuffer; - -static grub_err_t -grub_video_sm712_video_init (void) -{ - /* Reset frame buffer. */ - grub_memset (&framebuffer, 0, sizeof(framebuffer)); - - return grub_video_fb_init (); -} - -static grub_err_t -grub_video_sm712_video_fini (void) -{ - if (framebuffer.mapped) - grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, - GRUB_SM712_TOTAL_MEMORY_SPACE); - - return grub_video_fb_fini (); -} - -static grub_err_t -grub_video_sm712_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) -{ - int depth; - grub_err_t err; - int found = 0; - unsigned i; - - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); - 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) != 0x0300 || pciid != 0x0712126f) - return 0; - - found = 1; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr); - framebuffer.dev = dev; - - return 1; - } - - /* Decode depth from mode_type. If it is zero, then autodetect. */ - depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) - >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; - - if ((width != 1024 && width != 0) || (height != 600 && height != 0) - || (depth != 16 && depth != 0)) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Only 1024x600x16 is supported"); - - grub_pci_iterate (find_card); - if (!found) - return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); - - /* Fill mode info details. */ - framebuffer.mode_info.width = 1024; - framebuffer.mode_info.height = 600; - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; - framebuffer.mode_info.bpp = 16; - framebuffer.mode_info.bytes_per_pixel = 2; - framebuffer.mode_info.pitch = 1024 * 2; - framebuffer.mode_info.number_of_colors = 256; - framebuffer.mode_info.red_mask_size = 5; - framebuffer.mode_info.red_field_pos = 11; - framebuffer.mode_info.green_mask_size = 6; - framebuffer.mode_info.green_field_pos = 5; - framebuffer.mode_info.blue_mask_size = 5; - framebuffer.mode_info.blue_field_pos = 0; - framebuffer.mode_info.reserved_mask_size = 0; - framebuffer.mode_info.reserved_field_pos = 0; - framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); - - if (found && framebuffer.base == 0) - { - grub_pci_address_t addr; - /* FIXME: choose address dynamically if needed. */ - framebuffer.base = 0x04000000; - - addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, framebuffer.base); - - /* Set latency. */ - addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_CACHELINE); - grub_pci_write (addr, 0x8); - - /* Enable address spaces. */ - addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_COMMAND); - grub_pci_write (addr, 0x7); - } - - /* We can safely discard volatile attribute. */ - framebuffer.ptr - = (void *) grub_pci_device_map_range (framebuffer.dev, - framebuffer.base, - GRUB_SM712_TOTAL_MEMORY_SPACE); - framebuffer.mapped = 1; - - /* Initialise SM712. */ - grub_outb (0x18, GRUB_MACHINE_PCI_IO_BASE + 0x3c4); - grub_outb (0x11, GRUB_MACHINE_PCI_IO_BASE + 0x3c5); - - /* Prevent garbage from appearing on the screen. */ - grub_memset (framebuffer.ptr, 0, - framebuffer.mode_info.height * framebuffer.mode_info.pitch); - - for (i = 0; i < ARRAY_SIZE (sm712_init); i++) - switch (sm712_init[i].directive) - { - case 1: - *(volatile grub_uint8_t *) ((char *) framebuffer.ptr - + sm712_init[i].addr) = sm712_init[i].val; - break; - case -1: - { - grub_uint8_t val = *(volatile grub_uint8_t *) - ((char *) framebuffer.ptr + sm712_init[i].addr); - (void) val; - } - break; - case 2: - *(volatile grub_uint16_t *) ((char *) framebuffer.ptr - + sm712_init[i].addr) = sm712_init[i].val; - break; - case 4: - *(volatile grub_uint32_t *) ((char *) framebuffer.ptr - + sm712_init[i].addr) = sm712_init[i].val; - break; - } - - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); - - if (err) - return err; - - err = grub_video_fb_set_active_render_target (framebuffer.render_target); - - if (err) - return err; - - /* Copy default palette to initialize emulated palette. */ - err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - return err; -} - -static grub_err_t -grub_video_sm712_swap_buffers (void) -{ - /* TODO: Implement buffer swapping. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_sm712_set_active_render_target (struct grub_video_render_target *target) -{ - if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) - target = framebuffer.render_target; - - return grub_video_fb_set_active_render_target (target); -} - -static grub_err_t -grub_video_sm712_get_info_and_fini (struct grub_video_mode_info *mode_info, - void **framebuf) -{ - grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); - *framebuf = (char *) framebuffer.ptr; - - grub_video_fb_fini (); - - return GRUB_ERR_NONE; -} - - -static struct grub_video_adapter grub_video_sm712_adapter = - { - .name = "SM712 Video Driver", - .id = GRUB_VIDEO_DRIVER_SM712, - - .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, - - .init = grub_video_sm712_video_init, - .fini = grub_video_sm712_video_fini, - .setup = grub_video_sm712_setup, - .get_info = grub_video_fb_get_info, - .get_info_and_fini = grub_video_sm712_get_info_and_fini, - .set_palette = grub_video_fb_set_palette, - .get_palette = grub_video_fb_get_palette, - .set_viewport = grub_video_fb_set_viewport, - .get_viewport = grub_video_fb_get_viewport, - .map_color = grub_video_fb_map_color, - .map_rgb = grub_video_fb_map_rgb, - .map_rgba = grub_video_fb_map_rgba, - .unmap_color = grub_video_fb_unmap_color, - .fill_rect = grub_video_fb_fill_rect, - .blit_bitmap = grub_video_fb_blit_bitmap, - .blit_render_target = grub_video_fb_blit_render_target, - .scroll = grub_video_fb_scroll, - .swap_buffers = grub_video_sm712_swap_buffers, - .create_render_target = grub_video_fb_create_render_target, - .delete_render_target = grub_video_fb_delete_render_target, - .set_active_render_target = grub_video_sm712_set_active_render_target, - .get_active_render_target = grub_video_fb_get_active_render_target, - - .next = 0 - }; - -GRUB_MOD_INIT(video_sm712) -{ - grub_video_register (&grub_video_sm712_adapter); -} - -GRUB_MOD_FINI(video_sm712) -{ - grub_video_unregister (&grub_video_sm712_adapter); -} diff --git a/video/sm712_init.c b/video/sm712_init.c deleted file mode 100644 index 02c64c453..000000000 --- a/video/sm712_init.c +++ /dev/null @@ -1,546 +0,0 @@ -/* Following sequence is a capture of sm712 initialisation sequence. */ -static struct -{ - int directive; - grub_uint32_t addr; - grub_uint32_t val; -} sm712_init[] = -{ - {1, 0x7003c4, 0x21}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x62}, - {1, 0x7003c5, 0x7a}, - {1, 0x7003c4, 0x6a}, - {1, 0x7003c5, 0x16}, - {1, 0x7003c4, 0x6b}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c6, 0x0}, - {1, 0x7003c4, 0x0}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c2, 0xeb}, - {1, 0x7003c4, 0x0}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x1}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x2}, - {1, 0x7003c5, 0xf}, - {1, 0x7003c4, 0x3}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4}, - {1, 0x7003c5, 0xe}, - {1, 0x7003c4, 0x10}, - {1, 0x7003c5, 0xc8}, - {1, 0x7003c4, 0x11}, - {1, 0x7003c5, 0x40}, - {1, 0x7003c4, 0x12}, - {1, 0x7003c5, 0x14}, - {1, 0x7003c4, 0x13}, - {1, 0x7003c5, 0x60}, - {1, 0x7003c4, 0x14}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x15}, - {1, 0x7003c5, 0xa}, - {1, 0x7003c4, 0x16}, - {1, 0x7003c5, 0x92}, - {1, 0x7003c4, 0x17}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x18}, - {1, 0x7003c5, 0x51}, - {1, 0x7003c4, 0x19}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1a}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x1b}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1e}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1f}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x20}, - {1, 0x7003c5, 0xc4}, - {1, 0x7003c4, 0x21}, - {1, 0x7003c5, 0x30}, - {1, 0x7003c4, 0x22}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x23}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x24}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x30}, - {1, 0x7003c5, 0x28}, - {1, 0x7003c4, 0x31}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x32}, - {1, 0x7003c5, 0x24}, - {1, 0x7003c4, 0x33}, - {1, 0x7003c5, 0x9}, - {1, 0x7003c4, 0x34}, - {1, 0x7003c5, 0xc0}, - {1, 0x7003c4, 0x35}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x36}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x37}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x38}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x39}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x3a}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x3b}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x3c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x3d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x3e}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x3f}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x40}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x41}, - {1, 0x7003c5, 0xfc}, - {1, 0x7003c4, 0x42}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x43}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x44}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x45}, - {1, 0x7003c5, 0x18}, - {1, 0x7003c4, 0x46}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x47}, - {1, 0x7003c5, 0xfc}, - {1, 0x7003c4, 0x48}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x49}, - {1, 0x7003c5, 0xc}, - {1, 0x7003c4, 0x4a}, - {1, 0x7003c5, 0x44}, - {1, 0x7003c4, 0x4b}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x4c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4e}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4f}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x50}, - {1, 0x7003c5, 0x6}, - {1, 0x7003c4, 0x51}, - {1, 0x7003c5, 0x68}, - {1, 0x7003c4, 0x52}, - {1, 0x7003c5, 0xa7}, - {1, 0x7003c4, 0x53}, - {1, 0x7003c5, 0x7f}, - {1, 0x7003c4, 0x54}, - {1, 0x7003c5, 0x83}, - {1, 0x7003c4, 0x55}, - {1, 0x7003c5, 0x24}, - {1, 0x7003c4, 0x56}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x57}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x58}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x59}, - {1, 0x7003c5, 0x60}, - {1, 0x7003c4, 0x5a}, - {1, 0x7003c5, 0x59}, - {1, 0x7003c4, 0x5b}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x5c}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x5d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x5e}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x5f}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x60}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x61}, - {1, 0x7003c5, 0x80}, - {1, 0x7003c4, 0x63}, - {1, 0x7003c5, 0x1a}, - {1, 0x7003c4, 0x64}, - {1, 0x7003c5, 0x1a}, - {1, 0x7003c4, 0x65}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x66}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x67}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x68}, - {1, 0x7003c5, 0x50}, - {1, 0x7003c4, 0x69}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x6c}, - {1, 0x7003c5, 0x52}, - {1, 0x7003c4, 0x6d}, - {1, 0x7003c5, 0x89}, - {1, 0x7003c4, 0x6e}, - {1, 0x7003c5, 0x9}, - {1, 0x7003c4, 0x6f}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x70}, - {1, 0x7003c5, 0x4}, - {1, 0x7003c4, 0x71}, - {1, 0x7003c5, 0x45}, - {1, 0x7003c4, 0x72}, - {1, 0x7003c5, 0x30}, - {1, 0x7003c4, 0x73}, - {1, 0x7003c5, 0x30}, - {1, 0x7003c4, 0x74}, - {1, 0x7003c5, 0x40}, - {1, 0x7003c4, 0x75}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x80}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x81}, - {1, 0x7003c5, 0x7}, - {1, 0x7003c4, 0x82}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x83}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x84}, - {1, 0x7003c5, 0x8}, - {1, 0x7003c4, 0x85}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x86}, - {1, 0x7003c5, 0x42}, - {1, 0x7003c4, 0x87}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x88}, - {1, 0x7003c5, 0x59}, - {1, 0x7003c4, 0x89}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x8a}, - {1, 0x7003c5, 0x44}, - {1, 0x7003c4, 0x8b}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x8c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x8d}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x8e}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x8f}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x90}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x91}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x92}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x93}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0xa0}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0xa1}, - {1, 0x7003c5, 0x10}, - {1, 0x7003c4, 0xa2}, - {1, 0x7003c5, 0x8}, - {1, 0x7003c4, 0xa3}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0xa4}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0xa5}, - {1, 0x7003c5, 0xed}, - {1, 0x7003c4, 0xa6}, - {1, 0x7003c5, 0xed}, - {1, 0x7003c4, 0xa7}, - {1, 0x7003c5, 0xed}, - {1, 0x7003c4, 0xa8}, - {1, 0x7003c5, 0x7b}, - {1, 0x7003c4, 0xa9}, - {1, 0x7003c5, 0xfb}, - {1, 0x7003c4, 0xaa}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0xab}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0xac}, - {1, 0x7003c5, 0x97}, - {1, 0x7003c4, 0xad}, - {1, 0x7003c5, 0xef}, - {1, 0x7003c4, 0xae}, - {1, 0x7003c5, 0xbf}, - {1, 0x7003c4, 0xaf}, - {1, 0x7003c5, 0xdf}, - {1, 0x7003ce, 0x0}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x1}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x2}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x3}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x4}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x5}, - {1, 0x7003cf, 0x40}, - {1, 0x7003ce, 0x6}, - {1, 0x7003cf, 0x5}, - {1, 0x7003ce, 0x7}, - {1, 0x7003cf, 0xf}, - {1, 0x7003ce, 0x8}, - {1, 0x7003cf, 0xff}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003c1, 0x3e}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x1}, - {-1, 0x7003c1, 0x3b}, - {1, 0x7003c0, 0x1}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x2}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x2}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x3}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x3}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x4}, - {-1, 0x7003c1, 0x3b}, - {1, 0x7003c0, 0x4}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x5}, - {-1, 0x7003c1, 0x2f}, - {1, 0x7003c0, 0x5}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x6}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x6}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x7}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x7}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x8}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x8}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x9}, - {-1, 0x7003c1, 0x3d}, - {1, 0x7003c0, 0x9}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xa}, - {-1, 0x7003c1, 0x1f}, - {1, 0x7003c0, 0xa}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xb}, - {-1, 0x7003c1, 0x1f}, - {1, 0x7003c0, 0xb}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xc}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0xc}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xd}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0xd}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xe}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0xe}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xf}, - {-1, 0x7003c1, 0x2e}, - {1, 0x7003c0, 0xf}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x10}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x41}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x11}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x12}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0xf}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x13}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x14}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x0}, - {1, 0x7003d4, 0x0}, - {1, 0x7003d5, 0xa3}, - {1, 0x7003d4, 0x1}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x2}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x3}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x4}, - {1, 0x7003d5, 0x85}, - {1, 0x7003d4, 0x5}, - {1, 0x7003d5, 0x16}, - {1, 0x7003d4, 0x6}, - {1, 0x7003d5, 0x24}, - {1, 0x7003d4, 0x7}, - {1, 0x7003d5, 0xf5}, - {1, 0x7003d4, 0x8}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9}, - {1, 0x7003d5, 0x60}, - {1, 0x7003d4, 0xa}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xb}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xc}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xd}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xe}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xf}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x10}, - {1, 0x7003d5, 0x3}, - {1, 0x7003d4, 0x11}, - {1, 0x7003d5, 0x9}, - {1, 0x7003d4, 0x12}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x13}, - {1, 0x7003d5, 0x80}, - {1, 0x7003d4, 0x14}, - {1, 0x7003d5, 0x40}, - {1, 0x7003d4, 0x15}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x16}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x17}, - {1, 0x7003d5, 0xe3}, - {1, 0x7003d4, 0x18}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x30}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x31}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x32}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x33}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x34}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x35}, - {1, 0x7003d5, 0x80}, - {1, 0x7003d4, 0x36}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0x37}, - {1, 0x7003d5, 0x20}, - {1, 0x7003d4, 0x38}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x39}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x3a}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x3b}, - {1, 0x7003d5, 0x40}, - {1, 0x7003d4, 0x3c}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x3d}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x3e}, - {1, 0x7003d5, 0x46}, - {1, 0x7003d4, 0x3f}, - {1, 0x7003d5, 0x91}, - {1, 0x7003d4, 0x40}, - {1, 0x7003d5, 0xa3}, - {1, 0x7003d4, 0x41}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x42}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x43}, - {1, 0x7003d5, 0x86}, - {1, 0x7003d4, 0x44}, - {1, 0x7003d5, 0x15}, - {1, 0x7003d4, 0x45}, - {1, 0x7003d5, 0x24}, - {1, 0x7003d4, 0x46}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x47}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x48}, - {1, 0x7003d5, 0x1}, - {1, 0x7003d4, 0x49}, - {1, 0x7003d5, 0x7}, - {1, 0x7003d4, 0x4a}, - {1, 0x7003d5, 0xe5}, - {1, 0x7003d4, 0x4b}, - {1, 0x7003d5, 0x20}, - {1, 0x7003d4, 0x4c}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x4d}, - {1, 0x7003d5, 0x57}, - {1, 0x7003d4, 0x90}, - {1, 0x7003d5, 0x55}, - {1, 0x7003d4, 0x91}, - {1, 0x7003d5, 0xd5}, - {1, 0x7003d4, 0x92}, - {1, 0x7003d5, 0x5d}, - {1, 0x7003d4, 0x93}, - {1, 0x7003d5, 0xdd}, - {1, 0x7003d4, 0x94}, - {1, 0x7003d5, 0x86}, - {1, 0x7003d4, 0x95}, - {1, 0x7003d5, 0x17}, - {1, 0x7003d4, 0x96}, - {1, 0x7003d5, 0x8e}, - {1, 0x7003d4, 0x97}, - {1, 0x7003d5, 0xaa}, - {1, 0x7003d4, 0x98}, - {1, 0x7003d5, 0x8a}, - {1, 0x7003d4, 0x99}, - {1, 0x7003d5, 0xa3}, - {1, 0x7003d4, 0x9a}, - {1, 0x7003d5, 0xde}, - {1, 0x7003d4, 0x9b}, - {1, 0x7003d5, 0xab}, - {1, 0x7003d4, 0x9c}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9d}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9e}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9f}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xa0}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa1}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa2}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa3}, - {1, 0x7003d5, 0x15}, - {1, 0x7003d4, 0xa4}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa5}, - {1, 0x7003d5, 0x6}, - {1, 0x7003d4, 0xa6}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xa7}, - {1, 0x7003d5, 0x0}, - {1, 0x7003c2, 0x67}, - {4, 0x40c00c, 0x0}, - {4, 0x40c040, 0x0}, - {4, 0x40c000, 0x20000}, - {4, 0x40c010, 0x1020100}, - {1, 0x7003c4, 0x16}, - {-1, 0x7003c5, 0x17} -};