diff --git a/.bzrignore b/.gitignore similarity index 73% rename from .bzrignore rename to .gitignore index 60559af79..00e8f2ef4 100644 --- a/.bzrignore +++ b/.gitignore @@ -8,11 +8,16 @@ *.1 *.8 aclocal.m4 +ahci_test ascii.bitmaps ascii.h autom4te.cache build_env.mk -.bzrignore +build-grub-gen-asciih +build-grub-gen-widthspec +build-grub-mkfont +cdboot_test +cmp_test config.cache config.guess config.h @@ -22,35 +27,46 @@ config.log config.status config.sub configure +core_compress_test DISTLIST debian/grub-extras/*/conf/*.mk docs/*.info docs/stamp-vti docs/version.texi +ehci_test *.elf example_grub_script_test example_scripted_test example_unit_test *.exec +fddboot_test genkernsyms.sh gensymlist.sh gentrigtables +gettext_strings_test grub-bin2h +grub-bios-setup +grub_cmd_date grub_cmd_echo grub_cmd_regexp +grub_cmd_set_date +grub_cmd_sleep grub-editenv grub-emu +grub-emu-lite grub_emu_init.c grub_emu_init.h grub-fstest grub_fstest_init.c grub_fstest_init.h +grub_func_test grub-install grub-kbdcomp grub-macho2img grub-menulst2cfg grub-mk* grub-mount +grub-ofpathname grub-pe2elf grub-probe grub_probe_init.c @@ -67,15 +83,22 @@ grub_script_continue grub_script_dollar grub_script_echo1 grub_script_echo_keywords +grub_script_escape_comma +grub_script_eval grub_script_expansion grub_script_final_semicolon grub_script_for1 grub_script_functions +grub_script_gettext grub_script_if +grub_script_leading_whitespace +grub_script_no_commands grub_script_not grub_script_return grub_script_setparams grub_script_shift +grub_script_strcmp +grub_script_test grub_script_vars1 grub_script_while1 grub_script.tab.c @@ -88,6 +111,10 @@ grub_setup_init.c grub_setup_init.h grub-shell grub-shell-tester +grub-sparc64-setup +gzcompress_test +hddboot_test +help_test *.img *.image include/grub/cpu @@ -95,27 +122,40 @@ include/grub/machine install-sh lib/libgcrypt-grub libgrub_a_init.c +*.log *.lst +lzocompress_test *.marker Makefile *.mod mod-*.c missing +netboot_test +*.o +*.a +ohci_test partmap_test +pata_test *.pf2 *.pp po/*.mo po/grub.pot po/POTFILES po/stamp-po +printf_test +priority_queue_unit_test +pseries_test stamp-h stamp-h1 stamp-h.in symlist.c symlist.h trigtables.c +*.trs +uhci_test update-grub_lib unidata.c +xzcompress_test Makefile.in GPATH GRTAGS @@ -127,12 +167,13 @@ depcomp mdate-sh texinfo.tex grub-core/lib/libgcrypt-grub -**/.deps -**/.deps-util -**/.deps-core -**/.dirstamp +.deps +.deps-util +.deps-core +.dirstamp Makefile.util.am contrib +grub-core/bootinfo.txt grub-core/Makefile.core.am grub-core/Makefile.gcry.def grub-core/contrib @@ -140,6 +181,7 @@ grub-core/gdb_grub grub-core/genmod.sh grub-core/gensyminfo.sh grub-core/gmodule.pl +grub-core/grub.chrp grub-core/modinfo.sh grub-core/*.module grub-core/*.pp @@ -149,6 +191,7 @@ 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/float.h grub-core/gnulib/getopt.h grub-core/gnulib/langinfo.h grub-core/gnulib/ref-add.sed @@ -171,3 +214,14 @@ Makefile.utilgcry.def po/*.po po/*.gmo po/LINGUAS +po/remove-potcdate.sed +include/grub/gcrypt/gcrypt.h +include/grub/gcrypt/g10lib.h +po/POTFILES.in +po/POTFILES-shell.in +grub-glue-efi +grub-render-label +grub-core/gnulib/locale.h +grub-core/gnulib/unitypes.h +grub-core/gnulib/uniwidth.h +build-aux/test-driver diff --git a/ChangeLog b/ChangeLog index 81bdae957..4728f8ae4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6010 @@ +2013-11-14 Vladimir Serbinenko + + * grub-core/Makefile.am (efiemu64.o): Explicitly set link format. + +2013-11-14 Vladimir Serbinenko + + * Makefile.am (default_payload.elf): New target for easier coreboot + build. + +2013-11-14 Vladimir Serbinenko + + * grub-core/kern/arm/cache_armv6.S: Remove special handling for + clang (not necessarry with -no-integrated-as). + * include/grub/symbol.h [__arm__]: Likewise. + +2013-11-14 Vladimir Serbinenko + + * configure.ac: Use -no-integrated-as on arm with clang. + * INSTALL: Mention ARM compilation with clang. + +2013-11-14 Vladimir Serbinenko + + * conf/Makefile.common (CCASFLAGS_PLATFORM) [COND_arm]: Add + -mthumb-interwork. + +2013-11-14 Colin Watson + + * grub-core/fs/ext2.c (grub_ext2_read_block): Factor out common + code for indirect block handling. + + Saves 185 bytes on compressed image. + +2013-11-13 Paulo Flabiano Smorigo + + Fix make clean. + + * Makefile.am: Remove build-grub-* in make clean. + +2013-11-13 Paulo Flabiano Smorigo + + New files to gitignore. + + * .gitignore: Add build-grub-gen-asciih, build-grub-gen-widthspec, + build-grub-mkfont, and grub-emu-lite. Remove .bzrignore. + +2013-11-13 Leif Lindholm + + * grub-core/kern/arm/misc.S: Make thumb2-compatible. + +2013-11-13 Leif Lindholm + + * .gitignore: fix rules for .dep* and add *.a post git migration + +2013-11-13 Colin Watson + + * configure.ac (AM_INIT_AUTOMAKE): Require at least version 1.10.1, + to match INSTALL. + +2013-11-13 Colin Watson + + * grub-core/kern/misc.c: Don't redirect divisions in the + GRUB_UTIL case. + * include/grub/misc.h: Likewise. + +2013-11-13 Colin Watson + + * grub-core/osdep/unix/emuconsole.c (put): Pacify the compiler on + systems that require checking the return value of write. + +2013-11-13 Colin Watson + + * util/grub-install.in (efi_quiet): Fix inverted logic: make + efibootmgr quiet when --debug is not used, rather than when it is. + +2013-11-13 Colin Watson + + * gentpl.py (define_macro_for_platform_dependencies): Remove + first (and thus unused) of two definitions for this function. + (platform_dependencies): Likewise. + +2013-11-13 Colin Watson + + * acinclude.m4 (grub_apple_cc): Remove; since the removal of nested + functions, we only need to check this for the target, not the host. + * configure.ac (grub_apple_cc): Likewise. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/arm/cache.c (probe_caches): Move asm part to ... + * grub-core/kern/arm/cache_armv6.S: ... here. This allows this + asm to stay in arm even if surrounding is thumb. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/arm/misc.S: Add __muldi3 and __aeabi_lmul. Those + helper functions are needed for thumb. + +2013-11-13 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c (grub_diskfilter_make_raid): Make + level / 3 division explicitly unsigned. Saves few bytes. + +2013-11-13 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (ZAP_LEAF_NUMCHUNKS): Use unsigned arithmetics. + +2013-11-13 Vladimir Serbinenko + + * grub-core/normal/datetime.c (grub_get_weekday): Use if rather than + division. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/uboot/init.c: Move grub_uboot_machine_type and + grub_uboot_boot_data to asm part. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/arm/uboot/startup.S: Remove = by replacing with + literal load. + (grub_uboot_syscall): Save/restore r9 and align stack. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/arm/cache.S: Replace = with explicit litteral load. + +2013-11-13 Vladimir Serbinenko + + * include/grub/symbol.h (END) [__arm__]: New macros. Replace all .end + occurencies with END. + +2013-11-13 Colin Watson + + * util/grub-editenv.c (help_filter, argp): Document how to delete + the whole environment block. + Reported by Dan Jacobson. Fixes Debian bug #726265. + +2013-11-13 Colin Watson + + * docs/grub.texi (Internationalisation, Supported kernels): Fix + sectioning. + +2013-11-13 Josh Triplett + + * grub-core/normal/term.c (grub_set_more): Use bool logic rather than + increment/decrement. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/arm/cache_armv6.S [__clang__]: Don't add .armv6 when + compiling with clang. + +2013-11-13 Vladimir Serbinenko + + * grub-core/kern/arm/uboot/startup.S: Use .org rather than assigning + ".". + +2013-11-13 Vladimir Serbinenko + + Redirect all divisions to grub_divmod64. + +2013-11-12 Vladimir Serbinenko + + * grub-core/term/tparm.c (tparam_internal): Use unsigned divisions. + +2013-11-12 Vladimir Serbinenko + + Add missing includes of loader.h. + +2013-11-12 Vladimir Serbinenko + + * configure.ac: Allow disabling themes. + +2013-11-12 Lukas Schwaighofer + + * util/grub.d/20_linux_xen.in: Don't decompress initrd. + +2013-11-12 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c: Don't poll non-functional AT controller + until it becomes operational. + +2013-11-12 Vladimir Serbinenko + + * grub-core/Makefile.core.def (legacy_password_test): Disable + on platforms where no legacycfg is compiled. + * grub-core/tests/lib/functional_test.c: Tolerate failure to + load legacy_password_test. + +2013-11-12 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/efiemu/prepare.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/osdep/windows/hostdisk.c (grub_util_fd_strerror): Silence + strict-aliasing warning. + (fsync): Silence cast warning. + +2013-11-12 Vladimir Serbinenko + + * grub-core/commands/verify.c: Remove variable length arrays. + Load gcry_dsa/gcry_rsa automatically. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/signature_test.c: New test. + +2013-11-12 Vladimir Serbinenko + + * grub-core/disk/cryptodisk.c (luks_script_get): Adapt to new procfs + API. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/legacy_password_test.c (vectors): Make static. + * grub-core/tests/pbkdf2_test.c (vectors): Likewise. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/setjmp_test.c: Reset counter to 0 before starting. + +2013-11-12 Vladimir Serbinenko + + * grub-core/fs/proc.c: Allow \0 in proc files. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/xnu_uuid_test.c: Fix assert message. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/xnu_uuid_test.c: Fix copyright year. + +2013-11-12 Vladimir Serbinenko + + * grub-core/fs/ext2.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/lib/crypto.c (grub_crypto_cbc_decrypt): Remove variable + length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/disk/AFSplitter.c: Remove variable length arrays. + * grub-core/disk/cryptodisk.c: Likewise. + * grub-core/disk/geli.c: Likewise. + * grub-core/disk/luks.c: Likewise. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/legacy_password_test.c: New test. + * grub-core/commands/legacycfg.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/lib/pbkdf2.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/pbkdf2_test.c: New test. + +2013-11-12 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_dec_stream.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/io/lzopio.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * include/grub/crypto.h: Add maximums on hash size and cipher block + size. + +2013-11-12 Vladimir Serbinenko + + * grub-core/commands/xnu_uuid.c: Remove variable length arrays. + +2013-11-12 Vladimir Serbinenko + + * grub-core/tests/xnu_uuid_test.c: New test. + +2013-11-12 Vladimir Serbinenko + + * grub-core/commands/hashsum.c: Remove unneeded memset (zalloc already + covers it). + +2013-11-12 Vladimir Serbinenko + + * grub-core/commands/hashsum.c: Remove variable length arrays. + +2013-11-11 Vladimir Serbinenko + + * grub-core/tests/gfxterm_menu.c (gfxterm_menu): Handle out-of-memory + condition. + * tests/grub_func_test.in: Increase memory allocation. + +2013-11-11 Vladimir Serbinenko + + * grub-core/osdep/unix/getroot.c [HAVE_STRUCT_STATFS_F_FSTYPENAME + && HAVE_STRUCT_STATFS_F_MNTFROMNAME]: Include sys/param.h and + sys/mount.h. + +2013-11-11 Vladimir Serbinenko + + * grub-core/osdep/apple/hostdisk.c (grub_util_get_fd_size): Rename to .. + (grub_util_get_fd_size_os): ...this. + (grub_hostdisk_flush_initial_buffer): New empty function. + +2013-11-11 Vladimir Serbinenko + + * grub-core/gensyminfo.sh.in: Handle the case of portable output + without --defined-only. + +2013-11-11 Vladimir Serbinenko + + * grub-core/lib/i386/relocator_common.S [__APPLE__ && __x86_64__]: Use + rip-relative addressing in prologue. + +2013-11-11 Vladimir Serbinenko + + * include/grub/misc.h [__APPLE__]: Do not add regparm(0) on x86_64. + * grub-core/kern/misc.c (__bzero) [__APPLE__]: New function. + +2013-11-11 Vladimir Serbinenko + + * util/getroot.c (grub_util_biosdisk_get_grub_dev) [__APPLE__]: + Add missing semicolon. + +2013-11-11 Vladimir Serbinenko + + * util/grub-macho2img.c: Use plain fopen rather than grub_util_fopen. + +2013-11-11 Vladimir Serbinenko + + * configure.ac: Check for lzma.h for enabling liblzma and allow + manual disabling. + +2013-11-11 Vladimir Serbinenko + + Add missing includes of loader.h. + +2013-11-11 Fam Zheng + + * util/grub.d/30_os-prober.in: Add minix entry. + +2013-11-10 Vladimir Serbinenko + + * grub-core/loader/i386/coreboot/chainloader.c (load_segment): Use + right buffer for temporary load. + +2013-11-10 Vladimir Serbinenko + + * grub-core/loader/i386/coreboot/chainloader.c: Support tianocore. + +2013-11-10 Vladimir Serbinenko + + * grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed + payload. + +2013-11-10 Vladimir Serbinenko + + * include/grub/lib/LzmaDec.h: Fix to include LzmaTypes.h and + not Types.h. + * grub-core/lib/LzmaDec.c: Fix prologue to make it compileable in GRUB + environment. + (LzmaDec_InitDicAndState): Make static. + +2013-11-10 Vladimir Serbinenko + + * util/grub-mkimagexx.c (generate_elf): Fix module address on coreboot. + +2013-11-10 Vladimir Serbinenko + + * grub-core/term/ieee1275/escc.c (GRUB_MOD_INIT): Fix order of channels. + + Reported by: Aaro Koskinen + +2013-11-10 Vladimir Serbinenko + + * docs/grub-dev.texi: Replace bzr references with git ones. + +2013-11-10 Andrey Borzenkov + + * docs/grub.texi (Simple configuration): Remove reference to + grub-reboot from saved default entry description - grub-default + does not use it anymore. + +2013-11-10 Vladimir Serbinenko + + * configure.ac: Make efiemu test cflags match the cflags efiemu is + compiled with. + +2013-11-10 Andrey Borzenkov + + * docs/grub.texi (Simple configuration): Document GRUB_DISABLE_SUBMENU. + +2013-11-10 Vladimir Serbinenko + + Fix grub_machine_fini bitrot. + + Reported by: Glenn Washburn. + +2013-11-10 Vladimir Serbinenko + + * configure.ac: Remove leftover -fnested-funcions -Wl,-allow_execute. + +2013-11-10 Vladimir Serbinenko + + * grub-core/Makefile.am (efiemu): Remove leftover -DAPPLE_CC and + -DELF. + * grub-core/efiemu/runtime/config.h: Use __i386__ and __x86_64__ + instead of ELF*. + +2013-11-10 Vladimir Serbinenko + + * configure.ac: Restore CFLAGS to TARGET_CFLAGS before external tests. + Add -march=core2 when testing compile of efiemu64. + + Thanks Andrey Borzenkov for spotting this. + +2013-11-09 Vladimir Serbinenko + + Add new ports: i386-xen and x86_64-xen. This allows running GRUB in + XEN PV environment and load kernels. + +2013-11-09 Vladimir Serbinenko + + * grub-core/loader/i386/multiboot_mbi.c: Handle space in command line. + * grub-core/loader/multiboot_mbi2.c: Likewise. + +2013-11-09 Vladimir Serbinenko + + * grub-core/lib/cmdline.c (grub_loader_cmdline_size): Fix empty cmdline + handling. + +2013-11-09 Vladimir Serbinenko + + * grub-core/commands/i386/cmostest.c: Add new command "cmosset". + + Tested by: Denis 'GNUtoo' Carikli. + +2013-11-08 Vladimir Serbinenko + + * grub-core/normal/datetime.c (grub_get_weekday): Use unsigned types. + +2013-11-08 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_circular_progress.c (parse_angle): + Use to get rounded angle rather than truncated. + +2013-11-08 Vladimir Serbinenko + + * grub-core/term/serial.c: Add option for enabling/disabling + RTS/CTS flow control. + +2013-11-08 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/cipher/idea.c (mul_inv): Remove signed + divisions. + +2013-11-08 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/mpi/mpih-div.c (_gcry_mpih_divrem): + Use grub_fatal rather than divide by zero. + * grub-core/lib/libgcrypt/mpi/mpi-pow.c (gcry_mpi_powm): Likewise. + +2013-11-08 Vladimir Serbinenko + + * include/grub/gui.h (grub_fixed_sfs_divide): Round rather than + truncate. + (grub_fixed_fsf_divide): Likewise. + +2013-11-08 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_list.c (draw_scrollbar): Avoid + division by-zero and senseless negative divisions. + +2013-11-08 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_circular_progress.c (circprog_paint): Avoid + division by-zero and senseless negative divisions. + (circprog_set_property): Don't accept negative num_ticks. + +2013-11-08 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_progress_bar.c (draw_pixmap_bar): Avoid + division by-zero and senseless negative divisions. + +2013-11-08 Vladimir Serbinenko + + * configure.ac: Use elf_*_fbsd on kfreebsd. + +2013-11-08 Vladimir Serbinenko + + * grub-core/tests/div_test.c: New test. + +2013-11-08 Vladimir Testov + + * grub-core/gfxmenu/gui_box.c: Updated to work with area status. + * grub-core/gfxmenu/gui_canvas.c: Likewise. + * grub-core/gfxmenu/view.c: Likewise. + * grub-core/video/fb/video_fb.c: Introduce new functions: + grub_video_set_area_status, grub_video_get_area_status, + grub_video_set_region, grub_video_get_region. + * grub-core/video/bochs.c: Likewise. + * grub-core/video/capture.c: Likewise. + * grub-core/video/video.c: Likewise. + * grub-core/video/cirrus.c: Likewise. + * grub-core/video/efi_gop.c: Likewise. + * grub-core/video/efi_uga.c: Likewise. + * grub-core/video/emu/sdl.c: Likewise. + * grub-core/video/radeon_fuloong2e.c: Likewise. + * grub-core/video/sis315pro.c: Likewise. + * grub-core/video/sm712.c: Likewise. + * grub-core/video/i386/pc/vbe.c: Likewise. + * grub-core/video/i386/pc/vga.c: Likewise. + * grub-core/video/ieee1275.c: Likewise. + * grub-core/video/i386/coreboot/cbfb.c: Likewise. + * include/grub/video.h: Likewise. + * include/grub/video_fb.h: Likewise. + * include/grub/fbfill.h: Updated render_target structure. + grub_video_rect_t viewport, region, area + int area_offset_x, area_offset_y, area_enabled + * include/grub/gui.h: New helper function + grub_video_bounds_inside_region. + * docs/grub-dev.texi: Added information about new functions. + +2013-11-08 Vladimir Serbinenko + + * grub-core/kern/mm.c (grub_real_malloc): Use AND rather than MOD + for alignment. + +2013-11-08 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (grub_reed_solomon_recover): Add + missing attribute. + * grub-core/gdb/cstub.c (grub_gdb_trap): Likewise. + +2013-11-08 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_divmod64): Don't fallback to + simple division on arm and ia64. + +2013-11-08 Vladimir Serbinenko + + * grub-core/kern/arm/misc.S (__aeabi_unwind_cpp_pr0): Add dummy to + link with libgcc. + +2013-11-08 Vladimir Serbinenko + + * include/grub/symbol.h (FUNCTION), (VARIABLE): Fix precedence logic. + +2013-11-08 Vladimir Serbinenko + + * include/grub/symbol.h (FUNCTION), (VARIABLE) [__arm__]: Use % as + prefix symbol, not @. + +2013-11-08 Vladimir Serbinenko + + * INSTALL: Add note about older gcc and clang. + +2013-11-08 Vladimir Serbinenko + + * tests/util/grub-shell.in: Boot as hdd on ppc by default. + +2013-11-08 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_module): Fix + NULL pointer dereference. + +2013-11-07 Vladimir Serbinenko + + * grub-core/Makefile.am: Do not include libgcc.h when compiling with + clang. + +2013-11-07 Vladimir Serbinenko + + * grub-core/kern/powerpc/dl.c: Add missing pragma to silence cast-align + warnings. + +2013-11-07 Vladimir Serbinenko + + * grub-core/net/net.c (grub_net_route_unregister): Remove unused + function. + * grub-core/loader/i386/xnu.c (hextoval): Likewise. + * grub-core/disk/geli.c (ascii2hex): Likewise. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Run linker tests without -Werror. + Define TARGET_LDFLAGS_STATIC_LIBGCC and TARGET_LIBGCC. + Change all occurences of -static-libgcc resp -lgcc to + TARGET_LDFLAGS_STATIC_LIBGCC resp TARGET_LIBGCC. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Don't add -no-itegrated-as on clang on non-x86. + +2013-11-07 Vladimir Serbinenko + + Allow compiling with clang (not really supported though). + + * conf/Makefile.common (CFLAGS_PLATFORM): Don't add -mrtd -mregparm=3 + unconditionally. + * configure.ac: Add -no-integrated-as when using clangfor asm files. + Add -mrtd -mregparm=3 on i386 when not using clang. + * grub-core/kern/misc.c (grub_memset): Add volatile when on clang. + +2013-11-07 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c: Add explicit attribute on asm + bindings. + * grub-core/lib/reed_solomon.c: Likewise. + * include/grub/i386/gdb.h: Likewise. + * include/grub/i386/pc/int.h: Likewise. + * include/grub/i386/pc/pxe.h: Likewise. + * include/grub/ieee1275/ieee1275.h: Likewise. + +2013-11-07 Vladimir Serbinenko + + Import libgcrypt 1.5.3. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Don't add -Wcast-align on x86. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Add -freg-struct-return on all platforms that + support it. + +2013-11-07 Vladimir Serbinenko + + * acinclude.m4: Use -Werror on parameter tests. + * configure.ac: Likewise. + +2013-11-07 Vladimir Serbinenko + + * acinclude.m4: Add missing TARGET_CCASFLAGS on asm tests. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Check that -malign-loops works rather than assuming that + either -falign-loops or -malign-loops work. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Remove -fnested-functions. We don't need it anymore. + +2013-11-07 Vladimir Serbinenko + + * configure.ac: Prevent cflags leaking to subsequent tests by always + resetting cflags to target_cflags in target tests. + +2013-11-07 Vladimir Serbinenko + + * grub-core/kern/parser.c (grub_parser_split_cmdline): Remove nested + function. + +2013-11-07 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Remove nested functions. + +2013-11-07 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_parse): Remove nested function. + +2013-11-07 Vladimir Serbinenko + + * grub-core/normal/cmdline.c (grub_cmdline_get): + Remove nested functions. + +2013-11-07 Vladimir Serbinenko + + * tests/test_sha512sum.in: Make it work on emu. + +2013-11-07 Vladimir Serbinenko + + * grub-core/normal/charset.c (bidi_line_wrap): Eliminate nested + functions. + (grub_bidi_line_logical_to_visual): Likewise. + +2013-11-07 Vladimir Serbinenko + + Remove vestiges of -Wunsafe-loop-optimisations. + + * conf/Makefile.common (CFLAGS_GNULIB): Remove + -Wno-unsafe-loop-optimisations. + * grub-core/commands/legacycfg.c: Remove -Wunsafe-loop-optimisations + pragma. + * grub-core/io/gzio.c: Likewise. + * grub-core/script/parser.y: Likewise. + * grub-core/script/yylex.l: Likewise. + * util/grub-mkfont.c: Likewise. + +2013-11-07 Vladimir Serbinenko + + * util/grub-mkfont.c (process_cursive): Remove nested function. + +2013-11-07 Vladimir Serbinenko + + * include/grub/misc.h (grub_dprintf): Use unnamed vararg. + (grub_boot_time): Likewise. + +2013-11-07 Vladimir Serbinenko + + * include/grub/symbol.h (FUNCTION): Use @function rather than + "function". + (VARIABLE): Likewise. + +2013-11-07 Vladimir Serbinenko + + * grub-core/net/bootp.c (OFFSET_OF): Explicitly cast to grub_size_t. + +2013-11-07 Vladimir Serbinenko + + * grub-core/net/bootp.c (set_env_limn_ro): Make pointer const. + (parse_dhcp_vendor): Likewise. + +2013-11-07 Vladimir Serbinenko + + * util/grub-mkimagexx.c (relocate_symbols): Remove unneeded brackets. + +2013-11-07 Vladimir Serbinenko + + * grub-core/gettext/gettext.c (main_context), (secondary_context): + Define after defining type and not before. + +2013-11-07 Vladimir Serbinenko + + * grub-core/fs/zfs/zfscrypt.c (grub_ccm_decrypt): Return right error + type. + (grub_gcm_decrypt): Likewise. + (algo_decrypt): Likewise. + (grub_zfs_decrypt_real): Transform error type. + +2013-11-07 Vladimir Serbinenko + + * grub-core/disk/geli.c (geli_rekey): Fix error return type. + +2013-11-07 Vladimir Serbinenko + + * grub-core/disk/usbms.c (grub_usbms_cbi_cmd): Fix error type. + (grub_usbms_cbi_reset): Likewise. + (grub_usbms_bo_reset): Likewise. + (grub_usbms_reset): Likewise. + (grub_usbms_attach): Likewise. + (grub_usbms_transfer_cbi): Likewise. + +2013-11-07 Vladimir Serbinenko + + * grub-core/io/lzopio.c (test_header): Simplify code and remove useless + "checksum = checksum;". + +2013-11-07 Vladimir Serbinenko + + * grub-core/fs/reiserfs.c (grub_reiserfs_iterate_dir): Fix type of + entry_type. + +2013-11-07 Vladimir Serbinenko + + * grub-core/commands/legacycfg.c (grub_cmd_legacy_kernel): Fix + BIOS disk check. + +2013-11-07 Vladimir Serbinenko + + * grub-core/bus/usb/ehci.c (grub_ehci_restore_hw): Return right enum + type. + (grub_ehci_fini_hw): Likewise. + * grub-core/bus/usb/usbhub.c (grub_usb_add_hub): Likewise. + +2013-11-07 Vladimir Serbinenko + + * include/grub/usb.h (grub_usb_controller_dev): Make portstatus + return grub_usb_err_t for cosistency. All users updated. + +2013-11-07 Vladimir Serbinenko + + * util/mkimage.c (SzAlloc): Use attribute unused rather than dubious + assigning to itself. + +2013-11-05 Gustavo Luiz Duarte +2013-11-05 Paulo Flabiano Smorigo + + Issue separate DNS queries for ipv4 and ipv6 + + Adding multiple questions on a single DNS query is not supportted by + most DNS servers. This patch issues two separate DNS queries + sequentially for ipv4 and then for ipv6. + + Fixes: https://savannah.gnu.org/bugs/?39710 + + * grub-core/net/bootp.c (parse_dhcp_vendor): Add DNS option. + * grub-core/net/dns.c (grub_dns_qtype_id): New enum. + * (grub_net_dns_lookup): Now using separated dns packages. + * (grub_cmd_nslookup): Add error condition. + * (grub_cmd_list_dns): Print DNS option. + * (grub_cmd_add_dns): Add four parameters: --only-ipv4, --only-ipv6, + --prefer-ipv4, and --prefer-ipv6. + * include/grub/net.h (grub_dns_option_t): New enum. + * (grub_net_network_level_address): option added. + +2013-11-05 Vladimir Testov + + * grub-core/video/fb/video_fb.c: Merge two blit functions + into one. + +2013-11-05 Vladimir Serbinenko + + * grub-core/term/terminfo.c: Add sequences for home and end. + +2013-11-05 Vladimir Serbinenko + + * grub-core/lib/legacy_parse.c: Fix handling of hercules and add + graphics console. + +2013-11-05 Vladimir Serbinenko + + * grub-core/video/i386/pc/vga.c: Fix double bufferring and + add mode 0x12. + +2013-11-04 Vladimir Serbinenko + + * docs/grub.texi (Vendor power-on keys): Add XPS M1330M based on old + e-mail by Per Öberg. + +2013-11-04 Vladimir Serbinenko + + * grub-core/commands/i386/nthibr.c (GRUB_MOD_INIT): Fix typo in command + name. + +2013-11-04 Andrey Borzenkov + + * configure.ac: Explicitly disable emusdl, emuusb and emupci on non- + emu platforms. + * grub-core/Makefile.core.def: Enable emupci and emuucb only for emu. + +2013-11-04 Vladimir Serbinenko + + * docs/grub.texi: Document usage of menuentry id. + +2013-11-04 Vladimir Serbinenko + + * docs/grub.texi: Add few mentions about EFI, debug and videoinfo. + +2013-11-04 Peter Lustig + + * grub-core/commands/i386/nthibr.c: New command. + +2013-11-04 Vladimir Serbinenko + + * grub-core/tests/video_checksum.c: Add 2560x1440 mode to testing. + +2013-11-04 Vladimir Serbinenko + + * include/grub/term.h (grub_term_coordinate): Extend to 16-bit per + coordinate. + +2013-11-04 Vladimir Serbinenko + + Support GRUB_DISABLE_SUBMENU config. + + Inspired by patch from Prarit Bhargava. + +2013-11-03 Vladimir Serbinenko + + * docs/grub.texi: Mention RSA support. + +2013-11-03 Vladimir Serbinenko + + * grub-core/commands/verify.c: Add RSA support. + +2013-11-03 Vladimir Serbinenko + + * grub-core/disk/ahci.c (grub_ahci_pciinit): Detect ATAPI devices. + * grub-core/disk/ata.c (grub_ata_identify): Use atapi_identify if + device is known to be ATAPI. + +2013-11-03 Mike Frysinger + + * configure.ac: Don't add target-prefix. + +2013-11-03 Vladimir Serbinenko + + * grub-core/commands/loadenv.c (grub_cmd_save_env): Remove unset + variables. + +2013-11-03 Vladimir Serbinenko + + * grub-core/gettext/gettext.c (grub_gettext_init_ext): Ignore errors + if language is English. + +2013-11-03 Vladimir Serbinenko + + * grub-core/osdep/linux/getroot.c: Fix cast-align problems. + +2013-11-02 Vladimir Serbinenko + + * configure.ac: Don't add -m32/-m64 on emu. + +2013-11-02 neil + + * grub-core/osdep/linux/blocklist.c: Include linux/types.h for some + broken linux headers. + +2013-11-02 Vladimir Serbinenko + + * util/grub.d/30_os-prober.in: Add unhiding of partition if on msdos. + +2013-11-02 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (grub_reed_solomon_recover): Don't do + Reed-Solomon recovery if more than half of redundancy info is 0. + +2013-11-02 Vladimir Serbinenko + + * util/grub-mount.c: Handle symlinks to directories. + +2013-11-02 Vladimir Serbinenko + + * grub-core/fs/fshelp.c (find_file): Save ctx->next when calling + find_file recursively for symlink. + +2013-11-02 Vladimir Serbinenko + + * tests/util/grub-shell.in: Copy themes. + +2013-11-02 Vladimir Serbinenko + + * util/grub-mkimagexx.c (locate_sections): Reject mislinked images. + +2013-11-02 Vladimir Serbinenko + + * configure.ac: Use 0x8000 for address instead of 8000. + +2013-11-02 Vladimir Serbinenko + + * grub-core/loader/sparc64/ieee1275/linux.c (get_physbase): Fix + signature. + +2013-11-02 Vladimir Serbinenko + + * grub-core/disk/efi/efidisk.c (grub_efidisk_readwrite): Remove unused + variable. + +2013-11-02 Vladimir Serbinenko + + * configure.ac (TARGET_CFLAGS): Add -march=i386 on i386. + +2013-11-02 Vladimir Serbinenko + + * grub-core/fs/hfspluscomp.c (hfsplus_read_compressed_real): Call + file_progress_read_hook. + * grub-core/fs/ntfscomp.c (hfsplus_read_compressed_real): Likewise. + +2013-11-02 Vladimir Serbinenko + + * conf/Makefile.common (CFLAGS_PLATFORM): Remove poisoning of float + and double. + +2013-11-01 Vladimir Serbinenko + + * grub-core/fs/tar.c (grub_cpio_read): Add read_hook. + +2013-11-01 Vladimir Serbinenko + + Rewrite blocklist functions in order to get progress when + reading large extents and decrease amount of blocklist hook calls. + +2013-11-01 Vladimir Serbinenko + + * grub-core/term/serial.c (options), (grub_cmd_serial): Fix handling + of SI suffixes. + +2013-11-01 Vladimir Serbinenko + + Support --base-clock for serial command to handle weird cards with + non-standard base clock. + +2013-11-01 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext2_read_symlink): Use memcpy rather + strncpy. + * grub-core/fs/jfs.c (grub_jfs_lookup_symlink): Likewise. + * grub-core/kern/misc.c (grub_strncpy): Move from here ... + * include/grub/misc.h (grub_strncpy): ... to here. Make inline. + * grub-core/net/net.c (grub_net_addr_to_str): Use COMPILE_TIME_ASSERT + + strcpy rather than strncpy. + +2013-11-01 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (nvpair_name): Use correct type for size. + (check_pool_label): Likewise. Fixes overflow. + (nvlist_find_value): Fix comparison. + +2013-11-01 Vladimir Serbinenko + + * include/grub/misc.h (grub_strcat): Removed. All users changed to + more appropriate functions. + +2013-11-01 Vladimir Serbinenko + + * grub-core/kern/efi/efi.c (grub_efi_get_filename): Avoid inefficient + realloc. + +2013-11-01 Vladimir Serbinenko + + * util/grub-mkrescue.in: Do not use UUID search on EFI. + +2013-11-01 Vladimir Serbinenko + + * grub-core/kern/dl.c: Unify section-finding algorithm. Saves 30 bytes + on core size. + +2013-10-30 Vladimir Serbinenko + + * grub-core/kern/mm.c (grub_realloc): Don't copy more data than we have. + +2013-10-30 Vladimir Serbinenko + + * grub-core/io/gzio.c (huft_build): Use zalloc for safety. + (initialize_tables): reset tl and td to NULL after freeing. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c: Implement network tag. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c: Add EFI memory map to the list + of supported tags. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c: Implement EFI memory map. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/multiboot.c: Add support for multiboot kernels + quirks. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (allocate_pages): Allocate at least + a page in protected space. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/multiboot.c (grub_cmd_module): Don't attempt to + allocate space for zero-sized modules. + +2013-10-28 Vladimir Serbinenko + + * grub-core/loader/xnu_resume.c (grub_xnu_resume): Reject empty images. + +2013-10-28 Francesco Lavra + + * grub-core/lib/fdt.c: Fix miscellaneous bugs. + +2013-10-28 Vladimir Serbinenko + + * grub-core/lib/progress.c (grub_file_progress_hook_real): Add missing + safeguards. Fixes a crash with i386/pc/console.c. + +2013-10-28 Vladimir Serbinenko + + * include/grub/emu/hostdisk.h: Add proper declaration for grub_host_init + and grub_hostfs_init. + +2013-10-28 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_check_file_presence): Use + windows method on other platforms without good stat as well. + +2013-10-28 Vladimir Serbinenko + + * grub-core/osdep/linux/getroot.c: Add new btrfs defines. + +2013-10-28 Vladimir Serbinenko + + Make / in btrfs refer to real root, not the default volume. + Modify mkrelpath to work even if device is mounted with subvolid option. + +2013-10-28 Andrey Borzenkov + + * Makefile.util.def: Add grub-core/kern/disk_common.c to library + extra_dist. + * grub-core/Makefile.core.def: Add kern/disk_common.c to disk module + extra_dist. + +2013-10-27 Vladimir Serbinenko + + * util/grub-mkfont.c (main): Show error message when FT_Set_Pixel_Sizes + fails. + +2013-10-27 BVK Chaitanya + + * docs/autoiso.cfg: New file. + +2013-10-27 Vladimir Serbinenko + + * configure.ac: Remove leftover COND_BUILD_GRUB_MKFONT and + COND_GRUB_PE2ELF conditions. + +2013-10-27 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Accept "sd", "cd", + "vnd", "rd" and "fd" disks. + +2013-10-27 Vladimir Serbinenko + + Move grub_disk_write out of kernel into disk.mod. + +2013-10-27 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Unify int and wchar + handling. + +2013-10-27 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_abort): Make static + +2013-10-27 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Don't attempt to + transform invalid unicode codepoints. + +2013-10-27 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Remove needless explicit + \0 checking. + +2013-10-27 Vladimir Serbinenko + + * grub-core/lib/legacy_parse.c: Add support for "nd" disk. + +2013-10-26 Vladimir Serbinenko + + Consolidate cpuid code. + +2013-10-26 Vladimir Serbinenko + + Move cpuid code to cpuid.h and TSC code to tsc.c. + +2013-10-26 Grégoire Sutre + + * util/grub.d/00_header.in: Don't use LANG if it's not set. + +2013-10-26 Grégoire Sutre + + * util/grub-mkconfig.in: Replace $0 with $self. + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + +2013-10-26 BVK Chaitanya + + * docs/osdetect.cfg: New file. + +2013-10-26 BVK Chaitanya + + * tests/util/grub-shell.in: Add new --debug option. + +2013-10-26 BVK Chaitanya + + * tests/test_unset.in: New test. + +2013-10-26 BVK Chaitanya + + * tests/test_sha512sum.in: New test. + +2013-10-26 Vladimir Serbinenko + + * grub-core/fs/iso9660.c: Replace strncat with memcpy. + * include/grub/misc.h: Remove strncat. + * grub-core/lib/posix_wrap/string.h: Likewise. + +2013-10-26 Vladimir Serbinenko + + * grub-core/net/tftp.c: Retransmit ack when rereceiving old packet. + Try to handle more than 0xFFFF packets. + Reported by: Bernhard Übelacker . + He also spotted few overflows in first version of this patch. + +2013-10-26 Vladimir Serbinenko + + * tests/date_unit_test.c: New test. + +2013-10-26 Vladimir Serbinenko + + * grub-core/normal/datetime.c (grub_unixtime2datetime): Fix mishandling + of first three years after start of validity of unixtime. + +2013-10-26 Vladimir Serbinenko + + * grub-core/normal/menu_entry.c (get_logical_num_lines): Use unsigned + division as the one making more sense. + (update_screen): Likewise. + (complete): Likewise. + +2013-10-25 Vladimir Serbinenko + + * grub-core/normal/menu_entry.c (complete): Make sure that width is >0. + +2013-10-25 Vladimir Serbinenko + + Make char and string width grub_size_t rather than grub_ssize_t. + +2013-10-25 Vladimir Serbinenko + + * grub-core/normal/cmdline.c (grub_history_get): Make argument into + unsigned. + (grub_history_replace): Likewise. + +2013-10-25 Vladimir Serbinenko + + * grub-core/disk/raid6_recover.c: Use unsigned arithmetics when + appropriate. + +2013-10-25 Vladimir Serbinenko + + * grub-core/video/bitmap_scale.c: Use unsigned arithmetics when + appropriate. + +2013-10-25 Vladimir Serbinenko + + * grub-core/video/fb/fbblit.c: Use (255 ^ x) rather than (255 - x). + Use unsigned divisions rather than signed variants. + +2013-10-25 Vladimir Serbinenko + + * grub-core/video/readers/png.c (grub_png_convert_image): Use + unsigned arithmetics. + Add missing break. + +2013-10-25 Vladimir Serbinenko + + * grub-core/video/readers/jpeg.c: Use unsigned where appropriate. + +2013-10-25 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (xor_out): Use unsigned modular arithmetics + rather than signed one. + (recovery): Likewise. + +2013-10-25 Vladimir Serbinenko + + * grub-core/net/dns.c (hash): Use unsigned arithmetic. + +2013-10-25 Vladimir Serbinenko + + * grub-core/io/gzio.c (test_zlib_header): Use undigned modulo rather + than signed. + +2013-10-25 Jon McCune + + * docs/grub.texi: Cleanup security documentation around signatures. + +2013-10-25 Vladimir Serbinenko + + * grub-core/fs/ext2.c (EXT2_BLOCK_SIZE): Make unsigned. + +2013-10-25 Vladimir Serbinenko + + * grub-core/commands/gptsync.c (lba_to_chs): Use proper types rather + than int. + +2013-10-25 Vladimir Serbinenko + + * conf/Makefile.common (CPPFLAGS_KERNEL): Add -DGRUB_KERNEL=1. + * include/grub/dl.h (GRUB_MOD_INIT), (GRUB_MOD_FINI): Define + functions when compiling for kernel. + +2013-10-25 Vladimir Serbinenko + + * grub-core/lib/progress.c (grub_file_progress_hook_real): Cast to + unsigned long long when using %llu. + +2013-10-25 Vladimir Serbinenko + + * grub-core/lib/progress.c (grub_file_progress_hook_real): Refresh + terminal after updating progress. + +2013-10-25 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S (grub_gate_a20): Remove + argument. We don't disable Gate A20 in this code. + +2013-10-25 Vladimir Serbinenko + + * grub-core/boot/i386/qemu/boot.S: Ensure that A20 is enabled. + Conceptually based on change in branch "vbe-on-coreboot". + +2013-10-24 Robert Millan + + * grub-core/video/i386/pc/vbe.c (grub_video_vbe_setup): Replace + numeric constants with their symbolic equivalent. + Taken from branch "vbe-on-coreboot". + +2013-10-22 Vladimir Serbinenko + + * docs/grub.texi: Fix ordering and use pxref rather than xref. + +2013-10-22 Vladimir Serbinenko + + * grub-core/lib/progress.c (grub_file_progress_hook_real): Use + divmod64 for offset division. + +2013-10-22 Paulo Flabiano Smorigo + + Rename .bzrignore to .gitignore. Add "*.o" rule. + + * .bzrignore: Renamed to... + * .gitignore: ...this. + +2013-10-22 Paulo Flabiano Smorigo + + Add new progress module that displays the load progress of files. + + * grub-core/lib/progress.c: New file. + * grub-core/Makefile.core.def (progress): New module. + * grub-core/kern/file.c (grub_file_open): File name added. + * (grub_file_read): Progress hook added. + * grub-core/fs/cbfs.c (grub_cbfs_read): Likewise. + * grub-core/fs/cpio_common.c (grub_cpio_read): Likewise. + * grub-core/net/net.c (grub_net_fs_read_real): Likewise. + * include/grub/file.h (struct grub_file): Add progress module members. + * include/grub/term.h (struct grub_term_output): Likewise. + * grub-core/osdep/unix/emuconsole.c (grub_console_term_output): + Terminal velocity added. + * grub-core/osdep/windows/emuconsole.c (grub_console_term_output): Likewise. + * grub-core/term/arc/console.c (grub_console_term_output): Likewise. + * grub-core/term/efi/console.c (grub_console_term_output): Likewise. + * grub-core/term/gfxterm.c (grub_video_term): Likewise. + * grub-core/term/i386/coreboot/cbmemc.c (grub_cbmemc_term_output): Likewise. + * grub-core/term/i386/pc/console.c (grub_console_term_output): Likewise. + * grub-core/term/i386/pc/vga_text.c (grub_vga_text_term): Likewise. + * grub-core/term/ieee1275/console.c (grub_console_term_output): Likewise. + * grub-core/term/morse.c (grub_audio_term_output): Likewise. + * grub-core/term/serial.c (grub_serial_term_output): Likewise. + * grub-core/term/spkmodem.c (grub_spkmodem_term_output): Likewise. + * grub-core/term/uboot/console.c (uboot_console_term_output): Likewise. + +2013-10-22 Vladimir Serbinenko + + Verify signatures of signatures unless --skip-sig is specified. + +2013-10-21 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Remove needless explicit + \0 checking. + + Saves 70 bytes on compressed image. + +2013-10-21 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_strtoull): Remove needless *ptr != 0 + check. + + Saves 10 bytes on compressed image. + +2013-10-21 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_isprint): Move to ... + * include/grub/misc.h (grub_isprint): ... here. Make inline. + + Saves 20 bytes on compressed image due to remving exporting. + +2013-10-21 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (grub_ntfs_mount): Remove redundant check. + + Saves 5 bytes on compressed image. + +2013-10-21 Vladimir Serbinenko + + * grub-core/fs/ntfs.c: Move common UTF-16 handling to a separate + function get_utf8. + + Saves 379 bytes on compressed image. + +2013-10-21 Vladimir Serbinenko + + * grub-core/fs/ntfs.c: Handle 48-bit MFT no. + +2013-10-21 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (read_run_data): Rewrite using bitfields. + + Saves 40 bytes on compressed image. + +2013-10-21 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (grub_ntfs_iterate_dir): Use grub_uint8_t for + mask rather than 64-bit type. + + Saves 20 bytes on compressed image. + +2013-10-21 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (read_data): Move code for compressed data to ... + * grub-core/fs/ntfscomp.c (ntfscomp): ... here. + + Saves 273 bytes on compressed image. + +2013-10-20 Vladimir Serbinenko + + * grub-core/kern/disk.c (grub_disk_write): Use malloc/free instead of + variable length arrays. + + Saves 50 bytes on compressed image. + +2013-10-20 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c: Remove variable length arrays. + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/ufs.c: Remove variable length arrays. + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/ntfs.c: Add comment about fixed allocation size. + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/zfs.c: Remove variable length arrays. + Reduces zfs.mod by 160 bytes (208 compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (check_pool_label): Fix memory leak. + +2013-10-20 Vladimir Serbinenko + + * grub-core/net/arp.c: Remove variable length arrays. + * grub-core/net/bootp.c: Likewise. + * grub-core/net/dns.c: Likewise. + * grub-core/net/icmp6.c: Likewise. + * grub-core/net/net.c: Likewise. + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/ntfs.c: Remove variable length arrays. + Increases ntfs.mod by 64 bytes (but decreases by 3 when + compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/hfs.c: Remove variable length arrays. + Reduces hfs.mod by 8 bytes (52 compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/udf.c: Remove variable length arrays. + Increases udf.mod by 128 bytes (but decreases by 13 when + compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/iso9660.c: Remove variable length arrays. + Increases iso9660.mod by 200 bytes (but decreases by 79 when + compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c: Remove variable length arrays. + Increases nilfs2.mod by 24 bytes (but decreases by 115 when + compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/xfs.c: Remove variable length arrays. + Reduces xfs.mod by 40 bytes (43 compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/fshelp.c: Remove variable length arrays. + Reduces fshelp.mod by 116 bytes (23 compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/normal/completion.c: Remove variable length arrays. + * grub-core/normal/menu_entry.c: Likewise. + + Reduces normal.mod by 496 bytes. + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/minix.c: Remove variable length arrays. Reduces jfs.mod + by 356 bytes (158 compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/jfs.c: Remove variable length arrays. Reduces jfs.mod + by 364 bytes (169 compressed). + +2013-10-20 Vladimir Serbinenko + + * grub-core/fs/bfs.c: Remove variable length arrays. Reduces afs.mod and + bfs.mod size by 556 resp 740 bytes (288 resp 334 compressed). + * include/grub/types.h (grub_unaligned_uint64_t): New type. + +2013-10-19 Vladimir Serbinenko + + Lift 255x255 erminal sie restriction to 65535x65535. Also change from + bitmasks to small structures of size chosen to fit in registers. + +2013-10-19 Vladimir Serbinenko + + * conf/Makefile.common: Use -freg-struct-return on i386. This + decreases code size and improves performance. + +2013-10-19 Vladimir Serbinenko + + * grub-core/osdep/unix/exec.c: Fix compilation error on emu. + +2013-10-19 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Fix formatting of + "(null)" string. + Simplify expressions to save around 256 bytes in kernel.img. + * tests/printf_unit_test.c (printf_test): Add "(null)" tests. + +2013-10-19 Vladimir Serbinenko + + * grub-core/tests/video_checksum.c (grub_video_capture_write_bmp): + Use GRUB_UTIL_FD_O_* rather than O_*. + +2013-10-19 Vladimir Serbinenko + + Add haiku-specific functions. + +2013-10-19 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c: Remove few leftover includes. + +2013-10-19 Vladimir Serbinenko + + Move stat () and device mode checking into OS-dependent files as + long as performance doesn't suffer. + +2013-10-19 Vladimir Serbinenko + + Split make_system_path_relative_to_its_root into separate file + relpath.c from getroot.c as it's common between unix and haiku + but otherwise haiku doesn't use any functions from unix getroot.c. + +2013-10-19 Vladimir Serbinenko + + * grub-core/osdep/aros/hostdisk.c (grub_util_is_directory): + New function. + (grub_util_is_special_file): Likewise. + +2013-10-19 Vladimir Serbinenko + + * grub-core/osdep/unix/getroot.c: Move exec functions to ... + * osdep/unix/exec.c: ... here. Add few additional exec_* variants. + +2013-10-19 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Define size_t to + grub_size_t. This fixes the case when size_t mismatches grub_size_t. + +2013-10-19 Vladimir Serbinenko + + * util/grub-mkimagexx.c (make_reloc_section): Fix memory leak. + (load_image): Likewise. + +2013-10-19 Vladimir Serbinenko + + * util/grub-render-label.c: Move backend part to ... + * util/render-label.c: ... here. + +2013-10-18 Vladimir Serbinenko + + * grub-core/osdep/random.c: Use unix/random.c on haiku. Haiku uses + yarrow (by B. Schneier et al) for its /dev/urandom (similar to FreeBSD). + +2013-10-18 Vladimir Serbinenko + + * grub-core/osdep/generic/blocklist.c: Add missing include to string.h. + +2013-10-18 Vladimir Serbinenko + + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Handle + CD-ROM in case when it's declared as having subpartitions. + +2013-10-18 Vladimir Serbinenko + + Don't add -lm on haiku. + + * configure.ac: Define BUILD_LIBM to -lm on most platforms + and empty on haiku. + * grub-core/Makefile.am (gentrigtables): Use $(BUILD_LIBM) rather than + -lm. + +2013-10-18 Vladimir Serbinenko + + * configure.ac: Use -melf_*_haiku as target on haiku. + +2013-10-18 Vladimir Serbinenko + + * Makefile.util.def: Add util/setup.c to extra_dist. + +2013-10-18 Vladimir Serbinenko + + * grub-core/kern/i386/pc/mmap.c (grub_machine_mmap_iterate): Pass + unknown types through. + +2013-10-18 Vladimir Serbinenko + + * grub-core/osdep/unix/getroot.c (grub_util_check_block_device): Remove. + (grub_util_check_char_device): Likewise. + * include/grub/emu/getroot.h: Likewise. + +2013-10-18 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Use define for defining + memset rather than inline static function. + +2013-10-18 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_config.h: Enable all bcj filters when + not doing embedded decompressor. + +2013-10-18 Vladimir Serbinenko + + * grub-core/disk/ldm.c: Rename variables and arguments to prevent + shadowing. + * grub-core/kern/disk.c: Likewise. + * grub-core/kern/misc.c: Likewise. + * include/grub/parser.h: Likewise. + * include/grub/script_sh.h: Likewise. + * include/grub/zfs/zfs.h: Likewise. + +2013-10-18 Vladimir Serbinenko + + * grub-core/disk/luks.c (configure_ciphers): Fix spurious warning. + +2013-10-18 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs_lz4.c: Check that __INTEL_COMPILER is + defined before trying to use it. + +2013-10-18 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_create_node): Fix uninited value + warning. + +2013-10-18 Vladimir Serbinenko + + * include/grub/dl.h: Remove double declaration of GRUB_MOD_DEP. + Use __unused__ rather than __used__ on gcc < 3.2. + +2013-10-18 Vladimir Serbinenko + + * include/grub/setjmp.h: Define RETURNS_TWICE. Keep it empty for + gcc < 4.0. + * include/grub/*/setjmp.h: USe RETURNS_TWICE. + +2013-10-18 Vladimir Serbinenko + + * grub-core/disk/dmraid_nvidia.c: Fix potentially uninited "layout". + +2013-10-18 Vladimir Serbinenko + + * include/grub/misc.h: Don't use warn_unused_result on gcc < 3.4. + * include/grub/emu/misc.h: Likewise. + +2013-10-18 Vladimir Serbinenko + + * grub-core/term/i386/pc/vga_text.c: Remove extra declaration of + cur_color. + +2013-10-18 Vladimir Testov + + * grub-core/tests/checksums.h: Regenerated due to progress bar + get_minimal_size changes. + +2013-10-17 BVK Chaitanya + + Added `tr' command support. + + * grub-core/commands/tr.c: New file. + * grub-core/Makefile.core.def: Build rules for new module. + + * tests/grub_cmd_tr.in: New test. + * Makefile.util.def: Build rules for new test. + +2013-10-17 Vladimir Testov + + * grub-core/gfxmenu/gui_progress_bar.c: Sanity checks added. + +2013-10-17 Vladimir Testov + + * grub-core/gfxmenu/gui_progress_bar.c: New option ``highlight_overlay`` + * docs/gurb.texi: Likewise. + +2013-10-17 Vladimir Testov + + * grub-core/gfxmenu/gui_progress_bar.c (draw_pixmap_bar): Fixed bug. + Pixmap highlighted section with east and west slices was displayed + incorrectly due to negative width of the central slice. + +2013-10-17 Vladimir Testov + + * docs/grub.texi: Graphical options information update. + Removed outdated. Updated current. Inserted missed. + +2013-10-17 Vladimir Serbinenko + + * docs/grub.texi: Mention few new platform-specific commands. + +2013-10-17 Vladimir Serbinenko + + * grub-core/script/yylex.l: Fix LSQBR2 and RSQBR2. It's not + currently used so this doesn't really have any effect. + Reported by: Douglas Ray + +2013-10-17 Vladimir Serbinenko + + * autogen.sh: Don't set LC_CTYPE as it doesn't create problem for + compilation but prevents gcc from displaying messages in non-Latin + alphabets. + * conf/Makefile.common: Likewise. + +2013-10-16 Hiroyuki YAMAMORI + + Handle Japanese special keys. + Reported by: Hiroyuki YAMAMORI. + Codes supplied by: Hiroyuki YAMAMORI. + +2013-10-16 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: Scrollbar sanity checks added. + +2013-10-16 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: New option `item_pixmap_style`. + * docs/grub.texi: Likewise. + +2013-10-16 Vladimir Serbinenko + + * grub-core/osdep/unix/hostdisk.c (grub_util_fd_read): Return correct + value in case of incomplete read. + (grub_util_fd_write): Likewise. + +2013-10-15 Vladimir Serbinenko + + * util/editenv.c (grub_util_create_envblk_file): Use grub_util_rename. + +2013-10-15 Vladimir Serbinenko + + * util/grub-editenv.c (create_envblk_file): More from here ... + * util/editenv.c (grub_util_create_envblk_file): ... to here. + +2013-10-15 Vladimir Serbinenko + + * grub-core/osdep/unix/getroot.c (grub_guess_root_devices): + canonicalize file name before doing the rest. + +2013-10-15 Vladimir Serbinenko + + * include/grub/osdep/hostfile_windows.h: Add missing ftello for + mingw32. + +2013-10-15 Vladimir Serbinenko + + Define grub_util_is_directory/regular/special_file and + use OS-dependent versions rather than to rely on stat(). + +2013-10-15 Vladimir Serbinenko + + * util/grub-mkimage.c: Move backend part to ... + * util/mkimage.c: ... here. + +2013-10-15 Vladimir Serbinenko + + Allow compilation with mingw64 albeit with warnings due to lack of + %llx/%llu. + + * grub-core/gnulib/msvc-inval.c: Use __cdecl rather than cdecl. + * grub-core/lib/posix_wrap/wchar.h: Define wint_t. + * grub-core/lib/posix_wrap/wctype.h: Define wctype_t. + * include/grub/osdep/hostfile_windows.h: Don't define fseeko/ftello + on mingw64. + * include/grub/types.h: Allow sizeof (long) != sizeof (void *). + +2013-10-15 Vladimir Serbinenko + + Remove leftover references to some of the system headers. + +2013-10-15 Vladimir Serbinenko + + * grub-core/disk/geli.c (grub_util_get_geli_uuid): Close handle after + read. + +2013-10-15 Vladimir Serbinenko + + * grub-core/disk/cryptodisk.c: Use grub_util_fd_strerror instead + of strerror. + +2013-10-15 Vladimir Serbinenko + + Split out blocklist retrieving from setup.c to + grub-core/osdep/blocklist.c and add windows implementation since + generic version doesn't work on NTFS on Windows due to aggressive + unflushable cache. + +2013-10-15 Vladimir Serbinenko + + Split grub-setup.c into frontend (grub-setup.c) and backend (setup.c) + files. + +2013-10-15 Vladimir Serbinenko + + * grub-core/osdep/windows/hostdisk.c (grub_util_fd_strerror): + Cut tailing newline. Remove arbitrary limitation. Always use + grub_util_tchar_to_utf8. + +2013-10-15 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Handle %% properly. + * tests/printf_unit_test.c (printf_test): Add %% tests. + Reported by: Paulo Flabiano Smorigo. + +2013-10-15 Vladimir Serbinenko + + * grub-core/osdep/windows/hostdisk.c (fsync) [__MINGW32__]: Really + implement fsync. + +2013-10-15 Vladimir Serbinenko + + * configure.ac: Check for nvlist_lookup_string in nvpair since we + use nvlist_lookup_string and don't use nvlist_print. + +2013-10-15 Vladimir Serbinenko + + Add wrappers around rename, unlink, mkdir, opendir, readdir and + closedir to handle filename charset translation. + +2013-10-15 Vladimir Serbinenko + + * include/grub/emu/hostdisk.h: Move file operations to + * include/grub/emu/hostfile.h: ... here. + +2013-10-15 Vladimir Serbinenko + + * grub-core/osdep/windows/hostdisk.c (canonicalize_file_name): Handle + unicode path. + +2013-10-15 Vladimir Serbinenko + + * grub-core/tests/checksums.h: Regenerate due to swiss.sed change. + +2013-10-15 Vladimir Serbinenko + + Move cpu time retrieval to separate grub_util_get_cpu_time_ms + and remove export.h. + +2013-10-15 Vladimir Serbinenko + + * grub-core/kern/emu/error.c: Removed. + * grub-core/Makefile.core.def (kernel): Don't add error.c and progname.c + explicitly as it's already in libgnu.a. + +2013-10-15 Vladimir Serbinenko + + * grub-core/osdep/windows/emuconsole.c: Add missing config.h and + config-util.h include. + +2013-10-15 Vladimir Serbinenko + + Split emunet into platform-dependent and GRUB-binding parts. Keep + platform-dependent part in kernel for easy access to OS functions. + +2013-10-15 Vladimir Serbinenko + + * grub-core/tests/video_checksum.c: Use grub_util_fd_* rather than + open/read/write. + +2013-10-14 Vladimir Serbinenko + + * grub-core/osdep/windows/emuconsole.c: New file. + +2013-10-14 Andrey Borzenkov + + * conf/Makefile.extra-dist: Add osdep/*/init.c + +2013-10-14 Vladimir Serbinenko + + * Makefile.am: Use TARGET_OBJCOPY when doing objcopy for target. + +2013-10-14 Vladimir Serbinenko + + * util/grub-probe.c (probe): Separate different drives in hint-str + by spaces and not newlines. + * util/grub-mkconfig_lib.in: Handle multidevice filesystem. + +2013-10-14 Andrey Borzenkov + + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): + Handle CD-ROMs. + +2013-10-14 Vladimir Serbinenko + + Pass-through unknown E820 types. It required reorganisation of mmap + module. + +2013-10-14 Andrey Borzenkov + + * Makefile.util.def: Add osdep/init.c to grub-mount files. + +2013-10-14 Vladimir Serbinenko + + Make grub_util_fd_seek match behaviour of other grub_util_fd_* and + fseeko. + +2013-10-14 qwertial + + * grub-core/gdb_grub.in: Fix overflow and wrong field. + +2013-10-14 Jon McCune + + * docs/grub.texi: Document new signatures possibility. + +2013-10-14 Vladimir Serbinenko + + Define GRUB_UTIL_FD_O_* and always use them with grub_util_fd_open. + +2013-10-14 Vladimir Serbinenko + + * include/grub/osdep/hostfile_windows.h (grub_util_utf8_to_tchar): Add + missing prototype. + (grub_util_tchar_to_utf8): Likewise. + +2013-10-14 Vladimir Serbinenko + + * grub-core/Makefile.core.def: Add osdep/init.c on emu. + * grub-core/kern/emu/main.c: Add missing include. + * grub-core/osdep/basic/init.c (grub_util_host_init) [!GRUB_UTIL]: + Don't call grub_util_init_nls. + * grub-core/osdep/windows/init.c (grub_util_host_init) [!GRUB_UTIL]: + Likewise. + +2013-10-13 Vladimir Serbinenko + + * util/misc.c (grub_util_get_image_size): Use FILE functions rather than + stat. + +2013-10-13 Vladimir Serbinenko + + * util/grub-editenv.c: Remove leftover set_program_name and init_nls. + +2013-10-13 Vladimir Serbinenko + + * include/grub/misc.h: Use gnu_printf only on gcc 4.4 or later. + +2013-10-13 Vladimir Serbinenko + + Add a wrapper for fopen. On unix-like systems just pass-through. On + windows use unicode version. + +2013-10-13 Vladimir Serbinenko + + Move set_program_name and init_nls to host_init. On windows + fix in this fuction console and argument charset as well. + +2013-10-12 Andrey Borzenkov + + Fix inconsistent use of GRUB_CRYPTODISK_ENABLE and + GRUB_ENABLE_CRYPTODISK. + + * util/grub-install.in: Rename all GRUB_CRYPTODISK_ENABLE to + GRUB_ENABLE_CRYPTODISK. + * util/grub-mkconfig_lib.in: Likewise. + +2013-10-12 Christian Cier-Zniewski + + * docs/grub.texi (Vendor power-on keys): Add Dell Latitude E4300. + +2013-10-12 Melki Christian + + * grub-core/term/at_keyboard.c [DEBUG_AT_KEYBOARD]: Fix compilation + error when enabling debug. + +2013-10-12 Ilya Bakulin + + * configure.ac: Use -melf_*_obsd on openbsd. + +2013-10-12 Vladimir Serbinenko + + * grub-core/kern/arm/dl_helper.c: Use more proper %p for pointer. + +2013-10-12 Vladimir Serbinenko + + * include/grub/misc.h: Use gnu_printf rather than printf as format + template since our functions are independent of libc. + +2013-10-11 Vladimir Serbinenko + + * util/grub-setup.c (setup): Move copying of partition table as + futher up as possible to avoid possible overwrite by floppy routines. + +2013-10-11 Vladimir Serbinenko + + * grub-core/fs/fat.c: Fix handling of exfat contiguous files. + +2013-10-10 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: New option `scrollbar_thumb_overlay`. + * docs/grub.texi: Likewise. + +2013-10-10 Vladimir Serbinenko + + * util/getroot.c (make_device_name): Remove dos_part and bsd_part as + it's mostly unused. Move vestiges to the callers. + +2013-10-10 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c: Remove temporary buffers for hex + version of salt and hash. Use grub_snprintf rather than snprintf. + +2013-10-10 Vladimir Serbinenko + + * docs/grub.texi: Fix problem with braces. + +2013-10-10 Vladimir Serbinenko + + * conf/Makefile.extra-dist: Fix extra-dist list. + * grub-core/Makefile.core.def: Likewise. + +2013-10-10 Vladimir Serbinenko + + * docs/grub.texi: Document disk names used on Windows and AROS. + +2013-10-10 Vladimir Serbinenko + + * grub-core/osdep/aros/getroot.c: Change to //: prefix as discussed + with AROS devs. + * grub-core/osdep/aros/hostdisk.c: Likewise. + +2013-10-10 Vladimir Serbinenko + + Avoid including hostfile.h when not necessarry as it pulls + in OS-specific headers which may redefine generic names + like "far". + +2013-10-09 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: New options for scrollbar padding: + scrollbar_left_pad, scrollbar_right_pad, scrollbar_top_pad, + scrollbar_bottom_pad + * docs/grub.texi: Likewise. + +2013-10-09 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c (list_destroy): Fixed memory leak. + +2013-10-09 Vladimir Serbinenko + + Move OS-dependent file definitions to include/grub/osdep/hostfile*.h. + +2013-10-09 Vladimir Serbinenko + + * include/grub/emu/hostdisk.h (grub_hostdisk_linux_find_partition): + Removed. + * grub-core/osdep/linux/hostdisk.c (grub_hostdisk_linux_find_partition): + Made static. + +2013-10-09 Vladimir Serbinenko + + * include/grub/emu/getroot.h (grub_util_find_hurd_root_device): Remove + leftover. + +2013-10-09 Vladimir Serbinenko + + Move OS-specific driver configuration to grub_util_fd_open. This + moves OS-dependent parts from kern/emu/hostdisk.c to + grub-core/osdep/*/hostdisk.c. + +2013-10-09 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Use size_t instead of + grub_size_t. + * util/grub-mkimagexx.c (locate_sections): Likewise. + (load_image): Likewise. + +2013-10-09 Vladimir Serbinenko + + * util/misc.c (grub_util_write_image_at): Don't use PRIxGRUB_SIZE for + size_t. + (grub_util_write_image): Likewise. + +2013-10-08 Vladimir Serbinenko + + * grub-core/osdep/basic/random.c: New file. Abort on an attempt to + get random when no RNG is available. + * grub-core/osdep/random.c: Use basic/random.c on OS out of whitelist. + +2013-10-08 Vladimir Serbinenko + + * include/grub/util/lvm.h: Removed. + +2013-10-08 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c (fsync) [__MINGW32__]: Move to ... + * grub-core/osdep/windows/hostdisk.c (fsync) [__MINGW32__]: ... here. + +2013-10-08 Vladimir Serbinenko + + * grub-core/osdep/windows/sleep.c: Add missing config.h. + +2013-10-08 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c (grub_get_rtc): Remove (it's a leftover). + +2013-10-08 Vladimir Serbinenko + + * grub-core/net/drivers/emu/emunet.c: Move to .. + * grub-core/osdep/linux/emunet.c: ..here. + +2013-10-08 Vladimir Serbinenko + + * util/ieee1275/ofpath.c: Move to ... + * grub-core/osdep/linux/ofpath.c: ..here, split stub into ... + * grub-core/osdep/basic/ofpath.c: ..here. + +2013-10-08 Vladimir Serbinenko + + Move password-querying (util-version) routines to grub-core/osdep. + +2013-10-08 Vladimir Serbinenko + + Move sleep routines to grub-core/osdep. + +2013-10-08 Vladimir Serbinenko + + Move OS-dependent files to grub-core/osdep and document it. + +2013-10-08 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c (canonicalize_file_name): Move to ... + * grub-core/kern/emu/hostdisk_*.c (canonicalize_file_name): ... here. + +2013-10-08 Vladimir Serbinenko + + * grub-core/kern/arm/misc.S: Remove leftover ARM and THUMB. + +2013-10-08 Vladimir Serbinenko + + * util/misc.c: Remove leftover inclusion of malloc.h. + +2013-10-08 Vladimir Serbinenko + + * include/grub/setjmp.h: Remove leftover GRUBOF. + +2013-10-08 Vladimir Serbinenko + + * util/raid.c: Fold into ... + * util/getroot_linux.c: ... here. Make all functions static. + +2013-10-08 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs_lz4.c: Switch from ad-hoc endiannes and width + macros to GRUB ones. + +2013-10-08 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c (draw_scrollbar): Fixed rare + occasional bug. If there are too many boot entries or too low + scrollbar height then we need to use another formula to calculate + the position and size of the scrollbar thumb. + +2013-10-08 Vladimir Serbinenko + + * util/random_unix.c: Add NetBSD, Solaris and Mac OS X to verified list. + +2013-10-08 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: New option `scrollbar-slice`. + * docs/grub.texi: Likewise. + +2013-10-08 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: Draw the scrollbar in a separate + viewport. + +2013-10-08 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c (list_get_minimal_size): Corrected + minimal width calculations. + +2013-10-07 Vladimir Serbinenko + + * docs/grub.texi: Update note on colors on emu console. + +2013-10-07 Vladimir Serbinenko + + * grub-core/fs/ufs.c (grub_ufs_get_file_block): Give GRUB_ERR_BAD_FS + for quadruple indirect rather than GRUB_ERR_NOT_IMPLEMENTED_YET as + it's FS and not GRUB limitation. + +2013-10-07 Vladimir Serbinenko + + * grub-core/kern/arm/efi/startup.S: Remove thumb leftover. + +2013-10-07 Vladimir Serbinenko + + * grub-core/kern/arm/efi/init.c: Rewrite timer fucntion. + +2013-10-04 Samuel Thibault + + * util/grub.d/10_hurd.in: Use `version_find_latest` to sort gnumach + kernels by version order. + +2013-10-04 Vladimir Serbinenko + + * util/random_unix.c: Add kFreeBSD to the list of secure RNG. + +2013-10-04 Vladimir Serbinenko + + Add AROS hostdisk and getroot routines. + +2013-10-04 Vladimir Serbinenko + + Make cryptodisk and diskfilter probe data retrievable programmatically + and not just printable. + +2013-10-04 Vladimir Serbinenko + + Split random retrieving code into separate files. + +2013-10-03 Vladimir Serbinenko + + * grub-core/kern/arm/dl.c (do_relocations): Accept and ignore + R_ARM_V4BX. + +2013-10-03 Vladimir Serbinenko + + * grub-core/tests/video_checksum.c: Increase robustness to out of memory + condition. + * grub-core/tests/fake_input.c: Likewise. + * grub-core/tests/cmdline_cat_test.c: Likewise. + +2013-10-03 Vladimir Serbinenko + + * grub-core/video/capture.c: Do not do finalization when .fini + is called as there is explicit capture_end. + +2013-10-03 Vladimir Serbinenko + + * grub-core/term/gfxterm.c: Add flag "functional" to skip input when + changing windows to avoid crash. + +2013-10-03 Vladimir Serbinenko + + * grub-core/kern/arm/cache.c: Add v5 write-through cache support. + +2013-10-03 Vladimir Serbinenko + + * po/exclude.pot: Add several strings to exclude. + +2013-10-03 Vladimir Serbinenko + + * tests/gettext_strings_test.in: Add getroot_*.c to exclude list. + +2013-10-03 Vladimir Serbinenko + + * autogen.sh: Add ./util/grub-gen-widthspec.c and + ./util/grub-gen-asciih.c to exclude list. + +2013-10-03 Vladimir Serbinenko + + * grub-core/gfxmenu/theme_loader.c (theme_set_string): Fix memory leak + and don't mark error strings for translation. + +2013-10-03 Vladimir Serbinenko + + * grub-core/disk/uboot/ubootdisk.c (uboot_disk_open): Use grub_error + properly in case of missing block size. + +2013-10-03 Vladimir Serbinenko + + * grub-core/lib/arm/setjmp.S: Add missing license section. + +2013-10-03 Vladimir Serbinenko + + * po/swiss.sed: Add replacement for key names and for term computer. + +2013-10-02 Vladimir Testov + + * grub-core/gfxmenu/theme_loader.c: New global options for the + theme background image handling. desktop-image-scale-method, + desktop-image-h-align, desktop-image-v-align. + * grub-core/gfxmenu/view.c: Likewise. + * include/gfxmenu_view.h: Likewise. + * include/bitmap_scale.h: Proportional scale functions introduced. + * grub-core/video/bitmap_scale.c: Likewise. Verification checks are + put in a separate functions. GRUB_ERR_BUG is set for grub_error in + cases of unexpected input variables for scale functions. + * docs/grub.texi: Updated documentation for new options. + +2013-10-02 Vladimir Serbinenko + + * grub-core/video/readers/png.c: Support narrow (4-/2-/1-bpp) PNG. + +2013-10-01 Vladimir Testov + + * grub-core/tests/checksums.h: Corrected due to changes in + bilinear interpolation function. + +2013-10-01 Vladimir Testov + + * grub-core/video/bitmap_scale.c (scale_bilinear): Increased precision + to eliminate artefacts in bilinear interpolation. + +2013-09-28 Vladimir Serbinenko + + * grub-core/video/readers/tga.c: Support paletted tga. + +2013-09-28 Vladimir Serbinenko + + * grub-core/video/readers/jpeg.c (grub_jpeg_decode_data): Remove + incorrect cbcr setting when in color mode. + +2013-09-28 Vladimir Serbinenko + + * grub-core/video/readers/png.c: Support paletted images and clean up + greyscale support. + +2013-09-28 Vladimir Serbinenko + + * grub-core/term/terminfo.c (grub_terminfo_readkey): Fix + usage of wrong table which resulted in mishandling of 4-byte + sequences. + +2013-09-28 Vladimir Serbinenko + + * grub-core/term/terminfo.c: Add Home and End key sequences. + +2013-09-27 Vladimir Serbinenko + + * grub-core/video/readers/png.c (grub_png_decode_image_header): + Fix formula for computing total number of bytes. + +2013-09-27 Vladimir Serbinenko + + * grub-core/video/readers/tga.c: Reorganize to separate RLE and + image processing, fix big-endian and support grayscale. + +2013-09-27 Vladimir Serbinenko + + * grub-core/video/fb/video_fb.c (grub_video_fb_create_render_target): + Correctly will with maximum transparency when using index color. + +2013-09-27 Vladimir Serbinenko + + * grub-core/video/readers/png.c: Support grayscale + +2013-09-27 Vladimir Serbinenko + + * grub-core/video/readers/jpeg.c: Support grayscale. + +2013-09-26 Jon McCune + + * grub-core/commands/loadenv.c: Support skipping signature check + and variable names filtering. + +2013-09-24 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk_unix.c: Declare AROS as non-unix. + * grub-core/kern/emu/hostfs.c: Likewise. + * util/getroot_unix.c: Likewise. + +2013-09-24 Vladimir Serbinenko + + * include/grub/emu/hostdisk.h (GRUB_FD_STAT_IS_FUNTIONAL): New define. + Migrate all explicit defines to this new one. + +2013-09-24 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Use + grub_util_fd_strerror when using grub_util_fd_*. + (grub_util_fd_open_device): Likewise. + (grub_util_biosdisk_read): Likewise. + (grub_util_biosdisk_write): Likewise. + * grub-core/kern/emu/hostdisk_unix.c (grub_util_fd_open): New function. + (grub_util_fd_strerror): Likewise. + (grub_util_fd_sync): Likewise. + (grub_util_fd_close): Likewise. + * grub-core/kern/emu/hostdisk_windows.c (grub_util_fd_sync): Likewise. + (grub_util_fd_close): Likewise. + (grub_util_fd_strerror): Likewise. + * include/grub/emu/hostdisk.h (grub_util_fd_close): Make into real + function proto rather than macro. + (grub_util_fd_sync): Likewise. + (grub_util_fd_open): Likewise. + (grub_util_fd_strerror): New proto. + +2013-09-24 Vladimir Serbinenko + + * util/getroot.c (grub_util_biosdisk_is_present): Don't do stat on + platforms on which it doesn't work. + +2013-09-24 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Move struct + stat immediately to where it's used. + +2013-09-24 Vladimir Serbinenko + + * util/getroot.c (grub_util_check_block_device): Move to ... + * util/getroot_unix.c (grub_util_check_block_device): ... here. + * util/getroot.c (grub_util_check_char_device): Move to ... + * util/getroot_unix.c (grub_util_check_char_device): ... here. + +2013-09-24 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_close): Fix + disk closing logic. + +2013-09-24 Andrey Borzenkov + + * docs/grub.texi (Simple configuration): Document GRUB_ENABLE_CRYPTODISK. + +2013-09-24 Andrey Borzenkov + + * docs/grub.texi (File name syntax): Document ZFS filenames + (/volume@snapshot/...). + +2013-09-23 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk_windows.c (grub_util_get_windows_path): + Always return full path. Fixes a problem with mkrelpath. + +2013-09-23 Paulo Flabiano Smorigo + + * util/grub-install.in: Add GPT PReP support. + * util/grub-probe.c (probe): Support GPT partition type. + (main): Support -t gpt_parttype. + +2013-09-23 Aleš Nesrsta + + * grub-core/bus/usb/ehci.c: SMI disabled in all cases + +2013-09-23 Massimo Maggi + + * grub-core/fs/zfs/zfs.c (check_pool_label): Check nvlist. + +2013-09-23 Tim Hardeck + + * util/grub.d/10_hurd.in: Filter out character for the class. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + +2013-09-23 Melki Christian + + * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Fix the type of + "changed". + +2013-09-23 Josh Triplett + + * grub-core/boot/i386/pc/lnxboot.S: Re-add support for recording the + boot partition. + +2013-09-23 Vladimir Serbinenko + + * Makefile.util.def (libgrubmods.a): Remove CFLAGS_POSIX as this lib + doesn't use posix_wrap. Keep literal -fno-builtin however. + +2013-09-23 Vladimir Serbinenko + + * conf/Makefile.common (CPPFLAGS_LIBFDT): Remove leftover. + +2013-09-23 Vladimir Serbinenko +2013-09-23 neil + + * configure.ac: Do not enable -Wmissing-noreturn as its + usefulness is limited and creates problems on some OS notably with + code generated by bison. + +2013-09-23 Vladimir Serbinenko +2013-09-23 neil + + * configure.ac: Do not explicitly enable -Waddress as it's not + supported by all gcc and when it is, it's already enabled by -Wall. + +2013-09-23 Vladimir Serbinenko + + * grub-core/video/efi_gop.c (grub_video_gop_setup): Fix a typo which + desactivated use of EDID at all. + +2013-09-23 Vladimir Serbinenko +2013-09-23 neil + + * grub-core/loader/multiboot.c (grub_multiboot_set_console): Always use + video if no text is available. + +2013-09-23 Vladimir Serbinenko +2013-09-23 neil + + * configure.ac: Substitute TARGET_RANLIB. + +2013-09-23 Vladimir Serbinenko +2013-09-23 neil + + * grub-core/genmod.sh.in: Remove ./ from TARGET_OBJ2ELF. Add quotes. + + Based on patches from AROS. + +2013-09-23 Vladimir Serbinenko +2013-09-23 neil + + * grub-core/Makefile.am: Override STRIP and RANLIB. + * configure.ac: compute TARGET_RANLIB. + * INSTALL: Document TARGET_RANLIB + + Based on patches from AROS. + +2013-09-23 Vladimir Serbinenko + + * util/getroot.c (grub_util_biosdisk_get_grub_dev): Do not assume + that floppies are unpartitioned. + +2013-09-23 Vladimir Serbinenko + + * util/getroot_unix.c [__MINGW32__ || __CYGWIN__]: + Define dummy grub_util_pull_lvm_by_command to decrease number of #if's. + +2013-09-23 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/sys/types.h: Use OpenBSD approach: it's + less nice but more portable. + * grub-core/lib/posix_wrap/wchar.h: Likewise. + +2013-09-23 Vladimir Serbinenko + + * include/grub/cryptodisk.h (grub_cryptodisk): Use grub_util_fd_t + for cheat_fd. + * grub-core/disk/cryptodisk.c (grub_cryptodisk_open): Use grub_util_* + functions. + (grub_cryptodisk_cheat_insert): Likewise. + (grub_cryptodisk_close): Likewise. + +2013-09-23 Vladimir Serbinenko + + * include/grub/emu/misc.h: Remove leftover cygwin definitions. + Use windows path for DEFAULT_DIRECTORY. + +2013-09-23 Vladimir Serbinenko + + * include/grub/i386/setjmp.h: Remove useless #if MINGW where original + difference was likely just gcc version, not anything mingw-related. + +2013-09-23 Vladimir Serbinenko + + Use Winapi on both cygwin and mingw32 to share more code between both. + +2013-09-22 Andrey Borzenkov + + * util/grub-install.in: Add --grub-editenv option. + * util/grub-install_header (grub_compress_file): Explicitly check for + plain file to avoid cp error. + +2013-09-22 Andrey Borzenkov + + * docs/grub.texi (Device syntax): Document new LVM UUID based device + names; fix LVM driver name (lvm, not lv). + * util/grub-probe.c (probe_abstraction): Support lvmid/xxx device + names. + +2013-09-22 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c: Disentagle into a series of OS-specific + files rather than one file with loads of #if's. + * util/getroot.c: Likewise. + +2013-09-22 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/sys/types.h: Use stddef on *BSD. + +2013-09-22 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (grub_get_random): Add windows and + GNU/Hurd to the list of checked PRNG. + +2013-09-22 Vladimir Serbinenko + + * configure.ac: On FreeBSD use -melf_*_fbsd format. + +2013-09-21 Ales Nesrsta + + * grub-core/bus/usb/ehci.c: Corrected EHCI QH handling (async./sync.) + +2013-09-20 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c: Handle non-md UUIDs. + * grub-core/disk/lvm.c: Add LVM UUIDs. + * util/getroot.c: Use LVM UUIDs whenever possible. + +2013-09-19 Andrey Borzenkov + + * docs/grub.texi (Networking commands): Add documentation for + network related commands. + +2013-09-19 Vladimir Serbinenko + + * util/getroot.c (grub_util_open_dm): Check major rather than the name + to determine if device is handled by devmapper. + (convert_system_partition_to_system_disk): Likewise. + (get_dm_uuid): Don't check explicitly if device is mapped, it's + already done in grub_util_open_dm. + +2013-09-19 Leif Lindholm + + * kern/arm/cache.S: Correct access to ilinesz/dlinesz variables. + Clean up stack manipulation (sync_caches_armv*) + +2013-09-19 Vladimir Serbinenko + + * util/lvm.c: Remove since unused. Remove remaining references. + +2013-09-19 Vladimir Serbinenko + + Handle the case of partitioned LVM properly. + + * grub-core/kern/emu/hostdisk.c (grub_util_get_dm_node_linear_info): + Stop on meeting LVM, mpath or DMRAID. + (grub_hostdisk_os_dev_to_grub_drive): Canonicalize os device. + (read_device_map): Likewise. + * util/getroot.c (convert_system_partition_to_system_disk): Assume that + device is full disk rather than erroring out on LVM and similar cases. + +2013-09-18 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in: Keep supplied pkgdatadir if any. + +2013-09-18 Vladimir Serbinenko + + * grub-core/kern/mm.c (grub_mm_init_region): Skip regions less than + 4K before the end. + Reported by: Leif Lindholm + +2013-09-18 Pawel Wojtalczyk +2013-09-18 Vladimir Serbinenko + + * grub-core/term/efi/console.c (grub_console_getkey): Accept VT100-style + codes. + +2013-09-18 Colin Watson + + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name_iter): + Remove no-longer-true __attribute__ ((unused)) on disk parameter. + +2013-09-18 Douglas Ray + + * util/grub-mkpasswd-pbkdf2.c (grub_get_random): Declare OpenBSD PRNG + as secure. + +2013-09-18 Aleš Nesrsta + + * docs/grub.texi: Fix broken link. + +2013-09-18 Melki Christian + + * grub-core/bus/usb/usb.c (grub_usb_device_initialize): Add condition + to break endless loop. + +2013-08-23 Vladimir Serbinenko + + * util/grub-fstest.c: Fix several printf formats. + * util/grub-mkimage.c: Likewise. + * util/grub-mkimagexx.c: Likewise. + * util/grub-script-check.c: Likewise. + +2013-08-23 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_dec_lzma2.c: Make -Wattributes not cause + error. + +2013-08-23 Vladimir Serbinenko + + * config.h.in [GRUB_BUILD]: Explicitly undefine ENABLE_NLS. + +2013-08-23 Vladimir Serbinenko + + * util/getroot.c (grub_find_device): Use cygwin_conv_path ratherthan + removed in current versions cygwin_conv_*. + +2013-08-23 Vladimir Serbinenko + + * configure.ac: Disable efiemu runtime on cygwin. + +2013-08-23 Vladimir Serbinenko + + * conf/Makefile.extra-dist: Add missing util/grub-gen-asciih.c, + util/grub-gen-widthspec.c and util/grub-pe2elf.c. + +2013-08-22 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (grub_password_get): Remove extraneous + error message. + +2013-08-22 Vladimir Serbinenko + + * grub-core/lib/crypto.c (grub_password_get) [GRUB_UTIL]: Add + windows variant. + * util/grub-mkpasswd-pbkdf2.c: Add windows flavour for retrieving random + data. + +2013-08-22 Vladimir Serbinenko + + * configure.ac: Add -Wl,-melf_i386 and -Wl,-melf_x86_64 systematically + when on x86 and not cygwin. + * conf/Makefile.common: Remove unsystematic -Wl,-melf_i386 and + -Wl,-melf_x86_64. + +2013-08-22 Vladimir Serbinenko + + * configure.ac: Set CPP to build one when checkoing for freetype for + build. + +2013-08-22 Vladimir Serbinenko + + * util/grub-mkfont.c [!GRUB_BUILD]: Define my_argp_state. + [!GRUB_BUILD]: Remove has_argument. + +2013-08-22 Vladimir Serbinenko + + * util/ieee1275/ofpath.c (grub_util_devname_to_ofpath) [_WIN32]: + Replace with a dummy. + +2013-08-22 Vladimir Serbinenko + + * configure.ac: Don't change host_os from mingw to cygwin. + +2013-08-22 Vladimir Serbinenko + + * configure.ac: Change target_os from windows to cygwin. + +2013-08-22 Vladimir Serbinenko + + Handle grub-pe2elf and grub-mkfont for cases when build != host. + + * Makefile.am (build-grub-mkfont): Don't include gnulib. + (build-grub-gen-asciih): Likewise. + (build-grub-gen-widthspec): Likewise. + * Makefile.util.def (grub-pe2elf): Remove. + * config.h.in [GRUB_BUILD]: Use build rather than host constants. + * configure.ac: Separate tests for build. + Move ./build-grub-pe2elf to grub-core. + Fix typo. + * grub-core/Makefile.am (build-grub-pe2elf): New target. + * grub-core/kern/emu/misc.c (xasprintf): Don't compile if GRUB_BUILD is + defined. + * include/grub/types.h [GRUB_BUILD]: Use build rather than host + constants. + * util/grub-mkfont.c [GRUB_BUILD]: Simplify not to rely on argp. + * util/grub-pe2elf.c: Simplify not to rely on getopt. + * util/misc.c (program_name) [GRUB_BUILD]: Define to static string. + +2013-08-22 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_size): Adapt for + mingw32 as well based on grub_util_get_disk_size. + * util/misc.c (grub_util_get_disk_size): Removed. all users switched to + grub_util_get_fd_size. + (sync): Removed. + (fsync): Moved to ... + * grub-core/kern/emu/misc.c (fsync): ... here. + +2013-08-22 Vladimir Serbinenko + + * include/grub/mm.h (grub_extend_alloc): Remove. + * grub-core/loader/i386/pc/plan9.c: Use own version of + grub_extend_alloc with appropriate types. + +2013-08-22 Vladimir Serbinenko + + * conf/Makefile.common (CFLAGS_GCRY): Add -Wno-redundant-decls. + +2013-08-22 Vladimir Serbinenko + + * util/getroot.c: Include sys/wait.h only when we need waitpid. + +2013-08-22 Vladimir Serbinenko + + Fix dependencies on cygwin. + + * gentpl.py: Support variable dependencies. Add $TARGET_OBJ2ELF to + dependencies when used and defined. + * grub-core/Makefile.core.def (regexp): Add dependency on libgnulib.a. + +2013-08-22 Vladimir Serbinenko + + * include/grub/zfs/spa.h (zio_cksum): Add explicit members for mac. + * grub-core/fs/zfs/zfs.c (zio_read): Don't use casts to retrieve mac. + +2013-08-22 Vladimir Serbinenko + + * grub-core/kern/emu/mm.c (grub_memalign): Don't define if there is no + implementation available to cause compile-time rather than runtime + error. + +2013-08-22 Vladimir Serbinenko + + * util/grub-fstest.c: Don't check for symlinks on windows. + +2013-08-22 Vladimir Serbinenko + + * INSTALL: Mention unavailability of man pages when cross-compiling. + +2013-08-22 Vladimir Serbinenko + + * include/grub/crypto.h: Don't declare gcry_log_bug, gcry_log_printf + and gcry_log_bug. + * grub-core/lib/libgcrypt_wrap/mem.c: Include g10lib.h + +2013-08-21 Vladimir Serbinenko + + * INSTALL: Document cross-compilation. + * acinclude.m4: Determine whether nm support -P and --defined-only. + * configure.ac: Add TARGET_ to all variables pertaining to target + that don't have it yet. + * gentpl.py: Likewise. + * grub-core/Makefile.am: Likewise. + * grub-core/genmod.sh.in: Likewise. + * grub-core/gensyminfo.sh.in: Handle OpenBSD and other non-GNU nm + as well. + +2013-08-21 Ilya Bakulin + + * configure.ac: Remove -Wempty-body. It's not essential and needs + recent gcc. + +2013-08-21 Ilya Bakulin + + * grub-core/kern/emu/hostdisk.c: Add conditionals for OpenBSD. + * util/getroot.c: Likewise. + +2013-08-21 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Add needed explicit cast. + * grub-core/lib/backtrace.c: Likewise. + * grub-core/net/ip.c: Likewise. + * grub-core/net/tcp.c: Likewise. + * grub-core/net/udp.c: Likewise. + +2013-08-21 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/wchar.h: Fix typo. + +2013-08-21 Vladimir Serbinenko + + * util/import_gcry.py: Add final newline in visibility.h. + +2013-08-21 Vladimir Serbinenko + + * conf/Makefile.common: Fix typo. + +2013-08-21 Vladimir Serbinenko + + * Makefile.util.def (grub-mkfont): Add missing libgnu.a. + +2013-08-21 Vladimir Serbinenko + + * Makefile.am (widthspec.h): Fix typo. + * util/grub-gen-widthspec.c: Likewise. + +2013-08-21 Vladimir Serbinenko + + Move ascii.h and widthspec.h generation to a separate build-time-only + tool. + +2013-08-16 Grégoire Sutre + + * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): + Always fill bootdisk info and improve check for NetBSD disklabel. + +2013-08-16 Vladimir Serbinenko + + * conf/Makefile.extra-dist: Add util/bin2h.c. + Reported by: floppym. + +2013-08-16 Vladimir Serbinenko + + * configure.ac: Make unifont mandatory for powerpc-ieee1275. + +2013-08-16 Vladimir Serbinenko + + * configure.ac: Disable unifont and starfield if no freetype was found. + +2013-08-16 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/wchar.h: Fix wchar_t and mbstate_t conflict + on NetBSD and OpenBSD. + +2013-08-15 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: Baseline misplacement fixed. + +2013-08-15 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: The number of color mappings is + reduced. Inheritant options are processed during the theme loading. + +2013-08-15 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: Minimal width fixed. + +2013-08-14 Avik Sil + + * grub-core/net/tftp.c: Send tftp ack packet before closing the socket. + +2013-08-14 Avik Sil + + * grub-core/net/drivers/ieee1275/ofnet.c: Get proper mac address when + using qemu. + +2013-08-14 Paulo Flabiano Smorigo + + * .bzrignore: Add bootinfo.txt, grub.chrp, gnulib/float.h, and + remove-potcdate.sed. + +2013-08-14 Andrey Borzenkov + + * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_iterate): Remove + unused attribute from pull argument. + +2013-08-14 Andrey Borzenkov + + * util/getroot.c (grub_util_is_imsm): Fix descriptor and + memory leak. + +2013-08-14 Andrey Borzenkov + + * util/getroot.c (pull_lvm_by_command): add --separator option + to vgs call to disable padding of output to 10 characters. + +2013-08-14 Vladimir Serbinenko + + * grub-core/kern/emu/misc.c (grub_device_mapper_supported): Move from + here ... + * grub-core/kern/emu/hostdisk.c (grub_device_mapper_supported): ... to + here. + +2013-08-14 Vladimir Serbinenko + + * include/grub/i386/pc/biosdisk.h (grub_biosdisk_drp): Fix device_path + length. + +2013-08-14 Vladimir Serbinenko + + Fix handling of build-time grub-bin2h and grub-mkfont when doing + full Canadian cross. Tested with build=x86_64, host=arm, + target=ppc-ieee1275. + +2013-08-14 Vladimir Serbinenko + + * configure.ac: Error if no $BUILD_CC could be found. + Reported by: DevHC. + +2013-08-14 Vladimir Serbinenko + + * grub-core/kern/i386/coreboot/init.c: Fix compilation on + i386-multiboot. + +2013-08-14 Vladimir Serbinenko + + * grub-core/kern/vga_init.c: Fix compilation on qemu-mips. + * grub-core/kern/mips/qemu_mips/init.c: Likewise. + +2013-08-13 Colin Watson + + * util/getroot.c (grub_util_biosdisk_get_grub_dev): Zero out + grub_errno in the case where we handle GRUB_ERR_UNKNOWN_DEVICE by + falling back to the partition device, otherwise a later call to this + function may fail spuriously. + Reported by Axel Beckert. Fixes Debian bug #708614. + +2013-08-12 Grégoire Sutre + + * autogen.sh: Replace find -not by the POSIX-compliant find !. + +2013-08-12 Grégoire Sutre + + Prevent shadowing of stdlib's devname(3) on BSD. + + * grub-core/disk/cryptodisk.c (grub_cmd_cryptomount): Rename devname + and devlast to diskname and disklast, respectively. + +2013-08-11 Colin Watson + + * util/grub-mkconfig.in: Fix detection of Emacs autosave files. + +2013-08-08 Vladimir Testov + + * docs/grub.texi: Introduce terminal window position options: + terminal-left: terminal window's left position + terminal-top: terminal window's top position + terminal-width: terminal window's width + terminal-height: terminal window's height + terminal-border: terminal window's border width + * grub-core/gfxmenu/theme-loader.c: Likewise. + * include/grub/gfxmenu_view.h: Likewise. + * po/exlude.pot: Likewise. + * grub-core/gfxmenu/view.c: Likewise. + Also updated minimal window size. + Also terminal_sanity_check function has been introduced. + * grub-core/tests/checksums.h: Update (terminal window height + is adjusted now for low resolution screen) + +2013-08-02 Vladimir Serbinenko + + * grub-core/tests/checksums.h: Update (1-pixel difference in marker + position). + +2013-08-02 Vladimir Serbinenko + + * po/exclude.pot: Add few recent exceptions. + +2013-08-02 Vladimir Serbinenko + + * tests/grub_func_test.in: Add unicode.pf2. + +2013-08-02 Vladimir Serbinenko + + * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Start with + standard rather than noral color, in line with other terminals. + +2013-08-02 Vladimir Serbinenko + + * grub-core/partmap/dfly.c: Simplify dprintfs for easier gettext + analysis. + +2013-08-02 Vladimir Serbinenko + + * grub-core/loader/arm/linux.c: Change printf to dprintf. + +2013-08-02 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (check_feature): Cleanup and remove + inappropriate printf. + +2013-07-25 Andrey Borzenkov + + * .bzrignore: Remove grub-core/lib/dtc-grub, + grub-core/Makefile.libfdt.def + * conf/Makefile.extra-dist: Remove grub-core/Makefile.libfdt.def. + +2013-07-25 Vladimir Serbinenko + + * include/grub/video.h (grub_video_register): Keep double-linked as + well as single-linked invariants. + Reported by: qwertial. + +2013-07-25 Vladimir Serbinenko + + * grub-core/commands/nativedisk.c (get_uuid): Handle + GRUB_DISK_DEVICE_UBOOTDISK_ID. + +2013-07-25 Vladimir Testov + + * grub-core/gfxmenu/widget-box.c: Fixed draw function. Now it takes + maximum of NW, N, NE heights instead of N's height and maximum of + NW, W, SW widths instead of W's width. (So the box will be always + correctly drawn) + +2013-07-20 Grégoire Sutre + + * grub-core/partmap/bsdlabel.c (netopenbsdlabel_partition_map_iterate): + Fix misuse of variable count. + +2013-07-18 Leif Lindholm +2013-07-18 Francesco Lavra +2013-07-18 Vladimir Serbinenko + + New ports to arm-uboot and arm-efi. + Mostly by Leif Lindholm with some additions from + Francesco Lavra and cleanup by Vladimir Serbinenko. + +2013-07-16 Vladimir Serbinenko + + * grub-core/loader/multiboot_elfxx.c: Check eip after v2p translation + and not before. + Reported by: Leon Drugi. + +2013-07-16 Vladimir Serbinenko + + * grub-core/kern/powerpc/ieee1275/startup.S: Handle unaligned bss. + Reported by: Paulo Flabiano Smorigo. + +2013-07-14 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: USe viewport when drawing strings. + +2013-07-14 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: Fix height calculation. + +2013-07-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c: Stylistic fixes. + +2013-07-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c: Run emacs indent on file. + +2013-07-14 Andrey Borzenkov + + * grub-core/net/bootp.c: Export net_* variables. + * grub-core/net/net.c: Likewise. + +2013-07-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c: Remove brackets around return value. + +2013-07-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs_lz4.c: Add missing packed attribute. + +2013-07-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (nvlist_next_nvpair): Fix improper cast. + +2013-07-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs_lz4.c: Remove restrict keyword. + +2013-07-14 Massimo Maggi + + * grub-core/fs/zfs/zfs.c (nvlist_next_nvpair): Error is encode_size + <= 0. + +2013-07-14 Massimo Maggi + + * grub-core/fs/zfs/zfs.c: Split nvpair iterators into separate + functions. + +2013-07-14 Massimo Maggi + + * grub-core/fs/zfs/zfs_lz4.c: New file. + * grub-core/fs/zfs/zfs.c: Tie up lz4 decompression. + +2013-07-14 Massimo Maggi + + * grub-core/fs/zfs/zfs.c: Check for feature compatibility. + +2013-07-14 Massimo Maggi + + * grub-core/fs/zfs/zfs.c (uberblock_verify): Accept version 5000. + (check_pool_label): Likewise. + * include/grub/zfs/zfs.h: Rewrite SPA_VERSION_* macros. + +2013-07-14 Massimo Maggi + + * grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Fix RAIDZ reporting. + +2013-07-13 Andrey Borzenkov + + * docs/grub.texi (Commands): Document postition parameters + for menuentry command. + +2013-07-13 Andrey Borzenkov + + * util/grub-mknetdir.in: Remove stray line from help output. + +2013-07-11 Vladimir Serbinenko + + Remove early sm712 init as there is no reason for it (the "watchdog" + effect was due to wrong GPIO map). + +2013-07-11 Vladimir Serbinenko + + * grub-core/commands/pcidump.c: Remove static variables. + +2013-07-11 Vladimir Serbinenko + + * grub-core/commands/sleep.c: Refresh screen before sleeping. + +2013-07-11 Vladimir Serbinenko + + * configure.ac: Move delimiter after the infos. + +2013-07-11 Vladimir Serbinenko + + * grub-core/bus/usb/usbhub.c: Fix recheck logic. + +2013-07-11 Vladimir Serbinenko + + * util/grub-mkfont.c (write_font_ascii_bitmap): Fix handling of glyphs + not filling whole 8x16 space. + +2013-07-11 Vladimir Serbinenko + + * grub-core/normal/charset.c (bidi_line_wrap): Fix spurios warning. + +2013-07-11 Vladimir Serbinenko + + * configure.ac: Indicate which liblzma is used if any. + +2013-06-21 Paul Wise +2013-06-21 Craig Sanders + + * util/grub-reboot.in: Document submenu usage. + +2013-06-25 Colin Watson + + * .bzrignore: Update with a number of new test-related files. + +2013-06-25 Colin Watson + + * util/grub-script-check.c: Fail on scripts containing no + commands, to guard against corrupted grub-mkconfig setups that + produce no useful output. + * tests/grub_script_no_commands.in: New test. + * Makefile.util.def (grub_script_no_commands): Add. + Reported by Hans Putter. Fixes Debian bug #713886. + +2013-06-16 Andrey Borzenkov + + * grub-core/disk/diskfilter.c: Forgot to remove comment + from previous commit. + +2013-06-16 Andrey Borzenkov + + * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use + grub_term_normal_color, do not hardcode GRUB_TERM_DEFAULT_NORMAL_COLOR. + +2013-06-16 Andrey Borzenkov + + * conf/Makefile.extra-dist: Add grub-core/fs/cpio_common.c. + +2013-06-16 Andrey Borzenkov + + * grub-core/disk/diskfilter.c (scan_devices): Iteratively + rescan diskfilter devices until nothing new is found. + +2013-06-16 Vladimir Serbinenko + + Fix casts when compiling coreboot-specific code for 64-bit EFI. + +2013-06-16 Vladimir Serbinenko + + Don't try to detect cbfs on *-emu. + +2013-06-16 Vladimir Serbinenko + + * grub-core/term/gfxterm.c: USe right background color when scrolling. + +2013-06-16 Vladimir Serbinenko + + Add support for processed coreboot payload chainloading. + +2013-06-16 Vladimir Serbinenko + + Enable coreboot information commands even when not loaded as + coreboot payload (e.g. when loaded from SeaBIOS-as-payload). + +2013-06-15 Vladimir Serbinenko + + Support for cbfs. Also factor out the part which is common + for all archives to a separate module. This splits tar from cpio + as they are very different but keeps cpio, cpio_be, odc and newc + together since they're very similar. + +2013-06-15 David Michael + + * configure.ac (FREETYPE): Change AC_CHECK_PROGS to AC_CHECK_TOOLS. + (freetype_cflags,freetype_libs): Change freetype-config to $FREETYPE. + +2013-06-15 Vladimir Serbinenko + + * tests/grub_script_eval.in: Really add the eval test. + +2013-06-14 Vladimir Serbinenko + + Move flavour-specific parts out of common cpio.c file and + rename remaining to cpio_common.c + +2013-06-07 Andrey Borzenkov + + * grub-core/script/execute.c (grub_script_execute_sourcecode): Split + off new function grub_script_execute_new_scope. Change callers to use + either of them as appropriate. + * grub-core/commands/eval.c: New command eval. + * docs/grub.texi (Commands): Document it. + +2013-06-07 Andrey Borzenkov + + * grub-core/kern/corecmd.c (grub_core_cmd_set): Use grub_env_get + to fetch values when listing. + +2013-06-07 Andrey Borzenkov + + Fix make dist on non-pc. + +2013-06-07 Francesco Lavra + + * grub-core/kern/corecmd.c (grub_core_cmd_ls): Fix handling of paths + without a device name. + +2013-06-07 Vladimir Serbinenko + + Remove enable_executable_check as it's not needed anymore. + Reported by: dougray. + +2013-06-07 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c (insert_array): Fix order to discover + ambigouos RAID before discovering RAIDs on top of it. + Reported by: bodom. + +2013-06-07 Vladimir Serbinenko + + Fix typo (failback vs fallback). + +2013-05-31 Andrey Borzenkov + + * util/grub.d/30_os-prober.in: Add support for probing EFI + System Partition (as of os-prober 1.58). + +2013-05-31 Vladimir Serbinenko + + * configure.ac: Add yet another path to unifont. For parabola. + +2013-05-30 Josh Triplett + + * grub-core/normal/cmdline.c (grub_cmdline_get): Fix Ctrl-u + handling to copy the killed characters to the kill buffer as + UCS4 stored as grub_uint32_t rather than as 8-bit characters + stored as char. Eliminates UCS4 truncation and corruption + observed when killing characters with Ctrl-u and yanking them + back with Ctrl-y. + +2013-05-30 Vladimir Serbinenko + + Detach optional parts of gfxterm and integrate in with coreboot init. + +2013-05-30 Vladimir Serbinenko + + Move blit and fill dispatcher to appropriate files to decrease export + and relocation overhead. + +2013-05-30 Vladimir Serbinenko + + * grub-core/font/font.c, include/grub/font.h: Inline simple font + functions. + +2013-05-30 Vladimir Serbinenko + + * grub-core/Makefile.am: Fix compilation problem with some + automake versions. + +2013-05-30 Vladimir Serbinenko + + * configure.ac: Add Ubuntu path to unifont and report unifont path used. + +2013-05-30 Vladimir Serbinenko + + * Makefile.am, conf/Makefile.common: Fix compilation problem with some + automake versions. + +2013-05-30 Vladimir Serbinenko + + * grub-core/commands/acpihalt.c: Fix handling of DSDT in presence of + SSDT. + +2013-05-15 Radosław Szymczyszyn + + * grub-core/partmap/dfly.c: New partition map. + +2013-05-15 Vladimir Serbinenko + + * grub-core/kern/corecmd.c (grub_core_cmd_ls): Fix empty path + checking. + Reported by: Francesco Lavra. + +2013-05-14 Andrey Borzenkov + + * gentpl.py: Replace EXTRA_DIST with dist_noinst_DATA or + dist__DATA. EXTRA_DIST is ignored by automake inside + false conditions. + * conf/Makefile.common: define dist_grubconf_DATA + +2013-05-14 Vladimir Serbinenko + + Progressively skip menu elements on small terminals rather + than crashing. + +2013-05-14 Vladimir Serbinenko + + * grub-core/normal/cmdline.c (grub_cmdline_get): Fix off-by-one error + to avoid losing last column. + +2013-05-14 Vladimir Serbinenko + + * po/exclude.pot: Add missing string "%C". + +2013-05-14 Vladimir Serbinenko + + * tests/util/grub-shell.in: Remove the temporary directory on grub-emu + after the test. + +2013-05-11 Vladimir Serbinenko + + * util/grub-install.in: Gettextize "Not found" message. + +2013-05-11 Vladimir Serbinenko + + Fix distfiles list. + Reported by: Andrey Borzenkov + +2013-05-11 Paulo Flabiano Smorigo + + * grub-core/net/bootp.c (grub_cmd_bootp): Check if there is any card + present. + * include/grub/err.h (grub_err_t): New enum value GRUB_ERR_NET_NO_CARD. + +2013-05-11 Vladimir Serbinenko + + * grub-core/tests/setjmp_test.c: Ignore missing noreturn. + +2013-05-11 Vladimir Serbinenko + + * grub-core/fs/hfspluscomp.c (grub_hfsplus_compress_attr): Add packed + attribute since structure is not necessarily aligned. + +2013-05-11 Andrey Borzenkov + + * docs/grub.texi (Device syntax): Clarify description of network + drives. + +2013-05-10 Vladimir Serbinenko + + Redirect xasprintf to grub_xvasprintf rather than having #ifdef's + for vasprintf presence. + +2013-05-10 Vladimir Serbinenko + + * util/grub-install.in: Handle efibootmgr presence check. + Reported by: Leif Lindholm. + +2013-05-10 Vladimir Serbinenko + + * grub-core/commands/testspeed.c: Reuse formatting string to decrease + new strings to translate. + +2013-05-10 Vladimir Serbinenko + + * util/grub-mkrescue.in: Replace `STR' with `STRING' to avoid adding + yet another string (pun intended) to translate. + +2013-05-10 Vladimir Serbinenko + + * po/POTFILES-shell.in: Autogenerate it. + +2013-05-10 Vladimir Serbinenko + + * grub-core/net/net.c (grub_net_open_real): Autoload network modules. + +2013-05-10 Vladimir Serbinenko + + * grub-core/term/terminfo.c: Rename ANSI_C0 to ANSI_CSI to avoid + misnomer. + +2013-05-08 Andrey Borzenkov + + * docs/grub.texi (Network): Add description of net_default_interface, + net_default_ip and net_default_mac. Rewrite variables description + to emphasize that they are per-interface. + +2013-05-08 Vladimir Serbinenko + + New test: cmdline and cat. + +2013-05-08 Vladimir Serbinenko + + * grub-core/commands/cat.c: Show UTF-8 characters. + +2013-05-08 Vladimir Serbinenko + + * conf/Makefile.common: Poison float and double on non-emu. + +2013-05-08 Vladimir Serbinenko + + * configure.ac: Don't disable extended registers on emu. + +2013-05-07 Vladimir Serbinenko + + * configure.ac: Don't use extended registers on x86_64. + Reported by: Peter Jones. + +2013-05-07 Vladimir Serbinenko + + * grub-core/term/efi/console.c: Fix compile error. + +2013-05-07 Vladimir Serbinenko + + Compressed HFS+ support. + +2013-05-07 Vladimir Serbinenko + + * grub-core/commands/videoinfo.c: Use "paletted" rather than "packed + pixel". + +2013-05-07 Vladimir Serbinenko + + Menu color test. + +2013-05-07 Vladimir Serbinenko + + * grub-core/tests/setjmp_test.c: New test. + +2013-05-07 Vladimir Serbinenko + + New variables 'net_default_*' to determine MAC/IP of default interface. + +2013-05-07 Vladimir Serbinenko + + * tests/gettext_strings_test.in: A test to check for strings not + marked for translation. + +2013-05-07 Vladimir Serbinenko + + * autogen.sh: Exclude unused libgcrypt files from translation. + +2013-05-07 Vladimir Serbinenko + + Simplify few strings. + +2013-05-07 Vladimir Serbinenko + + Mark few forgotten strings for translation. + +2013-05-07 Vladimir Serbinenko + + * grub-core/loader/linux.c: Use grub_dprintf for debug statements + rather than printf. + +2013-05-07 Vladimir Serbinenko + + * grub-core/video/readers/jpeg.c: Use grub_dprintf for debug statements + rather than printf. + * grub-core/video/readers/tga.c: Likewise. + +2013-05-07 Vladimir Serbinenko + + * tests/priority_queue_unit_test.cc: New test. + +2013-05-07 Vladimir Serbinenko + + * grub-core/font/font.c: Use grub_dprintf for debug statements rather + than printf. + +2013-05-06 Andrey Borzenkov + + Reimplement grub-reboot to not depend on saved_entry. Use next_entry + variable for one time boot menu entry. + +2013-05-05 Bean + + * grub-core/commands/testspeed.c: New command testspeed. + +2013-05-05 Vladimir Serbinenko + + Factor-out human-size printing. + +2013-05-04 Vladimir Serbinenko + + Agglomerate more mallocs to speed-up gfxterm. + +2013-05-04 Vladimir Serbinenko + + Speed-up gfxterm by slightly agglomerating mallocs. + +2013-05-04 Vladimir Serbinenko + + More video checks. + +2013-05-04 Vladimir Serbinenko + + Speed-up gfxterm by saving intermediate results in index+alpha + format. + +2013-05-04 Vladimir Serbinenko + + * grub-core/tests/lib/functional_test.c: Don't stop on first failed + test. + +2013-05-04 Vladimir Serbinenko + + * grub-core/normal/menu_text.c (menu_clear_timeout): Clear second + line of timeout as it may contain the rest of long line. + +2013-05-04 Vladimir Serbinenko + + * grub-core/normal/main.c: Fix freed memory dereference. + +2013-05-04 Vladimir Serbinenko + + Fix several memory leaks. + +2013-05-04 Vladimir Serbinenko + + * grub-core/normal/menu.c (run_menu): Fix timeout reference point. + +2013-05-04 Vladimir Serbinenko + + * grub-core/gettext/gettext.c: Try $lang.gmo as well. + +2013-05-04 Vladimir Serbinenko + + Fix test -a and -o precedence. + Reported by: adrian15. + +2013-05-04 Vladimir Serbinenko + + * grub-core/font/font.c (grub_font_construct_glyph): Fix memory leak. + +2013-05-03 Andrey Borzenkov + + Rename grub-core/tests/checksums.c into grub-core/tests/checksums.h + and add it as source to functional_test module. + +2013-05-03 Vladimir Serbinenko + + * grub-core/tests/video_checksum.c: Don't set GENERATE_MODE. + +2013-05-03 Vladimir Serbinenko + + New series of tests for gfxterm and gfxmenu. + +2013-05-03 Vladimir Serbinenko + + * grub-core/gfxmenu/gfxmenu.c (grub_gfxmenu_try): Allow specifying + the theme path relative to $prefix/themes. + +2013-05-03 Vladimir Serbinenko + + * grub-core/video/fb/fbblit.c (grub_video_fbblit_blend_BGR888_RGBA8888): + Fix order bug. + (grub_video_fbblit_blend_RGB888_RGBA8888): Likewise. + +2013-05-03 Vladimir Serbinenko + + * include/grub/gui.h (grub_gfxmenu_timeout_unregister): Free cb + descriptor. + +2013-05-03 Vladimir Serbinenko + + * grub-core/gfxmenu/view.c (grub_gfxmenu_view_new): Clear + grub_gfxmenu_timeout_notifications. + (grub_gfxmenu_view_destroy): Likewise. + +2013-05-03 Vladimir Serbinenko + + * grub-core/normal/term.c (print_ucs4_real): Fix startwidth in dry run. + +2013-05-02 Vladimir Serbinenko + + Several fixes to ieee1275 and big-endian video. + +2013-05-02 Vladimir Serbinenko + + Add missing exports on mips. + +2013-05-02 Vladimir Serbinenko + + * grub-core/tests/videotest_checksum.c (videotest_checksum): Error out + if no unifont is found. + Restore original keyboard. + +2013-05-02 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add + GRUB_VIDEO_ADAPTER_CAPTURE: to handled drived ids. + +2013-05-02 Vladimir Serbinenko + + First automated video test (running videotest and comparing results) + +2013-05-02 Vladimir Serbinenko + + * grub-core/commands/videotest.c: Reduce flickering and draw 6 squares + instead of 2 to have full RGB/CMY test pattern. + +2013-04-30 Vladimir Serbinenko + + Add few more tests. + +2013-04-30 Vladimir Serbinenko + + * include/grub/arc/arc.h: Account for missing "other" peripheral on + ARCS. All users updated. + +2013-04-30 Vladimir Serbinenko + + * grub-core/kern/mips/loongson/init.c: Support halt for loongson 2E. + +2013-04-30 Vladimir Serbinenko + + * grub-core/partmap/amiga.c: Fix size of checksummed block. + +2013-04-29 Vladimir Serbinenko + + * configure.ac: Use -mcmodel=large on x86_64-emu as well. + Reported by: qwertial. + +2013-04-29 Vladimir Testov + + * grub-core/gfxmenu/circular_progress.c: Set start_angle in degrees + with syntax "XXX deg"/"XXX °". + +2013-04-29 Vladimir Serbinenko + + Make PCI init in i386-qemu port more robust. + +2013-04-29 Vladimir Testov + + * grub-core/gfxmenu/gui_list.c: Refresh first_shown_entry value when + cached view is reused. + * grub-core/gfxmenu/view.c: Call the refresh procedure for all + open boot menus. + +2013-04-29 Vladimir Serbinenko + + Unify more code in grub-install_header. + +2013-04-29 Vladimir Serbinenko + + Add few new tests. + +2013-04-29 Vladimir Serbinenko + + Enforce disabling of firmware disk drivers when native drivers kick in. + +2013-04-29 Vladimir Serbinenko + + * grub-core/commands/nativedisk.c: Customize the list of modules on + platform. Don't try to search for disks already using native drivers. + +2013-04-29 Vladimir Serbinenko + + * grub-core/bus/usb/uhci.c: Fix DMA handling and enable on all PCI + platforms. + +2013-04-29 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_arglist_to_argv): Fix + handling of variables containing backslash. + +2013-04-29 Vladimir Serbinenko + + * include/grub/list.h (FOR_LIST_ELEMENTS_SAFE):Fix a NULL pointer + dereference. + Reported by: qwertial. + +2013-04-29 Vladimir Serbinenko + + * grub-core/kern/mips/arc/init.c: Fix prefix detection. + +2013-04-29 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_show_help): Fix a NULL pointer + dereference. + Reported by: qwertial. + +2013-04-28 Vladimir Serbinenko + + * docs/grub.texi: Add a comment about usefullness of nativedisk. + +2013-04-28 Vladimir Serbinenko + + * grub-core/commands/nativedisk.c: Ignore unknown filesystem error. + +2013-04-28 Vladimir Serbinenko + + New command `nativedisk'. + +2013-04-28 Vladimir Serbinenko + + * grub-core/io/lzopio.c: Use GRUB_PROPERLY_ALIGNED_ARRAY. + * grub-core/loader/i386/bsd.c: Likewise. + +2013-04-28 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Fix compilation for amd64 (format warnings). + +2013-04-28 Vladimir Serbinenko + + * include/grub/efi/api.h (GRUB_EFI_DEVICE_PATH_LENGTH): Use + grub_get_unaligned16 rather than shifts. + +2013-04-28 Vladimir Serbinenko + + * grub-core/kern/file.c: Use const char * rather than casting to + non-const. + +2013-04-28 Vladimir Serbinenko + + * grub-core/commands/probe.c: Add missing grub_device_close. + +2013-04-28 Vladimir Serbinenko + + * INSTALL: Document linguas.sh. + +2013-04-28 Vladimir Serbinenko + + Remove POTFILES.in and regenerate it in autogen.sh. + +2013-04-28 Vladimir Serbinenko + + Move --directory/--override-directorry to grub-install_header and unify. + +2013-04-28 Vladimir Serbinenko + + * grub-core/term/morse.c: Macroify dih and dah. + +2013-04-27 Paulo Flabiano Smorigo + + * include/grub/macho.h: Set GRUB_MACHO_FAT_EFI_MAGIC as unsigned. + +2013-04-27 Vladimir Serbinenko + + * grub-core/term/ns8250.c: Systematically probe ports by writing + to SR before using them. + +2013-04-27 Paulo Flabiano Smorigo + + * util/ieee1275/ofpath.c (of_path_of_scsi): Fix path output for sas + disks. + (check_sas): Get sas_adress info. + +2013-04-27 Vladimir Serbinenko + + * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix handling of empty + ports. + +2013-04-27 Leon Drugi + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Fix cast in + BSS clearing. + +2013-04-27 Vladimir Serbinenko + + Core compression test. + +2013-04-27 Vladimir Serbinenko + + Implement grub_machine_get_bootlocation for ARC. + +2013-04-27 Vladimir Serbinenko + + Improve AHCI detection and command issuing. + +2013-04-26 Vladimir Serbinenko + + Fix pseries test. + +2013-04-26 Vladimir Serbinenko + + Make 'make check' work on emu. + +2013-04-26 Vladimir Serbinenko + + Replace libcurses with our own vt100 handling for the ease of testing + and decreasing prerequisites. + +2013-04-26 Vladimir Serbinenko + + * grub-core/Makefile.core.def: Fix grub-emu and grub-emu-lite sources. + +2013-04-26 Vladimir Serbinenko + + * util/getroot.c (exec_pipe): Put proper #if's so that its users don't + compile when not needed. + +2013-04-26 Vladimir Serbinenko + + * tests/pseries_test.in: New test. + +2013-04-26 Vladimir Serbinenko + + Add test to check that different boot mediums work. + +2013-04-26 Vladimir Serbinenko + + * util/grub-mkrescue.in: Rename i386-ieee1275 core image due to + ofw limited ISO support. + +2013-04-26 Vladimir Serbinenko + + * configure.ac: Fix loongson conditional. + +2013-04-25 Vladimir Serbinenko + + Enable mipsel-arc. + +2013-04-25 Vladimir Serbinenko + + Add serial on ARC platform. + +2013-04-25 Vladimir Serbinenko + + * grub-core/boot/powerpc/bootinfo.txt.in: Missing update from previous + commit. + +2013-04-25 Vladimir Serbinenko + + * tests/partmap_test.in: Add missing double semicolon. + +2013-04-25 Vladimir Serbinenko + + * util/grub-mkrescue.in: Fix loongson filename. + +2013-04-25 Vladimir Serbinenko + + * util/grub-mkrescue.in: Move all files that don't have a location + set in stone under /boot/grub. Use ISO hard links rather than copies + to save some space. + +2013-04-24 Vladimir Serbinenko + + * grub-core/term/ieee1275/console.c (grub_console_dimensions): Ignore + bogus SLOF values. + +2013-04-24 Vladimir Serbinenko + + Make check work on mips-arc. + +2013-04-24 Vladimir Serbinenko + + * util/grub-mkrescue.in: Alias sashARCS as sash. + +2013-04-24 Vladimir Serbinenko + + * grub-core/term/arc/console.c: Assume that console is 80x24 vt100 if + it's serial. + +2013-04-24 Vladimir Serbinenko + + * util/grub-install.in: Fix target fo qemu_mips. + Fix extension on EFI. + +2013-04-24 Vladimir Serbinenko + + * grub-core/normal/menu_text.c (print_entry): Put an asterisk + in front of chosen entry to mark it even if highlighting is lost. + +2013-04-24 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (grub_linux_boot): Default to + gfxpayload=keep if cbfb is active. + +2013-04-24 Vladimir Serbinenko + + * grub-core/disk/ata.c (grub_ata_real_open): Use grub_error properly. + +2013-04-24 Vladimir Serbinenko + + Add missing video ids to coreboot and ieee1275 video. + +2013-04-24 Vladimir Serbinenko + + * util/grub-mkrescue.in: Add mips-arc support. + +2013-04-24 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_resolve_symbols): Handle malloc failure. + +2013-04-24 Vladimir Serbinenko + + Move mips-arc link address. Previous link address was chosen + in belief that RAM on SGI platforms grows down while in fact it + grows up from an unusual base. + +2013-04-21 Vladimir Serbinenko + + * grub-core/disk/arc/arcdisk.c (grub_arcdisk_iterate_iter): + Fix a type which prevented CD-ROM and floppy boot. + +2013-04-21 Vladimir Serbinenko + + Support coreboot framebuffer. + + * grub-core/video/i386/coreboot/cbfb.c: New file. + +2013-04-20 Vladimir Serbinenko + + * grub-core/kern/mm.c (grub_mm_init_region): Fix condition for + detecting too small regions. + +2013-04-20 Vladimir Serbinenko + + * grub-core/Makefile.core.def (legacycfg): Enable on EFI. + +2013-04-20 Vladimir Serbinenko + + * grub-core/lib/efi/relocator.c (grub_relocator_firmware_alloc_region): + Remove dprintf. + * grub-core/lib/relocator.c (malloc_in_range): Likewise. + +2013-04-19 Vladimir Serbinenko + + * grub-core/kern/ieee1275/init.c (grub_claim_heap): Improve handling + of GRUB_IEEE1275_FLAG_FORCE_CLAIM. + * grub-core/loader/powerpc/ieee1275/linux.c + (grub_linux_claimmap_iterate): Handle GRUB_IEEE1275_FLAG_FORCE_CLAIM. + +2013-04-19 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): + Look for /boot-rom as well as /rom/boot-rom. + +2013-04-19 Vladimir Serbinenko + + * grub-core/commands/videotest.c (grub_cmd_videotest): Fix error + handling when creating text_layer failed. + * grub-core/video/video.c (grub_video_create_render_target): + Set result to 0 on error. + (grub_video_delete_render_target): Do not dereference NULL. + +2013-04-19 Vladimir Serbinenko + + * grub-core/kern/elfXX.c (grub_elfXX_load): Handle + GRUB_ELF_LOAD_FLAGS_30BITS and GRUB_ELF_LOAD_FLAGS_62BITS. + * grub-core/loader/powerpc/ieee1275/linux.c (grub_linux_load32), + (grub_linux_load64): Mask out 2 high bits. + +2013-04-19 Andrey Borzenkov + + * util/grub.d/30_os-prober.in: Add onstr to linux entries in one + more place. + +2013-04-19 Vladimir Serbinenko + + Add support for pseries and other bootinfo machines to grub-mkrescue. + + Tested by: Paulo Flabiano Smorigo. + +2013-04-17 Vladimir Serbinenko + + * util/grub-mkrescue.in: Add GPT for EFI boot. + +2013-04-17 Vladimir Serbinenko + + * grub-core/disk/efi/efidisk.c: Detect floppies by ACPI ID. + It improves performance in qemu. + +2013-04-17 Vladimir Serbinenko + + * build-aux/snippet: Add missing gnulib files. + +2013-04-16 Andrey Borzenkov + + * grub-core/disk/efi/efidisk.c: Really limit transfer chunk size. + +2013-04-16 Andrey Borzenkov + + * autogen.sh: Use "-f" in addition for "-h" when checking file presence. + +2013-04-15 Vladimir Serbinenko +2013-04-15 Peter Jones + + * grub-core/disk/efi/efidisk.c: Limit disk read or write chunk to 0x500 + sectors. + Based on patch by Peter Jones. + +2013-04-15 Vladimir Serbinenko + + Fix DMRAID partition handling. + +2013-04-15 Vladimir Serbinenko + + * tests/grub_cmd_date.in: Skip on sparc64. + +2013-04-15 Vladimir Serbinenko + + * tests/grub_script_expansion.in: Use fixed-string grep to skip over + firmware error messages. + +2013-04-15 Vladimir Serbinenko + + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_devalias_next): Make + source and destination differ. + +2013-04-15 Vladimir Serbinenko + + * grub-core/disk/ieee1275/ofdisk.c: Fix CD-ROM and boot device + detection. + +2013-04-14 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/sys/types.h: Make WORDS_BIGENDIAN definition + match config-util.h to avoid warnings and increase compatibility. + +2013-04-14 Szymon Janc +2013-04-14 Vladimir Serbinenko + + Add option to compress files on install/image creation. + +2013-04-14 Vladimir Serbinenko + + * docs/grub-dev.texi: Rearrange menu to match the section order. + Reported by: Bryan Hundven. + +2013-04-14 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c: Remove useless leftover pointer. + +2013-04-14 Vladimir Serbinenko + + Move GRUB out of system area when using xorriso 1.2.9 or later. + +2013-04-14 Vladimir Serbinenko + + * tests/grub_cmd_date.in: Add missing exit 1. + +2013-04-14 Vladimir Serbinenko + + * tests/partmap_test.in: Skip on sparc64. + +2013-04-14 Vladimir Serbinenko + + Support grub-shell on sparc64. + +2013-04-14 Vladimir Serbinenko + + Support mkrescue on sparc64. + +2013-04-14 Vladimir Serbinenko + + Allow IEEE1275 ports on path even if it wasn't detected automatically. + Needed on OpenBIOS due to incomplete device tree. + +2013-04-14 Vladimir Serbinenko + + * grub-core/disk/ieee1275/ofdisk.c: Iterate over bootpath even if it + would be otherwise excluded. + +2013-04-14 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): + Inline name defines used only once. + +2013-04-13 Vladimir Serbinenko + + Fix memory leaks in ofnet. + Reported by: Francesco Lavra. + +2013-04-12 Vladimir Serbinenko + + * docs/man/grub-glue-efi.h2m: Add missing file. + +2013-04-12 Vladimir Serbinenko + + * util/grub-mkrescue.in: Fix wrong architecture for ppc dir. + +2013-04-12 Vladimir Serbinenko + + Better support Apple Intel Macs on CD. + +2013-04-12 Vladimir Serbinenko + + Replace stpcpy with grub_stpcpy in tools. + +2013-04-12 Vladimir Serbinenko + + Handle Japanese special keys. + Reported by: Hiroyuki YAMAMORI. + Codes supplied by: Hiroyuki YAMAMORI. + +2013-04-12 Vladimir Serbinenko + + * util/grub-mkimage.c: Document memdisk implying --prefix. + +2013-04-12 Vladimir Serbinenko + + * grub-core/bus/usb/ehci.c (grub_ehci_fini_hw): Ignore errors, not + much we can do about it anyway. + +2013-04-12 Aleš Nesrsta + + Fix handling of split transfers. + +2013-04-12 Vladimir Serbinenko + + * grub-core/net/http.c: Fix bad free. + +2013-04-12 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c: Don't attempt to send more + than buffer size. + +2013-04-12 Vladimir Serbinenko + + Disable partmap check on i386-ieee1275 due to openfirmware issues. + +2013-04-12 Vladimir Serbinenko + + * tests/util/grub-shell.in: Fix it on powerpc. + +2013-04-12 Vladimir Serbinenko + + Turn off QEMU ACPI-way since new releases don't have shutdown port + anymore. + +2013-04-12 Vladimir Serbinenko + + * docs/grub.texi: Update coreboot status info. + +2013-04-12 Vladimir Serbinenko + + * tests/grub_cmd_date.in: New test for datetime. + +2013-04-12 Vladimir Serbinenko + + * tests/partmap_test.in: Fix missing qemudisk setting. + +2013-04-11 Vladimir Serbinenko + + Support i386-ieee1275 grub-mkrescue and make check on it. + +2013-04-11 Vladimir Serbinenko + + Merge powerpc grub-mkrescue flavour with common. Use xorriso HFS+ + feature for it. + +2013-04-11 Vladimir Serbinenko + + * docs/grub.texi: Fix description of GRUB_CMDLINE_XEN and + GRUB_CMDLINE_XEN_DEFAULT. + Reported by: Marc Warne (GigaTux) + +2013-04-11 Vladimir Serbinenko + + Import new gnulib. + +2013-04-11 Vladimir Serbinenko + + Use ACPI shutdown intests as traditional port was removed. + +2013-04-11 Andrey Borzenkov + + * util/grub.d/30_os-prober.in: Add onstr to entries for visual + distinction. + +2013-04-11 Vladimir Serbinenko + + Fix missing PVs if they don't contain "interesting" LV. Closes #38677. + Fix few warining messages and leaks while on it. + +2013-04-09 Andrey Borzenkov + + * autogen.sh: Use "-h", not "-f", to test for existence of symbolic + links under grub-core/lib/libgcrypt-grub/mpi. + +2013-04-08 Vladimir Serbinenko + + Fix ia64-efi image generation on big-endian machines. Deduplicate + some code while on it. + Reported by: Leif Lindholm. + +2013-04-08 Andrey Borzenkov + + * grub-core/Makefile.core.def: Add kern/elfXX.c to elf module + as extra_dist. + +2013-04-08 Andrey Borzenkov + + * grub-core/term/i386/pc/console.c: Fix cursor moving algorithm. + +2013-04-08 Bryan Hundven + + * docs/grub-dev.texi: Move @itemize after @subsection to satisfy + texinfo-5.1. + +2013-04-08 Vladimir Serbinenko + + * grub-core/normal/term.c: Few more fixes for menu entry editor + rendering. + Reported by: Andrey Borzenkov + +2013-04-07 Vladimir Serbinenko + + * grub-core/normal/term.c: Few more fixes for menu entry editor + rendering. + Reported by: Andrey Borzenkov + +2013-04-06 Andrey Borzenkov + + * conf/Makefile.extra-dist (EXTRA_DIST): Add + grub-core/lib/libgcrypt/src/gcrypt.h.in and util/import_gcrypth.sed. + +2013-04-06 Andrey Borzenkov + + * util/grub-install_header: Use @PACKAGE@.mo in message catalog name + instead of hardcoding grub.mo. + +2013-04-05 Fedora Ninjas + + * util/grub.d/30_os-prober.in: Support btrrfs linux-prober extensions. + +2013-04-05 Vladimir Serbinenko + + Use GRUB_PROPERLY_ALIGNED_ARRAY in grub-core/disk/cryptodisk.c and + grub-core/disk/geli.c. + +2013-04-05 Vladimir Serbinenko + + * util/grub-mkfont.c: Prefer enum to #define. + +2013-04-05 Vladimir Serbinenko + + * grub-core/commands/acpi.c: Use sizeof rather than hardcoding the size. + +2013-04-05 Vladimir Serbinenko + + Replace 8 with GRUB_CHAR_BIT in several places when appropriate. + +2013-04-05 Vladimir Serbinenko + + Add new defines GRUB_RSDP_SIGNATURE_SIZE and GRUB_RSDP_SIGNATURE. + +2013-04-05 Vladimir Serbinenko + + * grub-core/commands/verify.c: Use GRUB_CHAR_BIT. + +2013-04-05 Vladimir Serbinenko + + * include/grub/bsdlabel.h: Use enums. + +2013-04-05 Vladimir Serbinenko + + Move GRUB_CHAR_BIT to types.h. + +2013-04-04 Andrey Borzenkov + + * docs/grub.texi: Document more user commands. + +2013-04-04 Andrey Borzenkov + + * docs/grub.texi: Document menuentry --id option. + +2013-04-04 Francesco Lavra + + * util/grub-mkimage.c: Introduce new define EFI32_HEADER_SIZE. + +2013-04-04 Vladimir Serbinenko + + Unify file copying setup across different install scripts. Add + options for performing partial install. + +2013-04-04 Vladimir Serbinenko +2013-04-04 Peter Jones + + * grub-core/disk/efi/efidisk.c: Handle partitions on non-512B disks. + +2013-04-04 Vladimir Serbinenko + + Use TSC as a possible time source on i386-ieee1275. + +2013-04-04 Vladimir Serbinenko + + * grub-core/bus/usb/usbtrans.c (grub_usb_bulk_readwrite_packetize): + Init err. + +2013-04-04 Vladimir Serbinenko + + * util/grub-setup.c (setup): Handle some corner cases. + +2013-04-04 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/locale.h [GRUB_UTIL]: Include host locale.h. + +2013-04-03 Vladimir Serbinenko + + * grub-core/commands/verify.c: Save verified file to avoid it being + tampered with after verification was done. + +2013-04-03 Vladimir Serbinenko + + * grub-core/term/i386/pc/console.c (grub_console_getwh): Decrease + reported width by one to compensate for curesor algorithm problem. + +2013-04-03 Vladimir Serbinenko + + Fix screen corruption in menu entry editor and simplify the code + flow while on it. + +2013-04-03 Andrey Borzenkov + + * util/grub-mount.c (fuse_init): Return error if fuse_main + failed. + +2013-04-03 Francesco Lavra + + * include/grub/elf.h: Add missing ARM relocation codes and fix + existing ones. + +2013-04-03 Vladimir Testov + + * grub-core/gfxmenu/gui_progress_bar.c: Handle padding sizes. + +2013-04-03 Vladimir Testov +2013-04-03 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_circular_progress.c: Take both width and height + into account when calculating radius. + +2013-04-03 Vladimir Testov + + * grub-core/gfxmenu/view.c: Fix off-by-one error. + +2013-04-03 Vladimir Testov + + * grub-core/gfxmenu/gui_circular_progress.c: Fix off-by-one error. + +2013-04-01 Radosław Szymczyszyn + + * grub-core/partmap/apple.c (apple_partition_map_iterate): Add + missing closing bracket. + +2013-04-01 Radosław Szymczyszyn + + * INSTALL: Mention xorriso requirement. + +2013-03-31 Andrey Borzenkov + + * grub-core/commands/verify.c: Fix hash algorithms values for + the first three hashes - they start with 1, not with 0. + +2013-03-26 Vladimir Serbinenko + + * grub-core/kern/efi/mm.c (grub_efi_finish_boot_services): + Try terminating EFI services several times due to quirks in some + implementations. + +2013-03-26 Colin Watson + + * grub-core/commands/acpihalt.c (skip_ext_op): Add support for + skipping Event, Device, Processor, PowerRes, ThermalZone, and + BankField extended opcodes. + (get_sleep_type): Add minimal scope handling (just enough to + handle setting the scope to the root path). + (grub_acpi_halt): Parse any SSDTs as well as the DSDT. + * include/grub/acpi.h: Add enumeration values for Event, Device, + Processor, PowerRes, ThermalZone, and BankField extended opcodes. + +2013-03-26 Vladimir Testov + + * grub-core/gfxmenu/font.c (grub_font_get_string_width): Fix + memory leak. + +2013-03-25 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Give more time for AHCI request. + +2013-03-25 Vladimir Serbinenko + + * grub-core/normal/menu.c: Wait if there were errors shown at "boot" + command. + +2013-03-25 Vladimir Serbinenko + + Replace the region at 0 from coreboot tables to available in BSD + memory map. + +2013-03-24 Vladimir Serbinenko + + * util/grub.d/20_linux_xen.in: Automatically add no-real-mode edd=off on + non-BIOS platforms. + +2013-03-24 Vladimir Serbinenko + + * grub-core/Makefile.core.def (vga): Disable on coreboot and multiboot + platforms. + +2013-03-24 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Fix + handling of multi-device filesystems. + +2013-03-24 Vladimir Serbinenko + + * grub-core/Makefile.core.def (vbe): Disable on coreboot and multiboot + platforms. + +2013-03-24 Vladimir Serbinenko + + Add new 'proc' filesystem framework and put luks_script into it. + +2013-03-23 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c: Increase robustness on coreboot + and qemu. + +2013-03-22 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c: Fix incorrect handling of special volumes. + +2013-03-22 Vladimir Serbinenko + + Add ability to generate newc additions on runtime. + +2013-03-22 Vladimir Serbinenko + + * grub-core/commands/i386/coreboot/cbls.c: Fix typos and wrong + description. + +2013-03-21 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + +2013-03-20 Vladimir Serbinenko + + * grub-core/commands/verify.c (hashes): Add several hashes + from the spec. + +2013-03-20 Vladimir Serbinenko + + Slight improve in USB-related boot-time checkpoints. + +2013-03-20 Vladimir Serbinenko + + * grub-core/commands/boottime.c: Fix copyright header. + +2013-03-20 Vladimir Serbinenko + + New commands cbmemc, lscoreboot, coreboot_boottime to inspect + coreboot tables content. Support for cbmemc. + +2013-03-20 Vladimir Serbinenko + + Fix a conflict between ports structures with 2 controllers of + same kind. + +2013-03-20 Vladimir Serbinenko + + * include/grub/boottime.h: Add missing file. + +2013-03-19 Vladimir Serbinenko + + Initialize USB ports in parallel to speed-up boot. + +2013-03-19 Vladimir Serbinenko + + Fix USB devices not being detected when requested + due to delayed attach. + +2013-03-19 Vladimir Serbinenko + + Implement boot time analysis framework. + +2013-03-19 Vladimir Serbinenko + + Remove get_endpoint_descriptor and change all functions needing + descriptor to just receive it as argument rather than endpoint + address. + +2013-03-19 Aleš Nesrsta + + Better estimate the maximum USB transfer size. + +2013-03-17 Vladimir Serbinenko + + Resend a packet if we got the wrong buffer in status. + +2013-03-10 Vladimir Serbinenko + + * grub-core/loader/i386/bsdXX.c (grub_openbsd_find_ramdisk): Use + multiplication rather than division. + +2013-03-10 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_list_alloc): Use shifts rather + than divisions. + +2013-03-10 Vladimir Serbinenko + + * grub-core/commands/verify.c (grub_verify_signature): Use unsigned + operations to have intended shifts and not divisions. + +2013-03-10 Vladimir Serbinenko + + * grub-core/loader/i386/pc/plan9.c (fill_disk): Fix types to use + intended shifts rather than division. + +2013-03-10 Vladimir Serbinenko + + * include/grub/datetime.h (grub_datetime2unixtime): Fix unixtime + computation for some years before epoch. Avode confusing division + while on it. + +2013-03-10 Vladimir Serbinenko + + * grub-core/video/i386/pc/vbe.c + (grub_video_vbe_print_adapter_specific_info): Replace division by + shifts. + +2013-03-10 Vladimir Serbinenko + + Adjust types in gdb module to have intended unsigned shifts rather than + signed divisions. + +2013-03-10 Vladimir Serbinenko + + * grub-core/fs/hfs.c (grub_hfs_read_file): Avoid divmod64 since the + maximum size is 4G - 1 on hfs + +2013-03-10 Vladimir Serbinenko + + Avoid costly 64-bit division in grub_get_time_ms on most platforms. + +2013-03-10 Vladimir Serbinenko + + * grub-core/fs/fshelp.c (grub_fshelp_log2blksize): Remove now unused + function. + +2013-03-07 Andrey Borzenkov + + * grub-core/fs/iso9660.c (add_part): Remove always_inline attribute + causing gcc error with gcc 4.7.1. + +2013-03-07 Nickolai Zeldovich + + * grub-core/commands/acpi.c (grub_acpi_create_ebda): Don't + dereference null pointer. While the code is technically correct, gcc + may eliminate a null check if pointer is already dereferenced. + +2013-03-07 Nickolai Zeldovich + + * grub-core/normal/crypto.c (read_crypto_list): Fix incorrect + OOM check. + * grub-core/normal/term.c (read_terminal_list): Likewise. + +2013-03-07 Vladimir Serbinenko + + Lift up core size limits on some platforms. Fix potential memory + corruption with big core on small memory systems. Document remaining + limits. + +2013-03-05 Vladimir Serbinenko + + * grub-core/term/terminfo.c (grub_terminfo_cls): Issue an explicit + gotoxy to 0,0. + +2013-03-03 Vladimir Serbinenko + + Remove all trampoline support. Add -Wtrampolines when + present. Remove symbols used for trampolines to make + link fail if trampolines are present. + +2013-03-03 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_arglist_to_argv): Move + append out of its parent. + +2013-03-03 Vladimir Serbinenko + + * grub-core/commands/regexp.c (set_matches): Move setvar out of its + parent. + +2013-03-03 Vladimir Serbinenko + + * grub-core/kern/env.c, include/grub/env.h: Change iterator through + all vars to a macro. All users updated. + +2013-03-03 Vladimir Serbinenko + + * grub-core/disk/ieee1275/nand.c: Fix compilation on + i386-ieee1275. + +2013-03-02 Vladimir Serbinenko + + * include/grub/cmos.h: Handle high CMOS addresses on sparc64. + +2013-03-02 Vladimir Serbinenko + + * include/grub/mips/loongson/cmos.h: Fix high CMOS addresses. + +2013-03-02 Vladimir Serbinenko + + Move to more hookless approach in IEEE1275 devices handling. + +2013-03-02 Vladimir Serbinenko + + * grub-core/kern/term.c (grub_term_normal_color), + (grub_term_highlight_color): Add back lost defaults. + +2013-03-02 Vladimir Serbinenko + + Make elfload not use hooks. Opt for flags and iterators instead. + +2013-03-02 Vladimir Serbinenko + + * grub-core/lib/ia64/longjmp.S: Fix the name of longjmp function. + * grub-core/lib/ia64/setjmp.S: Fix the name of setjmp function. + +2013-03-02 Vladimir Serbinenko + + * grub-core/script/execute.c (gettext_append): Remove nested functions. + +2013-03-02 Vladimir Serbinenko + + * grub-core/normal/charset.c (grub_bidi_logical_to_visual): Add + hook pass-through parameter. All users updated and unnested. + +2013-03-02 Vladimir Serbinenko + + * grub-core/commands/loadenv.c (grub_cmd_list_env): Move print_var + out of its parent. + +2013-03-02 Vladimir Serbinenko + + * grub-core/fs/hfs.c: Remove nested functions. + +2013-03-01 Vladimir Serbinenko + + * grub-core/fs/hfsplus.c (grub_hfsplus_btree_iterate_node): Pass + the context through. + (grub_hfsplus_iterate_dir): Move nested function out of its parent. + +2013-03-01 Vladimir Serbinenko + + * util/grub-editenv.c (list_variables): Move print_var out of its + parent. + +2013-03-01 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (read_device_map): Remove nested + function. + +2013-03-01 Vladimir Serbinenko + + * grub-core/gentrigtables.c: Make tables const. + +2013-03-01 Vladimir Serbinenko + + Remove nested functions from videoinfo iterators. + +2013-03-01 Vladimir Serbinenko + + * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Fix compilation + for 64-bit platforms. + +2013-03-01 Vladimir Serbinenko + + * grub-core/disk/efi/efidisk.c: Transform iterate_child_devices into + a FOR_CHILDREN macro. + +2013-03-01 Vladimir Serbinenko + + * grub-core/kern/main.c (grub_set_prefix_and_root): Strip trailing + platform from firmware path. + +2013-02-28 Vladimir Serbinenko + + Enable linux16 on non-BIOS systems for i.a. memtest. + + * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Handle hole at 0 + correctly. + * grub-core/Makefile.core.def (linux16): Enable on all x86 flavours. + +2013-02-28 Vladimir Serbinenko + + * grub-core/kern/i386/coreboot/mmap.c (grub_linuxbios_table_iterate): + Fix end of table condition. + +2013-02-28 Vladimir Serbinenko + + * grub-core/lib/arg.c (grub_arg_show_help): Move showargs + out of its parent. + +2013-02-28 Vladimir Serbinenko + + * grub-core/fs/jfs.c: Remove nested functions. + +2013-02-28 Vladimir Serbinenko + + * grub-core/fs/minix.c: Remove nested functions. + +2013-02-28 Vladimir Serbinenko + + * grub-core/fs/iso9660.c: Remove nested functions. + +2013-02-28 Vladimir Serbinenko + + * grub-core/commands/parttool.c (grub_cmd_parttool): Move show_help out + of parent function. + +2013-02-28 Vladimir Serbinenko + + * util/grub-fstest.c: Remove nested functions. + +2013-02-27 Vladimir Serbinenko + + * grub-core/loader/machoXX.c: Remove nested functions. + +2013-02-27 Colin Watson + + Remove nested functions from disk and file read hooks. + + * include/grub/disk.h (grub_disk_read_hook_t): New type. + (struct grub_disk): Add read_hook_data member. + * include/grub/file.h (struct grub_file): Likewise. + * include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data + argument. + + Update all callers. + +2012-02-27 Andrey Borzenkov + + * grub-core/partmap/msdos.c (grub_partition_msdos_iterate): + Fix off by one error in enumerating extended partitions. + +2013-02-26 Andrey Borzenkov + + * grub-core/disk/efi/efidisk.c(grub_efidisk_get_device_name): Fix + memory leak if device name is not found. + +2013-02-25 Andrey Borzenkov + + * grub-core/normal/menu_entry.c (update_screen): remove + unused variable `off' which caused scroll down arrow to be always shown. + +2013-02-25 Andrey Borzenkov + + * grub-core/normal/menu_entry.c (insert_string): fix off by one + access to unallocated memory. + +2013-02-25 Andrey Borzenkov + + * Makefile.util.def: Add partmap/msdos.c to common library. + * include/grub/msdos_partition.h: Add GRUB_PC_PARTITION_TYPE_LDM + * grub-core/disk/ldm.c: Check for existence of + GRUB_PC_PARTITION_TYPE_LDM. + +2013-02-25 Vladimir Serbinenko + + * grub-core/normal/misc.c (grub_normal_print_device_info): Use KiB to display + sizes and display sector size. + +2013-02-24 Vladimir Serbinenko + + Implement new command cmosdump. + +2013-02-19 Paulo Flabiano Smorigo + + Support Openfirmware disks with non-512B sectors. + + * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Get the block + size of the disk. + * (grub_ofdisk_get_block_size): New function. + * (grub_ofdisk_prepare): Use the correct block size. + * (grub_ofdisk_read): Likewise. + * (grub_ofdisk_write): Likewise. + * include/grub/ieee1275/ofdisk.h (grub_ofdisk_get_block_size): + New proto. + +2013-02-06 Vladimir Serbinenko + + * grub-core/commands/lsacpi.c: Fix types on 64-bit platform. + +2013-02-04 Vladimir Serbinenko + + * grub-core/disk/cryptodisk.c (grub_cryptodisk_scan_device): Don't stop + on first error. + +2013-02-01 Vladimir Serbinenko + + * grub-core/fs/fshelp.c (find_file): Set oldnode to zero after + freeing it. + +2013-02-01 Vladimir Serbinenko + + Implement USBDebug (full USB stack variant). + +2013-02-01 Vladimir Serbinenko + + * grub-core/commands/lsacpi.c: Show more info. Hide some boring parts + unless they have unexpected values. + +2013-02-01 Vladimir Serbinenko + + * grub-core/bus/usb/usb.c (grub_usb_device_attach): Add missing + grub_print_error. + +2013-02-01 Vladimir Serbinenko + + * grub-core/bus/usb/serial/common.c (grub_usbserial_attach): Fix missing + zero-out of port structure. + +2013-01-30 Vladimir Serbinenko + + * grub-core/fs/xfs.c (grub_xfs_read_block): Fix computation in presence + of extended attributes. + +2013-01-27 Andrey Borzenkov + + * util/grub-install.in: change misleading comment about + device.map creation + +2013-01-27 Vladimir Serbinenko + + * grub-core/normal/menu_text.c (grub_menu_init_page): Fix behaviour + when menu highlight color isn't set. + +2013-01-27 C. Masloch + + Improve FreeDOS direct loading support compatibility. + + * include/grub/i386/relocator.h (grub_relocator16_state): + New member ebp. + * grub-core/lib/i386/relocator.c (grub_relocator16_ebp): New extern + variable. + (grub_relocator16_boot): Handle %ebp. + * grub-core/lib/i386/relocator16.S: Likewise. + * grub-core/loader/i386/pc/freedos.c: + Load BPB to pass kernel which partition to load from. + Check that kernel file is not too large. + Set register dl to BIOS unit number as well. + +2013-01-22 Colin Watson + + * util/grub-reboot.in (usage): Document the need for + GRUB_DEFAULT=saved. + * util/grub-set-default.in (usage): Likewise. + Reported by: Brian Candler. Fixes Ubuntu bug #1102925. + +2013-01-21 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Include sys/types.h rather + than defining WORDS_BIGENDIAN manually. + +2013-01-21 Vladimir Serbinenko + + * include/grub/kernel.h (FOR_MODULES): Adjust to preserve alignment + invariants. + +2013-01-21 Colin Watson + + * grub-core/font/font.c (blit_comb: do_blit): Make static instead of + nested. + (blit_comb: add_device_width): Likewise. + +2013-01-21 Colin Watson + + Remove nested functions from USB iterators. + + * include/grub/usb.h (grub_usb_iterate_hook_t): New type. + (grub_usb_controller_iterate_hook_t): Likewise. + (grub_usb_iterate): Add hook_data argument. + (grub_usb_controller_iterate): Likewise. + (struct grub_usb_controller_dev.iterate): Likewise. + + Update all implementations and callers. + +2013-01-21 Vladimir Serbinenko + + * grub-core/normal/term.c (print_ucs4_terminal): Don't output right + margin when not needed. + +2013-01-21 Vladimir Serbinenko + + Make color variables global instead of it being per-terminal. + +2013-01-21 Vladimir Serbinenko + + * grub-core/commands/ls.c (grub_ls_print_devices): Add missing + asterisk. + +2013-01-21 Colin Watson + + Fix powerpc and sparc64 build failures caused by un-nesting memory + map iterators. + +2013-01-21 Colin Watson + + * grub-core/disk/arc/arcdisk.c (grub_arcdisk_iterate): Fix + parameter declarations. + +2013-01-21 Vladimir Serbinenko + + * grub-core/commands/lsmmap.c: Fix unused variable on emu. + +2013-01-21 Vladimir Serbinenko + + Improve spkmomdem reliability by adding a separator between bytes. + +2013-01-21 Colin Watson + + * grub-core/partmap/msdos.c (embed_signatures): Add the signature of + an Acer registration utility with several sightings in the wild. + Reported by: Rickard Westman. Fixes Ubuntu bug #987022. + +2013-01-21 Colin Watson + + Remove nested functions from filesystem directory iterators. + + * include/grub/fs.h (grub_fs_dir_hook_t): New type. + (struct grub_fs.dir): Add hook_data argument. + + Update all implementations and callers. + +2013-01-21 Colin Watson + + * docs/grub.texi (Multi-boot manual config): Fix typo for + "recommended". + +2013-01-20 Leif Lindholm + + * util/grub-mkimage.c (main): Postpone freeing arguments.output + until after its use in generate_image. + +2013-01-20 Colin Watson + + * grub-core/loader/i386/linux.c (grub_cmd_initrd): Don't add the + initrd size to addr_min, since the initrd will be allocated after + this address. + +2013-01-20 Andrey Borzenkov + + * conf/Makefile.common: Fix autogen rules to pass definition + files on stdin; Makefile.util.am needs Makefile.utilgcry.def + +2013-01-20 Leif Lindholm + + * include/grub/elf.h: Update ARM definitions based on binutils. + +2013-01-20 Aleš Nesrsta + + Split long USB transfers into short ones. + +2013-01-20 Andrey Borzenkov + + * docs/grub.texi (Simple configuration): Clarify GRUB_HIDDEN_TIMEOUT + is interrupted by ESC. + +2013-01-20 Vladimir Serbinenko + + * util/grub-script-check.c (main): Uniform the error message. + +2013-01-20 Colin Watson + + Remove nested functions from ELF iterators. + +2013-01-20 Colin Watson + + Remove nested functions from device iterators. + + * include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type. + (grub_arc_iterate_devs): Add hook_data argument. + * include/grub/ata.h (grub_ata_dev_iterate_hook_t): New type. + (struct grub_ata_dev.iterate): Add hook_data argument. + * include/grub/device.h (grub_device_iterate_hook_t): New type. + (grub_device_iterate): Add hook_data argument. + * include/grub/disk.h (grub_disk_dev_iterate_hook_t): New type. + (struct grub_disk_dev.iterate): Add hook_data argument. + (grub_disk_dev_iterate): Likewise. + * include/grub/gpt_partition.h (grub_gpt_partition_map_iterate): + Likewise. + * include/grub/msdos_partition.h (grub_partition_msdos_iterate): + Likewise. + * include/grub/partition.h (grub_partition_iterate_hook_t): New + type. + (struct grub_partition_map.iterate): Add hook_data argument. + (grub_partition_iterate): Likewise. + * include/grub/scsi.h (grub_scsi_dev_iterate_hook_t): New type. + (struct grub_scsi_dev.iterate): Add hook_data argument. + + Update all callers. + +2013-01-20 Colin Watson + + Fix typos for "developer" and "development". + +2013-01-18 Vladimir Serbinenko + + Add license header to spkmodem-recv.c. + +2013-01-17 Vladimir Serbinenko + + Rewrite spkmodem to use PIT for timing. Double the speed. + +2013-01-16 Vladimir Serbinenko + + Add new command pcidump. + +2013-01-16 Vladimir Serbinenko + + New terminal outputs using serial: morse and spkmodem. + +2013-01-16 Vladimir Serbinenko + + Improve bidi handling in entry editor. + +2013-01-16 Vladimir Serbinenko + + * grub-core/script/lexer.c (grub_script_lexer_init): Rename getline + argument to prevent name collision. + +2013-01-15 Colin Watson + + Remove nested functions from script reading and parsing. + + * grub-core/kern/parser.c (grub_parser_split_cmdline): Add + getline_data argument, passed to getline. + * grub-core/kern/rescue_parser.c (grub_rescue_parse_line): Add + getline_data argument, passed to grub_parser_split_cmdline. + * grub-core/script/lexer.c (grub_script_lexer_yywrap): Pass + lexerstate->getline_data to lexerstate->getline. + (grub_script_lexer_init): Add getline_data argument, saved in + lexerstate->getline_data. + * grub-core/script/main.c (grub_normal_parse_line): Add getline_data + argument, passed to grub_script_parse. + * grub-core/script/script.c (grub_script_parse): Add getline_data + argument, passed to grub_script_lexer_init. + * include/grub/parser.h (grub_parser_split_cmdline): Update + prototype. Update all callers to pass appropriate getline data. + (struct grub_parser.parse_line): Likewise. + (grub_rescue_parse_line): Likewise. + * include/grub/reader.h (grub_reader_getline_t): Add void * + argument. + * include/grub/script_sh.h (struct grub_lexer_param): Add + getline_data member. + (grub_script_parse): Update prototype. Update all callers to pass + appropriate getline data. + (grub_script_lexer_init): Likewise. + (grub_normal_parse_line): Likewise. + + * grub-core/commands/legacycfg.c (legacy_file_getline): Add unused + data argument. + * grub-core/kern/parser.c (grub_parser_execute: getline): Make + static instead of nested. Rename to ... + (grub_parser_execute_getline): ... this. + * grub-core/kern/rescue_reader.c (grub_rescue_read_line): Add unused + data argument. + * grub-core/normal/main.c (read_config_file: getline): Make static + instead of nested. Rename to ... + (read_config_file_getline): ... this. + (grub_normal_read_line): Add unused data argument. + * grub-core/script/execute.c (grub_script_execute_sourcecode: + getline): Make static instead of nested. Rename to ... + (grub_script_execute_sourcecode_getline): ... this. + * util/grub-script-check.c (main: get_config_line): Make static + instead of nested. + +2013-01-15 Colin Watson + + Remove nested functions from memory map iterators. + + * grub-core/efiemu/mm.c (grub_efiemu_mmap_iterate): Add hook_data + argument, passed to hook. + * grub-core/kern/i386/coreboot/mmap.c + (grub_linuxbios_table_iterate): Likewise. + (grub_machine_mmap_iterate: iterate_linuxbios_table): Make static + instead of nested. + (grub_machine_mmap_iterate): Add hook_data argument. + * grub-core/kern/i386/multiboot_mmap.c (grub_machine_mmap_iterate): + Add hook_data argument, passed to hook. + * grub-core/kern/i386/pc/mmap.c (grub_machine_mmap_iterate): + Likewise. + * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_iterate): + Likewise. + * grub-core/kern/ieee1275/mmap.c (grub_machine_mmap_iterate): + Likewise. + * grub-core/kern/mips/arc/init.c (grub_machine_mmap_iterate): + Likewise. + * grub-core/kern/mips/loongson/init.c (grub_machine_mmap_iterate): + Likewise. + * grub-core/kern/mips/qemu_mips/init.c (grub_machine_mmap_iterate): + Likewise. + * grub-core/mmap/efi/mmap.c (grub_efi_mmap_iterate): Likewise. + (grub_machine_mmap_iterate): Likewise. + * grub-core/mmap/mmap.c (grub_mmap_iterate): Likewise. + * include/grub/efiemu/efiemu.h (grub_efiemu_mmap_iterate): Update + prototype. + * include/grub/memory.h (grub_memory_hook_t): Add data argument. + Remove NESTED_FUNC_ATTR from here and from all users. + (grub_mmap_iterate): Update prototype. + (grub_efi_mmap_iterate): Update prototype. Update all callers to + pass appropriate hook data. + (grub_machine_mmap_iterate): Likewise. + + * grub-core/commands/acpi.c (grub_acpi_create_ebda: find_hook): Make + static instead of nested. + * grub-core/commands/lsmmap.c (grub_cmd_lsmmap: hook): Likewise. + Rename to ... + (lsmmap_hook): ... this. + * grub-core/efiemu/mm.c (grub_efiemu_mmap_init: bounds_hook): + Likewise. + (grub_efiemu_mmap_fill: fill_hook): Likewise. + * grub-core/kern/i386/coreboot/init.c (grub_machine_init: + heap_init): Likewise. + * grub-core/kern/i386/pc/init.c (grub_machine_init: hook): Likewise. + Rename to ... + (mmap_iterate_hook): ... this. + * grub-core/kern/ieee1275/init.c (grub_claim_heap: heap_init): + Likewise. + * grub-core/lib/ieee1275/relocator.c + (grub_relocator_firmware_get_max_events: count): Likewise. + (grub_relocator_firmware_fill_events: fill): Likewise. Rename + to ... + (grub_relocator_firmware_fill_events_iter): ... this. + * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_align: + hook): Likewise. Rename to ... + (grub_relocator_alloc_chunk_align_iter): ... this. + * grub-core/loader/i386/bsd.c (generate_e820_mmap: hook): Likewise. + Rename to ... + (generate_e820_mmap_iter): ... this. + * grub-core/loader/i386/linux.c (find_mmap_size: hook): Likewise. + Rename to ... + (count_hook): ... this. + (grub_linux_boot: hook): Likewise. Rename to ... + (grub_linux_boot_mmap_find): ... this. + (grub_linux_boot: hook_fill): Likewise. Rename to ... + (grub_linux_boot_mmap_fill): ... this. + * grub-core/loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap: + hook): Likewise. Rename to ... + (grub_fill_multiboot_mmap_iter): ... this. + * grub-core/loader/multiboot.c (grub_get_multiboot_mmap_count: + hook): Likewise. Rename to ... + (count_hook): ... this. + * grub-core/loader/multiboot_mbi2.c (grub_fill_multiboot_mmap: + hook): Likewise. Rename to ... + (grub_fill_multiboot_mmap_iter): ... this. + * grub-core/loader/powerpc/ieee1275/linux.c + (grub_linux_claimmap_iterate: alloc_mem): Likewise. + * grub-core/loader/sparc64/ieee1275/linux.c (alloc_phys: choose): + Likewise. Rename to ... + (alloc_phys_choose): ... this. + (determine_phys_base: get_physbase): Likewise. + * grub-core/mmap/i386/mmap.c (grub_mmap_malign_and_register: + find_hook): Likewise. + * grub-core/mmap/i386/pc/mmap.c (preboot: fill_hook): Likewise. + (malloc_hook: count_hook): Likewise. + * grub-core/mmap/i386/uppermem.c (grub_mmap_get_lower: hook): + Likewise. Rename to ... + (lower_hook): ... this. + (grub_mmap_get_upper: hook): Likewise. Rename to ... + (upper_hook): ... this. + (grub_mmap_get_post64: hook): Likewise. Rename to ... + (post64_hook): ... this. + * grub-core/mmap/mips/uppermem.c (grub_mmap_get_lower: hook): + Likewise. Rename to ... + (lower_hook): ... this. + (grub_mmap_get_upper: hook): Likewise. Rename to ... + (upper_hook): ... this. + * grub-core/mmap/mmap.c (grub_mmap_iterate: count_hook): Likewise. + (grub_mmap_iterate: fill_hook): Likewise. + (fill_mask): Pass addr and mask within a single struct. + (grub_cmd_badram: hook): Make static instead of nested. Rename + to ... + (badram_iter): ... this. + (grub_cmd_cutmem: hook): Likewise. Rename to ... + (cutmem_iter): ... this. + +2013-01-13 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (read_device_map): Explicitly + delimit path in strings using quotes. + * util/getroot.c (grub_guess_root_devices): Likewise. + (grub_make_system_path_relative_to_its_root): Likewise. + * util/grub-probe.c (probe): Likewise. + * util/ieee1275/ofpath.c (find_obppath): Likewise. + (xrealpath): Likewise. + +2013-01-13 Vladimir Serbinenko + + Fix compilation with older compilers. + + * grub-core/Makefile.core.def (mpi): Add mpi-inline.c. + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h: Remove redundant + declarations. + * grub-core/lib/posix_wrap/string.h: Include sys/types.h. + * grub-core/lib/posix_wrap/sys/types.h: Add common types. + * grub-core/lib/xzembed/xz_dec_lzma2.c (dict_put): Replace byte + identifier with b. + * grub-core/lib/xzembed/xz_dec_stream.c (dec_vli): Likewise. + * include/grub/crypto.h: Add type defines. + * util/import_gcrypth.sed: Remove duplicate type defines. + +2013-01-13 Vladimir Serbinenko + + New command list_trusted. + + * grub-core/commands/verify.c (grub_cmd_list): New function. + +2013-01-13 Colin Watson + + * util/grub-mkimage.c (generate_image): Fix "size of public key" + info message. + +2013-01-13 Colin Watson + + Remove nested functions from PCI iterators. + + * grub-core/bus/pci.c (grub_pci_iterate): Add hook_data argument, + passed to hook. Update all callers to pass appropriate hook data. + * grub-core/bus/emu/pci.c (grub_pci_iterate): Likewise. + * include/grub/pci.h (grub_pci_iteratefunc_t): Add data argument. + Remove NESTED_FUNC_ATTR from here and from all users. + (grub_pci_iterate): Update prototype. + * grub-core/bus/cs5536.c (grub_cs5536_find: hook): Make static + instead of nested. Rename to ... + (grub_cs5536_find_iter): ... this. + * grub-core/kern/efi/mm.c (stop_broadcom: find_card): Likewise. + * grub-core/kern/mips/loongson/init.c (init_pci: set_card): + Likewise. + * grub-core/kern/vga_init.c (grub_qemu_init_cirrus: find_card): + Likewise. + * grub-core/video/bochs.c (grub_video_bochs_setup: find_card): + Likewise. + * grub-core/video/cirrus.c (grub_video_cirrus_setup: find_card): + Likewise. + * grub-core/video/efi_uga.c (find_framebuf: find_card): Likewise. + * grub-core/video/radeon_fuloong2e.c + (grub_video_radeon_fuloong2e_setup: find_card): Likewise. + * grub-core/video/sis315pro.c (grub_video_sis315pro_setup: + find_card): Likewise. + * grub-core/video/sm712.c (grub_video_sm712_setup: find_card): + Likewise. + +2013-01-12 Vladimir Serbinenko + + * grub-core/commands/verify.c: Mark messages for translating. + +2013-01-12 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/mem.c (gcry_x*alloc): Make out of memory + fatal. + +2013-01-12 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/mem.c (_gcry_log_bug): Make gcrypt bugs + fatal. + +2013-01-12 Vladimir Serbinenko + + * autogen.sh: Do not try to delete nonexistant files. + * util/import_gcrypth.sed: Add some missing header removals. + +2013-01-12 Colin Watson + + Clean up dangling references to grub-setup. + Fixes Ubuntu bug #1082045. + + * docs/grub.texi (Images): Refer generally to grub-install rather + than directly to grub-setup. + (Installing GRUB using grub-install): Remove direct reference to + grub-setup. + (Device map) Likewise. + (Invoking grub-install): Likewise. + * docs/man/grub-install.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise. + * util/grub-install.in (usage): Likewise. + + * util/bash-completion.d/grub-completion.bash.in (_grub_setup): + Apply to grub-bios-setup and grub-sparc64-setup rather than to + grub-setup. + * configure.ac: Remove grub_setup output variable. + + * docs/man/grub-bios-setup.h2m (NAME): Change name from grub-setup + to grub-bios-setup. + * docs/man/grub-sparc64-setup.h2m (NAME): Change name from + grub-setup to grub-sparc64-setup. + +2013-01-11 Vladimir Serbinenko + + Import gcrypt public-key cryptography and implement signature checking. + +2013-01-10 Vladimir Serbinenko + + * grub-core/fs/ntfs.c: Ue more appropriate types. + * grub-core/fs/ntfscomp.c: Likewise. + * include/grub/ntfs.h: Likewise. + +2013-01-10 Vladimir Serbinenko + + Support Apple FAT binaries on non-Apple platforms. + + * include/grub/macho.h (GRUB_MACHO_FAT_EFI_MAGIC): New define. + * include/grub/i386/macho.h (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT): + Likewise. + * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Parse + Apple FAT binaries. + +2013-01-10 Vladimir Serbinenko + + * grub-core/kern/disk.c (grub_disk_write): Fix sector number on 4K + sector devices. + +2013-01-07 Colin Watson + + * grub-core/io/bufio.c (grub_bufio_open): Use grub_zalloc instead of + explicitly zeroing elements. + * grub-core/io/gzio.c (grub_gzio_open): Likewise. + * grub-core/io/lzopio.c (grub_lzopio_open): Remove explicit zeroing + of elements in a structure already allocated using grub_zalloc. + * grub-core/io/xzio.c (grub_xzio_open): Likewise. + +2013-01-07 Colin Watson + + * docs/grub.texi (grub_cpu): New subsection. + (grub_platform): Likewise. + +2013-01-07 Vladimir Serbinenko + + * grub-core/fs/minix.c (grub_minix_read_file): Simplify arithmetics. + +2013-01-05 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext2_read_block): Use shifts rather than + divisions. + +2013-01-05 Vladimir Serbinenko + + * grub-core/fs/ntfs.c: Eliminate useless divisions in favor of shifts. + * grub-core/fs/ntfscomp.c: Likewise. + * include/grub/ntfs.h (grub_ntfs_data): Replace spc with log_spc. + (grub_ntfs_comp): Likewise. + +2013-01-05 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (-grub_nilfs2_palloc_groups_per_desc_block): + Rename to ... + (grub_nilfs2_palloc_log_groups_per_desc_block): ... this. Return log + of groups_per_block. All users updated. + +2013-01-05 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c (grub_diskfilter_write): Call + grub_error properly. + * grub-core/disk/ieee1275/nand.c (grub_nand_write): Likewise. + * grub-core/disk/loopback.c (grub_loopback_write): Likewise. + +2013-01-03 Vladimir Serbinenko + + * util/grub.d/10_kfreebsd.in: Correct the patch to zpool.cache as it's + always in /boot/zfs. + Reported by: Yuta Satoh. + +2013-01-03 Yuta Satoh + + * util/grub.d/10_kfreebsd.in: Fix improper references to grub-probe by + ${grub_probe} + +2013-01-03 Vladimir Serbinenko + + * configure.ac: Extend -Wno-trampolines to host. + +2013-01-03 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_susp_iterate): Avoid hang if + entry->len = 0. + +2013-01-03 Colin Watson + + * docs/grub.texi (Invoking grub-mkrelpath): New section. + (Invoking grub-script-check): Likewise. + +2013-01-03 Colin Watson + + * docs/grub.texi (Invoking grub-mount): New section. + Reported by: Filipus Klutiero. Fixes Debian bug #666427. + +2013-01-02 Colin Watson + + * grub-core/tests/lib/test.c (grub_test_run): Return non-zero on + test failures, so that a failing unit test correctly causes 'make + check' to fail. + +2013-01-02 Colin Watson + + Fix failing printf test. + + * grub-core/kern/misc.c (grub_vsnprintf_real): Parse '-', '.', and + '$' in the correct order when collecting type information. + +2013-01-02 Colin Watson + + * docs/grub.texi (configfile): Explain environment variable + handling. + (source): New section. + Reported by: Arbiel Perlacremaz. Fixes Savannah bug #35564. + +2012-12-31 Colin Watson + + Remove several trivially-unnecessary uses of nested functions. + + * grub-core/commands/i386/pc/sendkey.c + (grub_cmd_sendkey: find_key_code, find_ascii_code): Make static + instead of nested. + * grub-core/commands/legacycfg.c (legacy_file: getline): Likewise. + Rename to ... + (legacy_file_getline): ... this. + * grub-core/commands/loadenv.c (grub_cmd_load_env: set_var): + Likewise. + * grub-core/kern/corecmd.c (grub_core_cmd_set: print_env): Likewise. + * grub-core/kern/fs.c (grub_fs_probe: dummy_func): Likewise. Rename + to ... + (probe_dummy_iter): ... this. + * grub-core/kern/i386/coreboot/mmap.c + (grub_linuxbios_table_iterate: check_signature): Likewise. + * grub-core/kern/parser.c (grub_parser_split_cmdline: + check_varstate): Likewise. Mark inline. + * grub-core/lib/arg.c (find_short: fnd_short): Likewise. Pass + an additional parameter. + (find_long: fnd_long): Likewise. Pass two additional parameters. + * grub-core/lib/crc.c (init_crc32c_table: reflect): Likewise. + * grub-core/lib/crc64.c (init_crc64_table: reflect): Likewise. + * grub-core/lib/ieee1275/cmos.c (grub_cmos_find_port: hook): + Likewise. Rename to ... + (grub_cmos_find_port_iter): ... this. + * grub-core/lib/ieee1275/datetime.c (find_rtc: hook): Likewise. + Rename to ... + (find_rtc_iter): ... this. + + * grub-core/normal/menu_entry.c (run): Fold nested editor_getsource + function directly into the function body, since it is only called + once. + +2012-12-30 Colin Watson + + * grub-core/bus/usb/ehci.c (grub_ehci_pci_iter): Remove incorrect + __attribute__ ((unused)). + * grub-core/video/bochs.c (find_card): Likewise. + * grub-core/video/cirrus.c (find_card): Likewise. + * grub-core/video/radeon_fuloong2e.c (find_card): Likewise. + * grub-core/video/sis315pro.c (find_card): Likewise. + * grub-core/video/sm712.c (find_card): Likewise. + +2012-12-28 Colin Watson + + * util/grub-mkconfig.in: Accept GRUB_TERMINAL_OUTPUT=vga_text. + Fixes Savannah bug #37821. + +2012-12-28 Colin Watson + + Apply program name transformations at build-time rather than at + run-time. Fixes Debian bug #696465. + + * acinclude.m4 (grub_TRANSFORM): New macro. + * configure.ac: Create output variables with transformed names for + most programs. + * util/bash-completion.d/grub-completion.bash.in: Use + pre-transformed variables for program names. + * util/grub-install.in: Likewise. + * util/grub-kbdcomp.in: Likewise. + * util/grub-mkconfig.in: Likewise. + * util/grub-mkconfig_lib.in: Likewise. + * util/grub-mknetdir.in: Likewise. + * util/grub-mkrescue.in: Likewise. + * util/grub-mkstandalone.in: Likewise. + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. + * tests/util/grub-shell-tester.in: Remove unused assignment. + * tests/util/grub-shell.in: Likewise. + * util/grub.d/00_header.in: Likewise. + +2012-12-28 Colin Watson + + Backport gnulib fixes for C11. Fixes Savannah bug #37738. + + * grub-core/gnulib/stdio.in.h (gets): Warn on use only if + HAVE_RAW_DECL_GETS. + * m4/stdio_h.m4 (gl_STDIO_H): Check for gets. + +2012-12-11 Vladimir Serbinenko + + * util/grub.d/20_linux_xen.in: Addmissing assignment to machine. + Reported by: Eriks Latosheks . + +2012-12-10 Vladimir Serbinenko + + * docs/grub.texi (Network): Update instructions on generating netboot + image. + +2012-12-10 Vladimir Serbinenko + + * grub-core/disk/cryptodisk.c (grub_cmd_cryptomount): Strip brackets + around device name if necessarry. + +2012-12-10 Paulo Flabiano Smorigo + + * util/grub-install.in: Follow the symbolic link parameter added + to the file command. + +2012-12-10 Andrey Borzenkov + + * util/grub-install.in: Remove stale TODO. + +2012-12-10 Paulo Flabiano Smorigo + + * grub-core/kern/ieee1275/init.c (grub_machine_get_bootlocation): Use + dynamic allocation for the bootpath buffer. + +2012-12-10 Dr. Tilmann Bubeck + + * grub-core/gfxmenu/view.c (init_terminal): Avoid making terminal + window too small. + +2012-12-10 Vladimir Serbinenko + + * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Get font as + argument rather than font name. All users updated. + (grub_gfxterm_set_window): Likewise. + +2012-12-10 Vladimir Testov + + * util/grub-mkfont.c (argp_parser): Fix a typo which prevented --asce + from working. + +2012-12-10 Vladimir Serbinenko + + * util/getroot.c (convert_system_partition_to_system_disk): Support + nbd disks. + +2012-12-10 Vladimir Serbinenko + + * grub-core/fs/ufs.c (grub_ufs_dir): Stop if direntlen is 0 to avoid + infinite loop on corrupted FS. + +2012-12-08 Vladimir Serbinenko + + Fix big-endian mtime. + + * grub-core/fs/ufs.c (grub_ufs_inode): Split improperly attached + together sec and usec. + (grub_ufs_dir): Use correct byteswapping for UFS time. + +2012-12-08 Vladimir Serbinenko + + Support big-endian UFS1. + + * Makefile.util.def (libgrubmods): Add ufs_be.c + * grub-core/Makefile.core.def (ufs1_be): New module. + * grub-core/fs/ufs_be.c: New file. + * grub-core/fs/ufs.c: Declare grub_ufs_to_le* and use them throughout + the file. + +2012-11-28 Leif Lindholm + + * include/grub/types.h: Fix functionality unaffecting typo in + GRUB_TARGET_WORDSIZE conditional macro. + +2012-11-28 Paulo Flabiano Smorigo + + * grub-core/net/bootp.c (parse_dhcp_vendor): Fix double increment. + +2012-10-28 Grégoire Sutre + + * util/grub.d/10_netbsd.in: Fix tab indentation and make sure + that /netbsd appears first (when it exists). + +2012-10-12 Christoph Junghans + + * grub-core/Makefile.am (moddep.lst): Use $(AWK) rather than awk. + Fixes Savannah bug #37558. + +2012-10-12 Colin Watson + + * grub-core/commands/configfile.c (GRUB_MOD_INIT): Correct + description of extract_entries_configfile. + +2012-10-05 Colin Watson + + * grub-core/loader/i386/linux.c (allocate_pages): Fix spelling of + preferred_address. + (grub_cmd_linux): Likewise. + * grub-core/net/icmp6.c (struct prefix_option): Fix spelling of + preferred_lifetime. Update all users. + +2012-09-26 Colin Watson + + * Makefile.util.def (grub-mknetdir): Move to $prefix/bin. + Reported by: Daniel Kahn Gillmor. Fixes Debian bug #688799. + +2012-09-26 Colin Watson + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Redirect + errors from grub-probe to /dev/null, not stdout. + +2012-09-26 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_mount): Support AFFS bootblock in + sector 1. + +2012-09-24 Colin Watson + + * util/grub-install.in: Make the error message if $source_dir + doesn't exist more useful. + +2012-09-22 Colin Watson + + Fix grub-emu build on FreeBSD. + + * Makefile.util.def (grub-mount): Add LIBGEOM to ldadd. + * grub-core/net/drivers/emu/emunet.c: Only include Linux-specific + headers on Linux. + (GRUB_MOD_INIT): Return immediately on non-Linux platforms; this + implementation is currently Linux-specific. + * util/getroot.c (exec_pipe): Define only on Linux or when either + libzfs or libnvpair is unavailable. + (find_root_devices_from_poolname): Remove unused path variable. + +2012-09-19 Colin Watson + + * grub-core/partmap/msdos.c (pc_partition_map_embed): Revert + incorrect off-by-one fix from 2011-02-12. A 62-sector core image + should fit before end == 63. + +2012-09-19 Colin Watson + + * util/grub-setup.c (write_rootdev): Remove unused core_img + parameter. Update all callers. + (setup): Define core_sectors only if GRUB_SETUP_BIOS, to appease + 'gcc -Wunused-but-set-variable'. Remove unnecessary nested #ifdef + GRUB_SETUP_BIOS. + +2012-09-18 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (grub_tab): New variable. + (grub_add_tab): New function. + * util/grub.d/10_hurd.in: Replace \t with $grub_tab orgrub_add_tab. + * util/grub.d/10_illumos.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/10_netbsd.in: Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/10_xnu.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + * util/grub.d/30_os-prober.in: Likewise. + +2012-09-18 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set + GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN on mac. + * grub-core/term/ieee1275/console.c (grub_console_init_lately): Use + ieee1275-nocursor if GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN is set. + * grub-core/term/terminfo.c (grub_terminfo_set_current): Add new type + ieee1275-nocursor. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New value + GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN. + +2012-09-18 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (grub_cmd_linux): Fix incorrect + le-conversion. + Reported by: BURETTE, Bernard. + +2012-09-17 Colin Watson + + * util/grub-mkconfig_lib.in (grub_quote): Remove outdated sentence + from comment. + +2012-09-14 Colin Watson + + * grub-core/term/terminfo.c: Only fix up powerpc key repeat on + IEEE1275 machines. Fixes powerpc-emu compilation. + * include/grub/terminfo.h: Likewise. + +2012-09-12 Vladimir Serbinenko + + * include/grub/efi/api.h (grub_efi_runtime_services): Make vendor_guid + a const pointer. + * grub-core/efiemu/runtime/efiemu.c (efiemu_memcpy): Make from a + const pointer. + (efiemu_set_variable): Make vendor_guid a const pointer. + +2012-09-12 Vladimir Serbinenko + + Don't require grub-mkconfig_lib to generate manpages for programs. + + * gentpl.py (manpage): Additional argument adddeps. Add adddeps to + dependencies, don't add grub-mkconfig_lib. + (program): Pass empty adddeps. + (script): Pass grub-mkconfig_lib as adddeps. + +2012-09-11 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c (free_array) [GRUB_UTIL]: Fix memory leak. + * util/getroot.c (grub_find_device): Likewise. + (get_mdadm_uuid): Likewise. + (grub_util_is_imsm): Likewise. + (grub_util_pull_device): Likewise. + * util/grub-probe.c (probe): Likewise. + +2012-09-10 Benoit Gschwind + + * grub-core/loader/efi/appleloader.c (devpath_8): New var. + (devs): Add devpath_8. + +2012-09-08 Peter Jones + + * grub-core/Makefile.core.def (efifwsetup): New module. + * grub-core/commands/efi/efifwsetup.c: New file. + * grub-core/kern/efi/efi.c (grub_efi_set_variable): New function + * include/grub/efi/api.h (GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI): + New define. + * include/grub/efi/efi.h (grub_efi_set_variable): New proto. + +2012-09-05 Jiri Slaby + + * configure.ac: Add SuSe path. + +2012-09-05 Colin Watson + + * NEWS: Fix typo. + +2012-09-05 Colin Watson + + * util/import_gcry.py: Sort cipher_files, to make build system + generation more deterministic. + +2012-09-05 Vladimir Serbinenko + + * grub-core/disk/ieee1275/ofdisk.c (scan): Check function return value. + * grub-core/lib/ieee1275/datetime.c (grub_get_datetime): Likewise. + (grub_set_datetime): Likewise. + +2012-09-05 Vladimir Serbinenko + + * grub-core/script/yylex.l: Ignore unused-function and sign-compare + warnings. + +2012-09-05 Vladimir Serbinenko + + * grub-core/partmap/dvh.c (grub_dvh_is_valid): Add missing byteswap. + +2012-09-05 Vladimir Serbinenko + + * grub-core/fs/xfs.c (grub_xfs_read_block): Make keys a const pointer. + +2012-09-04 Colin Watson + + * Makefile.am (EXTRA_DIST): Add linguas.sh. It's only strictly + required for checkouts from bzr, but it may be useful for users or + distributors wishing to update translations against a tarball + distribution, and it can be helpful for the tarball to be a superset + of what's in bzr. + +2012-09-04 Colin Watson + + * Makefile.am (EXTRA_DIST): Add + grub-core/tests/boot/linux.init-mips.S, + grub-core/tests/boot/linux.init-ppc.S, and + grub-core/tests/boot/linux-ppc.cfg. + +2012-09-04 Colin Watson + + * grub-core/mmap/mips/loongson: Remove empty directory. + +2012-09-04 Colin Watson + + * docs/man/grub-mkdevicemap.h2m: Remove, since grub-mkdevicemap is + gone. + +2012-09-04 Colin Watson + + * .bzrignore: Add grub-bios-setup, grub-ofpathname, and + grub-sparc64-setup. + +2012-08-05 Grégoire Sutre + + * configure.ac: Strengthen the test for working -nostdinc -isystem. + +2012-07-31 Grégoire Sutre + + * po/POTFILES.in: Regenerated. + +2012-07-31 Grégoire Sutre + + * docs/grub.texi: Note that NetBSD/i386 is Multiboot-compliant. + (NetBSD): New subsection. + +2012-07-22 Ales Nesrsta + + * grub-core/bus/usb/ehci.c: PCI iter. - added PCI bus master setting. + * grub-core/bus/usb/ohci.c: PCI iter. - added PCI bus master setting. + +2012-07-22 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (grub_quote): Remove extra layer of escape. + * util/grub.d/10_hurd.in: Add missing quoting. + * util/grub.d/10_illumos.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + +2012-07-22 Vladimir Serbinenko + + New command `lsefi'. + + * grub-core/Makefile.core.def (lsefi): New module. + * grub-core/commands/efi/lsefi.c: New file. + * include/grub/efi/api.h: Add more GUIDs. + +2012-07-22 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_bsd_elf32_size_hook): Fix mask. + (grub_bsd_elf32_hook): Likewise. + (grub_bsd_elf64_size_hook): Likewise. + (grub_bsd_elf64_hook): Likewise. + (grub_bsd_load_elf): Likewise. + +2012-07-22 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_dec_stream.c (hash_validate): Fix behaviour + if hash function is unavailable. + (dec_stream_header): Likewise. + +2012-07-22 Vladimir Serbinenko + + * grub-core/normal/autofs.c (autoload_fs_module): Save and restore + filter state. + +2012-07-22 Vladimir Serbinenko + + Fix coreboot compilation. + + * grub-core/term/i386/pc/vga_text.c (grub_vga_text_init): Rename to ... + (grub_vga_text_init_real): ... this. + (grub_vga_text_fini): Rename to ... + (grub_vga_text_fini_real): ... this. + +2012-07-07 Vladimir Serbinenko + + * grub-core/Makefile.am: Fix path to boot/i386/pc/startup_raw.S. + +2012-07-02 Vladimir Serbinenko + + * grub-core/lib/legacy_parse.c: Support clear and testload. + +2012-07-02 Vladimir Serbinenko + + * grub-core/term/efi/serial.c: Support 1.5 stop bits. + +2012-07-02 Vladimir Serbinenko + + * grub-core/fs/ext2.c: Experimental support for 64-bit. + +2012-07-02 Vladimir Serbinenko + + * grub-core/net/tftp.c (ack): Fix endianness problem. + (tftp_receive): Likewise. + Reported by: Michael Davidsaver. + +2012-07-02 Vladimir Serbinenko + + * gentpl.py: Make mans depend on grub-mkconfig_lib. + +2012-07-02 Vladimir Serbinenko + + * include/grub/list.h (FOR_LIST_ELEMENTS_SAFE): New macro. + * include/grub/command.h (FOR_COMMANDS_SAFE): Likewise. + * grub-core/commands/help.c (grub_cmd_help): Use FOR_COMMANDS_SAFE. + +2012-07-02 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (find_efi_mmap_size): Don't decrease + efi_mmap_size. + Reported by: Stuart Hayes. + +2012-06-28 Vladimir Serbinenko + + Add monochrome text support (mda_text, aka `hercules' in grub-legacy). + + * grub-core/Makefile.core.def (mda_text): New module. + * grub-core/lib/legacy_parse.c (grub_legacy_parse): Support `hercules'. + * grub-core/term/i386/vga_common.c (grub_console_cur_color): Moved to .. + * grub-core/term/i386/pc/vga_text.c (cur_color): ... here + * grub-core/term/i386/pc/console.c (grub_console_cur_color): ... and + here. + * grub-core/term/i386/vga_common.c (grub_console_getwh): Moved to .. + * grub-core/term/i386/pc/vga_text.c (grub_console_getwh): ... here + * grub-core/term/i386/pc/console.c (grub_console_getwh): ... and + here. + * grub-core/term/i386/vga_common.c (grub_console_setcolorstate): Moved + to .. + * grub-core/term/i386/pc/vga_text.c (grub_console_setcolorstate): + ... here + * grub-core/term/i386/pc/console.c (grub_console_setcolorstate): ... and + here. + * grub-core/term/i386/vga_common.c: Removed. + * include/grub/i386/vga_common.h: Likewise. + * include/grub/vga.h (grub_vga_cr_bw_write): New function. + (grub_vga_cr_bw_read): Likewise. + * include/grub/vgaregs.h (GRUB_VGA_IO_CR_BW_INDEX): New enum value. + (GRUB_VGA_IO_CR_BW_DATA): Likewise. + * grub-core/term/i386/pc/vga_text.c [MODE_MDA]: Call + grub_vga_cr_bw_read/grub_vga_cr_bw_write instead of + grub_vga_cr_read/grub_vga_cr_write. + (grub_vga_text_setcolorstate) [MODE_MDA]: Ignore color. + 2012-06-27 Vladimir Serbinenko * configure.ac: Bump version to 2.00. diff --git a/INSTALL b/INSTALL index e325fa2b2..39718ecde 100644 --- a/INSTALL +++ b/INSTALL @@ -12,6 +12,11 @@ you don't have any of them, please obtain and install them before configuring the GRUB. * GCC 4.1.3 or later + Note: older versions may work but support is limited + Note: clang 3.2 or later works for i386 and x86_64 targets but results in + much bigger binaries. + Note: clang 3.2 or later works for arm + Note: clang 3.4 or later works for powerpc * GNU Make * GNU Bison 2.3 or later * GNU gettext 0.17 or later @@ -23,11 +28,11 @@ On GNU/Linux, you also need: * libdevmapper 1.02.34 or later (recommended) -To build grub-emu, you need: +For optional grub-emu features, you need: -* ncurses -* libusb (recommended) * SDL (recommended) +* libpciaccess (optional) +* libusb (optional) To build GRUB's graphical terminal (gfxterm), you need: @@ -45,6 +50,7 @@ need the following. Prerequisites for make-check: * qemu, specifically the binary 'qemu-system-i386' +* xorriso 1.2.9 or later, for grub-mkrescue and grub-shell Configuring the GRUB ==================== @@ -75,9 +81,14 @@ Building the GRUB The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code. If - you don't use a release tarball you have to type `./autogen.sh'. - Type `./configure' to configure the package for your system. + 1. `cd' to the directory containing the package's source code. + + 2. Skip this and following step if you use release tarball and proceed to + step 4. If you want translations type `./linguas.sh'. + + 3. Type `./autogen.sh'. + + 4. Type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. @@ -85,15 +96,15 @@ The simplest way to compile this package is: Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. - 2. Type `make' to compile the package. + 6. Type `make' to compile the package. - 3. Optionally, type `make check' to run any self-tests that come with + 7. Optionally, type `make check' to run any self-tests that come with the package. - 4. Type `make install' to install the programs and any data files and + 8. Type `make install' to install the programs and any data files and documentation. - 5. You can remove the program binaries and object files from the + 9. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is @@ -102,6 +113,87 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. +Cross-compiling the GRUB +======================== + +GRUB defines 3 platforms: + + - "Build" is the one which build systems runs on. + - "Host" is where you execute GRUB utils. + - "Target" is where GRUB itself runs. + +For grub-emu host and target must be the same but may differ from build. + +If build and host are different make check isn't available. + +If build and host are different man pages are not generated. + +As an example imagine you have a build system running on FreeBSD on sparc +which prepares packages for developpers running amd64 GNU/Linux laptop and +they need to make images for ARM board running U-boot. In this case: + +build=sparc64-freebsd +host=amd64-linux-gnu +target=arm-uboot + +For this example the configure line might look like (more details below) +(some options are optional and included here for completeness but some rarely +used options are omited): + +./configure BUILD_CC=gcc BUILD_FREETYPE=freetype-config --host=amd64-linux-gnu +CC=amd64-linux-gnu-gcc CFLAGS="-g -O2" FREETYPE=amd64-linux-gnu-freetype-config +--target=arm --with-platform=uboot TARGET_CC=arm-elf-gcc +TARGET_CFLAGS="-Os -march=armv6" TARGET_CCASFLAGS="-march=armv6" +TARGET_OBJCOPY="arm-elf-objcopy" TARGET_STRIP="arm-elf-strip" +TARGET_NM=arm-elf-nm TARGET_RANLIB=arm-elf-ranlib LEX=gflex + +You need to use following options to specify tools and platforms. For minimum +version look at prerequisites. All tools not mentioned in this section under +corresponding platform are not needed for the platform in question. + + - For build + 1. BUILD_CC= to gcc able to compile for build. This is used, for + example, to compile build-gentrigtables which is then run to + generate sin and cos tables. + 2. BUILD_CFLAGS= for C options for build. + 3. BUILD_CPPFLAGS= for C preprocessor options for build. + 4. BUILD_FREETYPE= for freetype-config for build (optional). + + - For host + 1. --host= to autoconf name of host. + 2. CC= for gcc able to compile for host + 3. CFLAGS= for C options for host. + 4. CPPFLAGS= for C preprocessor options for host. + 5. LDFLAGS= for linker options for host. + 6. FREETYPE= for freetype-config for host (optional). + 7. Libdevmapper if any must be in standard linker folders (-ldevmapper) (optional). + 8. Libfuse if any must be in standard linker folders (-lfuse) (optional). + 9. Libzfs if any must be in standard linker folders (-lzfs) (optional). + 10. Liblzma if any must be in standard linker folders (-llzma) (optional). + + - For target + 1. --target= to autoconf cpu name of target. + 2. --with-platform to choose firmware. + 3. TARGET_CC= for gcc able to compile for target + 4. TARGET_CFLAGS= for C options for target. + 5. TARGET_CPPFLAGS= for C preprocessor options for target. + 6. TARGET_CCASFLAGS= for assembler options for target. + 7. TARGET_LDFLAGS= for linker options for target. + 8. TARGET_OBJCOPY= for objcopy for target. + 9. TARGET_STRIP= for strip for target. + 10. TARGET_NM= for nm for target. + 11. TARGET_RANLIB= for ranlib for target. + + - Additionally for emu, for host and target. + 1. SDL is looked for in stadard linker directories (-lSDL) (optional) + 2. libpciaccess is looked for in stadard linker directories (-lpciaccess) (optional) + 3. libusb is looked for in stadard linker directories (-lusb) (optional) + + - Platform-agnostic tools and data. + 1. make is the tool you execute after ./configure. + 2. Bison is specified in YACC= variable + 3. Flex is specified in LEX= variable + 4. GNU unifont and Djvu sans are looked for in standard directories. Compiling For Multiple Architectures ==================================== diff --git a/Makefile.am b/Makefile.am index db9e930ff..3b5c0e48e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,63 +60,65 @@ grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) CLEANFILES += grub_fstest_init.c -if COND_GRUB_MKFONT if COND_HAVE_FONT_SOURCE pkgdata_DATA += unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h endif -endif starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0 +build-grub-mkfont: util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs) +CLEANFILES += build-grub-mkfont + +build-grub-gen-asciih: util/grub-gen-asciih.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror +CLEANFILES += build-grub-gen-asciih + +build-grub-gen-widthspec: util/grub-gen-widthspec.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror +CLEANFILES += build-grub-gen-widthspec + if COND_STARFIELD starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files) -dejavu_10.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 10 -o $@ $(DJVU_FONT_SOURCE) -dejavu_12.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 12 -o $@ $(DJVU_FONT_SOURCE) -dejavu_14.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 14 -o $@ $(DJVU_FONT_SOURCE) -dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -b -s 14 -o $@ $(DJVU_FONT_SOURCE) -dejavu_16.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 16 -o $@ $(DJVU_FONT_SOURCE) +dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont + ./build-grub-mkfont -s 10 -o $@ $(DJVU_FONT_SOURCE) +dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont + ./build-grub-mkfont -s 12 -o $@ $(DJVU_FONT_SOURCE) +dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont + ./build-grub-mkfont -s 14 -o $@ $(DJVU_FONT_SOURCE) +dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont + ./build-grub-mkfont -b -s 14 -o $@ $(DJVU_FONT_SOURCE) +dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont + ./build-grub-mkfont -s 16 -o $@ $(DJVU_FONT_SOURCE) else -starfield_DATA = +starfield_DATA = endif EXTRA_DIST += $(starfield_theme_files) EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf -unicode.pf2: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) +unicode.pf2: $(FONT_SOURCE) build-grub-mkfont + ./build-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) +ascii.pf2: $(FONT_SOURCE) build-grub-mkfont + ./build-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) +euro.pf2: $(FONT_SOURCE) build-grub-mkfont + ./build-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: $(FONT_SOURCE) build-grub-gen-asciih + ./build-grub-gen-asciih $(FONT_SOURCE) $@ +CLEANFILES += ascii.h -ascii.h: ascii.bitmaps grub-bin2h - $(builddir)/grub-bin2h ascii_bitmaps < $< > $@ -CLEANFILES += ascii.h $(top_builddir)/grub-core/include/ascii.h - -widthspec.bin: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont --width-spec -o $@ $(FONT_SOURCE) -CLEANFILES += widthspec.bin - -widthspec.h: widthspec.bin grub-bin2h - $(builddir)/grub-bin2h widthspec < $< > $@ +widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec + ./build-grub-gen-widthspec $(FONT_SOURCE) $@ CLEANFILES += widthspec.h # Install config.h into platformdir @@ -153,10 +155,10 @@ if COND_x86_64_efi QEMU32=qemu-system-x86_64 endif -linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S +linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S +linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.mips: $(srcdir)/grub-core/tests/boot/linux.init-mips.S @@ -171,46 +173,46 @@ linux.init.mipsel: $(srcdir)/grub-core/tests/boot/linux.init-mips.S linux.init.loongson: $(srcdir)/grub-core/tests/boot/linux.init-mips.S $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1 -multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S +multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S +kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include kfreebsd.aout: kfreebsd.elf - $(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id -R .note.gnu.gold-version + $(TARGET_OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id -R .note.gnu.gold-version -pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S +pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32 pc-chainloader.bin: pc-chainloader.elf - $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; + $(TARGET_OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; -ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S +ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32 ntldr.bin: ntldr.elf - $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; + $(TARGET_OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; -multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S +multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1 -kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S +kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ -kfreebsd.init.i386: $(srcdir)/grub-core/tests/boot/kfreebsd.init-i386.S +kfreebsd.init.i386: $(srcdir)/grub-core/tests/boot/kfreebsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ -knetbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S +knetbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_NETBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -kopenbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S +kopenbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m32 -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 +knetbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m64 -DTARGET_NETBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -kopenbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S +kopenbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S $(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux-initramfs.mips: linux.init.mips Makefile @@ -244,7 +246,7 @@ kopenbsd.image.x86_64: kopenbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kopen TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@ knetbsd.miniroot-image.i386.img: knetbsd.image.i386 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 - $(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@ + $(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@ kfreebsd-mfsroot.x86_64.img: kfreebsd.init.x86_64 Makefile TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR @@ -253,7 +255,7 @@ knetbsd.image.x86_64: knetbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kbsd.sp TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR knetbsd.miniroot-image.x86_64.img: knetbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 - $(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@ + $(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@ CLEANFILES += linux.init.i386 kfreebsd.init.i386 linux.init.x86_64 linux-initramfs.i386 linux-initramfs.x86_64 @@ -261,70 +263,70 @@ kfreebsd-mfsroot.i386.gz: kfreebsd-mfsroot.i386.img gzip < $< > $@ bootcheck-kfreebsd-i386: kfreebsd-mfsroot.i386.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.i386 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null kfreebsd-mfsroot.x86_64.gz: kfreebsd-mfsroot.x86_64.img gzip < $< > $@ bootcheck-kfreebsd-x86_64: kfreebsd-mfsroot.x86_64.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null knetbsd.miniroot-image.i386.gz: knetbsd.miniroot-image.i386.img gzip < $< > $@ bootcheck-knetbsd-i386: knetbsd.miniroot-image.i386.gz $(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null knetbsd.miniroot-image.x86_64.gz: knetbsd.miniroot-image.x86_64.img gzip < $< > $@ bootcheck-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-mips: linux-initramfs.mips $(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.mips --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mips --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-ppc: linux-initramfs.ppc $(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.ppc --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux-ppc.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.ppc --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux-ppc.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-mipsel: linux-initramfs.mipsel $(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.mipsel --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mipsel --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-loongson: linux-initramfs.loongson $(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.loongson --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.loongson --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux16-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-multiboot: multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-multiboot2: multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null if COND_i386_efi BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 @@ -335,18 +337,17 @@ BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd- endif if COND_i386_multiboot -# Freebsd crashes because memory at 0-0x1000 is occupied and requires ACPI +# FreeBSD requires ACPI BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 endif if COND_i386_coreboot -# 64-bit NetBSD crashes because memory at 0-0x1000 is occupied -# Freebsd crashes because memory at 0-0x1000 is occupied and requires ACPI -BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 +# Freebsd requires ACPI +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 endif if COND_i386_qemu -# Freebsd crashes because memory at 0-0x1000 is occupied and requires ACPI +# FreeBSD requires ACPI BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 endif @@ -377,7 +378,7 @@ if COND_powerpc_ieee1275 BOOTCHECKS = bootcheck-linux-ppc endif -EXTRA_DIST += grub-core/tests/boot/kbsd.init-i386.S grub-core/tests/boot/kbsd.init-x86_64.S grub-core/tests/boot/kbsd.spec.txt grub-core/tests/boot/kernel-8086.S grub-core/tests/boot/kernel-i386.S grub-core/tests/boot/kfreebsd-aout.cfg grub-core/tests/boot/kfreebsd.cfg grub-core/tests/boot/kfreebsd.init-i386.S grub-core/tests/boot/kfreebsd.init-x86_64.S grub-core/tests/boot/knetbsd.cfg grub-core/tests/boot/kopenbsd.cfg grub-core/tests/boot/kopenbsdlabel.txt grub-core/tests/boot/linux16.cfg grub-core/tests/boot/linux.cfg grub-core/tests/boot/linux.init-i386.S grub-core/tests/boot/linux.init-x86_64.S grub-core/tests/boot/multiboot2.cfg grub-core/tests/boot/multiboot.cfg grub-core/tests/boot/ntldr.cfg grub-core/tests/boot/pc-chainloader.cfg +EXTRA_DIST += grub-core/tests/boot/kbsd.init-i386.S grub-core/tests/boot/kbsd.init-x86_64.S grub-core/tests/boot/kbsd.spec.txt grub-core/tests/boot/kernel-8086.S grub-core/tests/boot/kernel-i386.S grub-core/tests/boot/kfreebsd-aout.cfg grub-core/tests/boot/kfreebsd.cfg grub-core/tests/boot/kfreebsd.init-i386.S grub-core/tests/boot/kfreebsd.init-x86_64.S grub-core/tests/boot/knetbsd.cfg grub-core/tests/boot/kopenbsd.cfg grub-core/tests/boot/kopenbsdlabel.txt grub-core/tests/boot/linux16.cfg grub-core/tests/boot/linux.cfg grub-core/tests/boot/linux.init-i386.S grub-core/tests/boot/linux.init-mips.S grub-core/tests/boot/linux.init-ppc.S grub-core/tests/boot/linux.init-x86_64.S grub-core/tests/boot/linux-ppc.cfg grub-core/tests/boot/multiboot2.cfg grub-core/tests/boot/multiboot.cfg grub-core/tests/boot/ntldr.cfg grub-core/tests/boot/pc-chainloader.cfg grub-core/tests/boot/qemu-shutdown-x86.S .PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64 \ bootcheck-kfreebsd-i386 bootcheck-kfreebsd-x86_64 \ @@ -390,3 +391,11 @@ SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d BOOTCHECK_TIMEOUT=180 bootcheck: $(BOOTCHECKS) + +if COND_i386_coreboot +default_payload.elf: grub-mkstandalone grub-mkimage + pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci ehci usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump setpci lsacpi chain' --fonts= --themes= --locales= -d grub-core/ +endif + + +EXTRA_DIST += linguas.sh diff --git a/Makefile.util.def b/Makefile.util.def index cbac10c8c..222582214 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -9,9 +9,23 @@ library = { common = grub-core/kern/command.c; common = grub-core/kern/device.c; common = grub-core/kern/disk.c; + common = grub-core/lib/disk.c; common = util/getroot.c; - common = util/raid.c; + common = grub-core/osdep/unix/getroot.c; + common = grub-core/osdep/getroot.c; + common = grub-core/osdep/devmapper/getroot.c; + common = grub-core/osdep/relpath.c; + extra_dist = grub-core/kern/disk_common.c; + extra_dist = grub-core/osdep/unix/relpath.c; + extra_dist = grub-core/osdep/aros/relpath.c; + extra_dist = grub-core/osdep/windows/relpath.c; common = grub-core/kern/emu/hostdisk.c; + common = grub-core/osdep/devmapper/hostdisk.c; + common = grub-core/osdep/hostdisk.c; + common = grub-core/osdep/unix/hostdisk.c; + common = grub-core/osdep/exec.c; + common = grub-core/osdep/sleep.c; + common = grub-core/osdep/password.c; common = grub-core/kern/emu/misc.c; common = grub-core/kern/emu/mm.c; common = grub-core/kern/env.c; @@ -32,11 +46,13 @@ library = { common = grub-core/disk/ldm.c; common = grub-core/disk/diskfilter.c; common = grub-core/partmap/gpt.c; + common = grub-core/partmap/msdos.c; + common = grub-core/fs/proc.c; }; library = { name = libgrubmods.a; - cflags = '$(CFLAGS_POSIX) -Wno-undef -Wno-error=missing-noreturn'; + cflags = '-fno-builtin -Wno-undef'; cppflags = '-I$(top_srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -DMINILZO_HAVE_CONFIG_H'; common_nodist = grub_script.tab.c; @@ -57,10 +73,24 @@ library = { common = grub-core/disk/mdraid1x_linux.c; common = grub-core/disk/raid5_recover.c; common = grub-core/disk/raid6_recover.c; + common = grub-core/font/font.c; + common = grub-core/gfxmenu/font.c; + common = grub-core/normal/charset.c; + common = grub-core/video/fb/fbblit.c; + common = grub-core/video/fb/fbutil.c; + common = grub-core/video/fb/fbfill.c; + common = grub-core/video/fb/video_fb.c; + common = grub-core/video/video.c; + common = grub-core/video/capture.c; + common = grub-core/video/colors.c; + common = grub-core/unidata.c; + common = grub-core/io/bufio.c; common = grub-core/fs/affs.c; common = grub-core/fs/afs.c; common = grub-core/fs/bfs.c; common = grub-core/fs/btrfs.c; + common = grub-core/fs/cbfs.c; + common = grub-core/fs/archelp.c; common = grub-core/fs/cpio.c; common = grub-core/fs/cpio_be.c; common = grub-core/fs/odc.c; @@ -71,6 +101,7 @@ library = { common = grub-core/fs/fshelp.c; common = grub-core/fs/hfs.c; common = grub-core/fs/hfsplus.c; + common = grub-core/fs/hfspluscomp.c; common = grub-core/fs/iso9660.c; common = grub-core/fs/jfs.c; common = grub-core/fs/minix.c; @@ -90,11 +121,13 @@ library = { common = grub-core/fs/udf.c; common = grub-core/fs/ufs2.c; common = grub-core/fs/ufs.c; + common = grub-core/fs/ufs_be.c; common = grub-core/fs/xfs.c; common = grub-core/fs/zfs/zfscrypt.c; common = grub-core/fs/zfs/zfs.c; common = grub-core/fs/zfs/zfsinfo.c; common = grub-core/fs/zfs/zfs_lzjb.c; + common = grub-core/fs/zfs/zfs_lz4.c; common = grub-core/fs/zfs/zfs_sha256.c; common = grub-core/fs/zfs/zfs_fletcher.c; common = grub-core/lib/envblk.c; @@ -109,12 +142,12 @@ library = { common = grub-core/partmap/acorn.c; common = grub-core/partmap/amiga.c; common = grub-core/partmap/apple.c; - common = grub-core/partmap/msdos.c; common = grub-core/partmap/sun.c; common = grub-core/partmap/plan.c; common = grub-core/partmap/dvh.c; common = grub-core/partmap/sunpc.c; common = grub-core/partmap/bsdlabel.c; + common = grub-core/partmap/dfly.c; common = grub-core/script/function.c; common = grub-core/script/lexer.c; common = grub-core/script/main.c; @@ -129,24 +162,17 @@ library = { common = grub-core/lib/xzembed/xz_dec_stream.c; }; -program = { - name = grub-bin2h; - common = util/bin2h.c; - ldadd = libgrubmods.a; - ldadd = libgrubgcry.a; - ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; - installdir = noinst; -}; - program = { name = grub-mkimage; mansection = 1; common = util/grub-mkimage.c; + common = util/mkimage.c; common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + common = grub-core/kern/arm/dl_helper.c; extra_dist = util/grub-mkimagexx.c; @@ -165,6 +191,7 @@ program = { common = util/grub-mkrelpath.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -179,6 +206,7 @@ program = { common = util/grub-script-check.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -192,6 +220,8 @@ program = { mansection = 1; common = util/grub-editenv.c; + common = util/editenv.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -206,14 +236,14 @@ program = { common = util/grub-mkpasswd-pbkdf2.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cflags = '$(CFLAGS_GCRY)'; - cppflags = '$(CPPFLAGS_GCRY)'; }; program = { @@ -223,19 +253,6 @@ program = { condition = COND_APPLE_CC; }; -program = { - name = grub-pe2elf; - mansection = 1; - common = util/grub-pe2elf.c; - - ldadd = libgrubmods.a; - ldadd = libgrubgcry.a; - ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL)'; - condition = COND_GRUB_PE2ELF; -}; - program = { name = grub-fstest; mansection = 1; @@ -243,9 +260,7 @@ program = { common = util/grub-fstest.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; - - cflags = '$(CFLAGS_GCRY)'; - cppflags = '$(CPPFLAGS_GCRY)'; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -261,6 +276,7 @@ program = { common = util/grub-mount.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -274,10 +290,11 @@ program = { name = grub-mkfont; mansection = 1; common = util/grub-mkfont.c; - common = grub-core/unidata.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; cflags = '$(freetype_cflags)'; + cppflags = '-DGRUB_MKFONT=1'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -309,8 +326,9 @@ program = { installdir = sbin; mansection = 8; common = util/grub-probe.c; - common = util/ieee1275/ofpath.c; + common = grub-core/osdep/ofpath.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -324,16 +342,22 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/lvm.c; + common = util/setup_bios.c; + extra_dist = util/setup.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/blocklist.c; + extra_dist = grub-core/osdep/generic/blocklist.c; + extra_dist = grub-core/osdep/linux/blocklist.c; + extra_dist = grub-core/osdep/windows/blocklist.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_SETUP_BIOS=1'; + cppflags = '-DGRUB_SETUP_FUNC=grub_util_bios_setup'; }; program = { @@ -341,17 +365,19 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/lvm.c; + common = util/setup_sparc.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/lib/reed_solomon.c; - common = util/ieee1275/ofpath.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_SETUP_SPARC64=1'; + cppflags = '-DGRUB_SETUP_FUNC=grub_util_sparc_setup'; }; program = { @@ -359,7 +385,8 @@ program = { installdir = sbin; mansection = 8; common = util/ieee1275/grub-ofpathname.c; - common = util/ieee1275/ofpath.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -374,6 +401,7 @@ program = { common = util/grub-mklayout.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -476,26 +504,15 @@ script = { script = { mansection = 1; name = grub-mkrescue; - x86 = util/grub-mkrescue.in; - mips_qemu_mips = util/grub-mkrescue.in; - mips_loongson = util/grub-mkrescue.in; - ia64_efi = util/grub-mkrescue.in; - powerpc_ieee1275 = util/powerpc/ieee1275/grub-mkrescue.in; - enable = i386_pc; - enable = i386_efi; - enable = x86_64_efi; - enable = i386_qemu; - enable = i386_multiboot; - enable = i386_coreboot; - enable = mips_qemu_mips; - enable = mips_loongson; - enable = ia64_efi; - enable = powerpc_ieee1275; + common = util/grub-install_header; + common = util/grub-mkrescue.in; + enable = noemu; }; script = { mansection = 1; name = grub-mkstandalone; + common = util/grub-install_header; common = util/grub-mkstandalone.in; }; @@ -504,15 +521,17 @@ script = { installdir = sbin; name = grub-install; + common = util/grub-install_header; common = util/grub-install.in; enable = noemu; }; script = { - mansection = 8; - installdir = sbin; + mansection = 1; + installdir = bin; name = grub-mknetdir; + common = util/grub-install_header; common = util/grub-mknetdir.in; }; @@ -567,12 +586,61 @@ script = { common = tests/example_scripted_test.in; }; +script = { + testcase; + name = gettext_strings_test; + common = tests/gettext_strings_test.in; + extra_dist = po/exclude.pot; +}; + +script = { + testcase; + name = pata_test; + common = tests/pata_test.in; +}; + +script = { + testcase; + name = ahci_test; + common = tests/ahci_test.in; +}; + +script = { + testcase; + name = uhci_test; + common = tests/uhci_test.in; +}; + +script = { + testcase; + name = ohci_test; + common = tests/ohci_test.in; +}; + +script = { + testcase; + name = ehci_test; + common = tests/ehci_test.in; +}; + script = { testcase; name = example_grub_script_test; common = tests/example_grub_script_test.in; }; +script = { + testcase; + name = grub_script_eval; + common = tests/grub_script_eval.in; +}; + +script = { + testcase; + name = grub_script_test; + common = tests/grub_script_test.in; +}; + script = { testcase; name = grub_script_echo1; @@ -687,6 +755,24 @@ script = { common = tests/grub_cmd_regexp.in; }; +script = { + testcase; + name = grub_cmd_date; + common = tests/grub_cmd_date.in; +}; + +script = { + testcase; + name = grub_cmd_set_date; + common = tests/grub_cmd_set_date.in; +}; + +script = { + testcase; + name = grub_cmd_sleep; + common = tests/grub_cmd_sleep.in; +}; + script = { testcase; name = grub_script_expansion; @@ -711,24 +797,114 @@ script = { common = tests/partmap_test.in; }; +script = { + testcase; + name = hddboot_test; + common = tests/hddboot_test.in; +}; + +script = { + testcase; + name = fddboot_test; + common = tests/fddboot_test.in; +}; + +script = { + testcase; + name = cdboot_test; + common = tests/cdboot_test.in; +}; + +script = { + testcase; + name = netboot_test; + common = tests/netboot_test.in; +}; + +script = { + testcase; + name = pseries_test; + common = tests/pseries_test.in; +}; + +script = { + testcase; + name = core_compress_test; + common = tests/core_compress_test.in; +}; + +script = { + testcase; + name = xzcompress_test; + common = tests/xzcompress_test.in; +}; + +script = { + testcase; + name = gzcompress_test; + common = tests/gzcompress_test.in; +}; + +script = { + testcase; + name = lzocompress_test; + common = tests/lzocompress_test.in; +}; + script = { testcase; name = grub_cmd_echo; common = tests/grub_cmd_echo.in; }; +script = { + testcase; + name = help_test; + common = tests/help_test.in; +}; + script = { testcase; name = grub_script_gettext; common = tests/grub_script_gettext.in; }; +script = { + testcase; + name = grub_script_escape_comma; + common = tests/grub_script_escape_comma.in; +}; + script = { testcase; name = grub_script_strcmp; common = tests/grub_script_strcmp.in; }; +script = { + testcase; + name = test_sha512sum; + common = tests/test_sha512sum.in; +}; + +script = { + testcase; + name = test_unset; + common = tests/test_unset.in; +}; + +script = { + testcase; + name = grub_func_test; + common = tests/grub_func_test.in; +}; + +script = { + testcase; + name = grub_cmd_tr; + common = tests/grub_cmd_tr.in; +}; + program = { testcase; name = example_unit_test; @@ -759,6 +935,38 @@ program = { ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; +program = { + testcase; + name = date_test; + common = tests/date_unit_test.c; + common = tests/lib/unit_test.c; + common = grub-core/kern/list.c; + common = grub-core/kern/misc.c; + common = grub-core/tests/lib/test.c; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + testcase; + name = priority_queue_unit_test; + common = tests/priority_queue_unit_test.cc; + common = tests/lib/unit_test.c; + common = grub-core/kern/list.c; + common = grub-core/kern/misc.c; + common = grub-core/tests/lib/test.c; + common = grub-core/lib/priority_queue.c; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + condition = COND_HAVE_CXX; +}; + program = { testcase; name = cmp_test; @@ -780,6 +988,41 @@ program = { common = util/grub-menulst2cfg.c; common = grub-core/lib/legacy_parse.c; common = grub-core/lib/i386/pc/vesa_modes_table.c; + common = grub-core/osdep/init.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + name = grub-glue-efi; + mansection = 1; + + common = util/grub-glue-efi.c; + common = util/glue-efi.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + name = grub-render-label; + mansection = 1; + + common = util/grub-render-label.c; + common = util/render-label.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; diff --git a/NEWS b/NEWS index f9b06ab48..4bb5f9801 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ New in 2.00: -* Appearence: +* Appearance: * Official theme for gfxmenu (starfield) * Menu is organised with submenus. * Better default video mode selection using EDID. diff --git a/acinclude.m4 b/acinclude.m4 index 0eb2e2a17..ecbde9594 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -74,7 +74,7 @@ AC_MSG_RESULT([$grub_cv_asm_uscore]) dnl Some versions of `objcopy -O binary' vary their output depending dnl on the link address. AC_DEFUN([grub_PROG_OBJCOPY_ABSOLUTE], -[AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses]) +[AC_MSG_CHECKING([whether ${TARGET_OBJCOPY} works for absolute addresses]) AC_CACHE_VAL(grub_cv_prog_objcopy_absolute, [cat > conftest.c <<\EOF void cmain (void); @@ -95,9 +95,9 @@ for link_addr in 0x2000 0x8000 0x7C00; do else AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) fi - if AC_TRY_COMMAND([${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : + if AC_TRY_COMMAND([${TARGET_OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : else - AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files]) + AC_MSG_ERROR([${TARGET_OBJCOPY-objcopy} cannot create binary files]) fi if test ! -f conftest.old || AC_TRY_COMMAND([cmp -s conftest.old conftest]); then mv -f conftest conftest.old @@ -134,6 +134,54 @@ if test "x$grub_cv_prog_ld_build_id_none" = xyes; then fi ]) +dnl Supply -P to nm +AC_DEFUN([grub_PROG_NM_MINUS_P], +[AC_MSG_CHECKING([whether nm accepts -P]) +AC_CACHE_VAL(grub_cv_prog_nm_minus_p, +[ +nm_minus_p_tmp_dir="$(mktemp -d "./confXXXXXX")" +AC_LANG_CONFTEST([AC_LANG_PROGRAM([[]], [[]])]) +$TARGET_CC conftest.c -o "$nm_minus_p_tmp_dir/ef" +if $TARGET_NM -P "$nm_minus_p_tmp_dir/ef" 2>&1 > /dev/null; then + grub_cv_prog_nm_minus_p=yes +else + grub_cv_prog_nm_minus_p=no +fi +rm "$nm_minus_p_tmp_dir/ef" +]) +AC_MSG_RESULT([$grub_cv_prog_nm_minus_p]) + +if test "x$grub_cv_prog_nm_minus_p" = xyes; then + TARGET_NMFLAGS_MINUS_P="-P" +else + TARGET_NMFLAGS_MINUS_P= +fi +]) + +dnl Supply --defined-only to nm +AC_DEFUN([grub_PROG_NM_DEFINED_ONLY], +[AC_MSG_CHECKING([whether nm accepts --defined-only]) +AC_CACHE_VAL(grub_cv_prog_nm_defined_only, +[ +nm_defined_only_tmp_dir="$(mktemp -d "./confXXXXXX")" +AC_LANG_CONFTEST([AC_LANG_PROGRAM([[]], [[]])]) +$TARGET_CC conftest.c -o "$nm_defined_only_tmp_dir/ef" +if $TARGET_NM --defined-only "$nm_defined_only_tmp_dir/ef" 2>&1 > /dev/null; then + grub_cv_prog_nm_defined_only=yes +else + grub_cv_prog_nm_defined_only=no +fi +rm "$nm_defined_only_tmp_dir/ef" +]) +AC_MSG_RESULT([$grub_cv_prog_nm_defined_only]) + +if test "x$grub_cv_prog_nm_defined_only" = xyes; then + TARGET_NMFLAGS_DEFINED_ONLY=--defined-only +else + TARGET_NMFLAGS_DEFINED_ONLY= +fi +]) + dnl Mass confusion! dnl Older versions of GAS interpret `.code16' to mean ``generate 32-bit @@ -164,7 +212,7 @@ else sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s fi -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then +if AC_TRY_COMMAND([${CC-cc} ${TARGET_CCASFLAGS} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then grub_cv_i386_asm_addr32=yes else grub_cv_i386_asm_addr32=no @@ -174,21 +222,6 @@ rm -f conftest*]) AC_MSG_RESULT([$grub_cv_i386_asm_addr32])]) -dnl check if our compiler is apple cc -dnl because it requires numerous workarounds -AC_DEFUN([grub_apple_cc], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING([whether our compiler is apple cc]) -AC_CACHE_VAL(grub_cv_apple_cc, -[if $CC -v 2>&1 | grep "Apple Inc." > /dev/null; then - grub_cv_apple_cc=yes -else - grub_cv_apple_cc=no -fi -]) - -AC_MSG_RESULT([$grub_cv_apple_cc])]) - dnl check if our target compiler is apple cc dnl because it requires numerous workarounds AC_DEFUN([grub_apple_target_cc], @@ -218,7 +251,7 @@ AC_CACHE_VAL(grub_cv_i386_asm_prefix_requirement, l1: addr32 movb %al, l1 EOF -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then +if AC_TRY_COMMAND([${CC-cc} ${TARGET_CCASFLAGS} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then grub_cv_i386_asm_prefix_requirement=yes else grub_cv_i386_asm_prefix_requirement=no @@ -313,32 +346,6 @@ else fi ]) -dnl Check if the C compiler generates calls to `__enable_execute_stack()'. -AC_DEFUN([grub_CHECK_ENABLE_EXECUTE_STACK],[ -AC_MSG_CHECKING([whether `$CC' generates calls to `__enable_execute_stack()']) -AC_LANG_CONFTEST([AC_LANG_SOURCE([[ -void f (int (*p) (void)); -void g (int i) -{ - int nestedfunc (void) { return i; } - f (nestedfunc); -} -]])]) -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then - true -else - AC_MSG_ERROR([${CC-cc} failed to produce assembly code]) -fi -if grep __enable_execute_stack conftest.s >/dev/null 2>&1; then - NEED_ENABLE_EXECUTE_STACK=1 - AC_MSG_RESULT([yes]) -else - NEED_ENABLE_EXECUTE_STACK=0 - AC_MSG_RESULT([no]) -fi -rm -f conftest* -]) - dnl Check if the C compiler supports `-fstack-protector'. AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[ @@ -369,7 +376,7 @@ AC_MSG_CHECKING([whether `$CC' accepts `-mstack-arg-probe']) AC_LANG_CONFTEST([AC_LANG_SOURCE([[ void foo (void) { volatile char a[8]; a[3]; } ]])]) -[if eval "$ac_compile -S -mstack-arg-probe -o conftest.s" 2> /dev/null; then] +[if eval "$ac_compile -S -mstack-arg-probe -Werror -o conftest.s" 2> /dev/null; then] AC_MSG_RESULT([yes]) [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'? rm -f conftest.s @@ -452,3 +459,29 @@ else AC_MSG_RESULT([no]) [fi] ]) + +dnl Create an output variable with the transformed name of a GRUB utility +dnl program. +AC_DEFUN([grub_TRANSFORM],[dnl +AC_SUBST(AS_TR_SH([$1]), [`AS_ECHO([$1]) | sed "$program_transform_name"`])dnl +]) + +dnl Check if the C compiler supports `-mno-unaligned-access'. +AC_DEFUN([grub_CHECK_NO_UNALIGNED_ACCESS],[ +[# foobar +nua_possible=yes] +AC_MSG_CHECKING([whether `$CC' supports `-mno-unaligned-access']) +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +int main() { + return 0; +} +]])]) + +[if eval "$ac_compile -S -mno-unaligned-access -o conftest.s" 2> /dev/null; then] + AC_MSG_RESULT([yes]) + [rm -f conftest.s +else + nua_possible=no] + AC_MSG_RESULT([no]) +[fi] +]) diff --git a/autogen.sh b/autogen.sh index db719cd1d..10fe68fb9 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,10 +2,12 @@ set -e -export LC_CTYPE=C export LC_COLLATE=C unset LC_ALL +find . -iname '*.[ch]' ! -ipath './grub-core/lib/libgcrypt-grub/*' ! -ipath './build-aux/*' ! -ipath './grub-core/lib/libgcrypt/src/misc.c' ! -ipath './grub-core/lib/libgcrypt/src/global.c' ! -ipath './grub-core/lib/libgcrypt/src/secmem.c' ! -ipath './util/grub-gen-widthspec.c' ! -ipath './util/grub-gen-asciih.c' |sort > po/POTFILES.in +find util -iname '*.in' ! -name Makefile.in |sort > po/POTFILES-shell.in + autogen --version >/dev/null || exit 1 echo "Importing unicode..." @@ -13,6 +15,22 @@ python util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt echo "Importing libgcrypt..." python util/import_gcry.py grub-core/lib/libgcrypt/ grub-core +sed -n -f util/import_gcrypth.sed < grub-core/lib/libgcrypt/src/gcrypt.h.in > include/grub/gcrypt/gcrypt.h +if [ -f include/grub/gcrypt/g10lib.h ]; then + rm include/grub/gcrypt/g10lib.h +fi +if [ -d grub-core/lib/libgcrypt-grub/mpi/generic ]; then + rm -rf grub-core/lib/libgcrypt-grub/mpi/generic +fi +ln -s ../../../grub-core/lib/libgcrypt-grub/src/g10lib.h include/grub/gcrypt/g10lib.h +cp -R grub-core/lib/libgcrypt/mpi/generic grub-core/lib/libgcrypt-grub/mpi/generic + +for x in mpi-asm-defs.h mpih-add1.c mpih-sub1.c mpih-mul1.c mpih-mul2.c mpih-mul3.c mpih-lshift.c mpih-rshift.c; do + if [ -h grub-core/lib/libgcrypt-grub/mpi/"$x" ] || [ -f grub-core/lib/libgcrypt-grub/mpi/"$x" ]; then + rm grub-core/lib/libgcrypt-grub/mpi/"$x" + fi + ln -s generic/"$x" grub-core/lib/libgcrypt-grub/mpi/"$x" +done echo "Creating Makefile.tpl..." python gentpl.py | sed -e '/^$/{N;/^\n$/D;}' > Makefile.tpl diff --git a/build-aux/config.rpath b/build-aux/config.rpath index c492a93b6..c38b914d6 100755 --- a/build-aux/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-2006 Free Software Foundation, Inc. +# Copyright 1996-2013 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # @@ -25,7 +25,7 @@ # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so @@ -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 AC_LIBTOOL_PROG_COMPILER_PIC. +# Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then @@ -57,14 +57,7 @@ else aix*) wl='-Wl,' ;; - darwin*) - case $cc_basename in - xlc*) - wl='-Wl,' - ;; - esac - ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' @@ -72,24 +65,37 @@ else irix5* | irix6* | nonstopux*) wl='-Wl,' ;; - newsos6) - ;; - linux*) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in - icc* | ecc*) + ecc*) wl='-Wl,' ;; - pgcc | pgf77 | pgf90) + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; *Sun\ C*) wl='-Wl,' ;; @@ -97,22 +103,36 @@ else ;; esac ;; + newsos6) + ;; + *nto* | *qnx*) + ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; - sco3.2v5*) + rdos*) ;; solaris*) - wl='-Wl,' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac ;; sunos4*) wl='-Qoption ld ' ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; unicos*) wl='-Wl,' ;; @@ -121,7 +141,7 @@ else esac fi -# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= @@ -129,7 +149,7 @@ hardcode_direct=no hardcode_minus_L=no case "$host_os" in - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # 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++. @@ -155,22 +175,21 @@ 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 - aix3* | aix4* | aix5*) + aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we cannot use - # them. - ld_shlibs=no + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then @@ -179,7 +198,7 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no fi ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' @@ -189,11 +208,13 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no fi ;; - interix3*) + haiku*) + ;; + interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; - linux*) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else @@ -251,7 +272,7 @@ else hardcode_direct=unsupported fi ;; - aix4* | aix5*) + aix[4-9]*) 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. @@ -261,7 +282,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].*|aix5*) + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes @@ -280,7 +301,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 @@ -316,14 +337,18 @@ else fi ;; amigaos*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac ;; bsdi[45]*) ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is @@ -333,24 +358,15 @@ else ;; darwin* | rhapsody*) hardcode_direct=no - if test "$GCC" = yes ; then + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then : else - case $cc_basename in - xlc*) - ;; - *) - ld_shlibs=no - ;; - esac + ld_shlibs=no fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; - freebsd1*) - ld_shlibs=no - ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -359,7 +375,7 @@ else hardcode_direct=yes hardcode_minus_L=yes ;; - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; @@ -411,19 +427,25 @@ else hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; + *nto* | *qnx*) + ;; openbsd*) - hardcode_direct=yes - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + 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 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 + ld_shlibs=no fi ;; os2*) @@ -471,7 +493,7 @@ else ld_shlibs=yes fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' @@ -487,34 +509,58 @@ else fi # Check dynamic linker characteristics -# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. +# 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 libname_spec='lib$name' case "$host_os" in aix3*) + library_names_spec='$libname.a' ;; - aix4* | aix5*) + aix[4-9]*) + library_names_spec='$libname$shrext' ;; amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac ;; beos*) + library_names_spec='$libname$shrext' ;; bsdi[45]*) + library_names_spec='$libname$shrext' ;; - cygwin* | mingw* | pw32*) + cygwin* | mingw* | pw32* | cegcc*) shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib + library_names_spec='$libname$shrext' ;; dgux*) - ;; - freebsd1*) - ;; - kfreebsd*-gnu) + library_names_spec='$libname$shrext' ;; 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' + ;; + haiku*) + library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in @@ -528,10 +574,13 @@ case "$host_os" in shrext=.sl ;; esac + library_names_spec='$libname$shrext' ;; - interix3*) + interix[3-9]*) + library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= @@ -548,41 +597,62 @@ case "$host_os" in ;; linux*oldld* | linux*aout* | linux*coff*) ;; - linux*) + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' ;; knetbsd*-gnu) + library_names_spec='$libname$shrext' ;; netbsd*) + library_names_spec='$libname$shrext' ;; newsos6) + library_names_spec='$libname$shrext' ;; - nto-qnx*) + *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' + ;; + tpf*) + 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=/' <. */ diff --git a/build-aux/c++defs.h b/build-aux/snippet/c++defs.h similarity index 99% rename from build-aux/c++defs.h rename to build-aux/snippet/c++defs.h index 0c2fad7a2..b35b933cd 100644 --- a/build-aux/c++defs.h +++ b/build-aux/snippet/c++defs.h @@ -1,5 +1,5 @@ /* C++ compatible function declaration macros. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -9,7 +9,7 @@ This program is distributed in the hope that 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. + 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 . */ diff --git a/build-aux/warn-on-use.h b/build-aux/snippet/warn-on-use.h similarity index 96% rename from build-aux/warn-on-use.h rename to build-aux/snippet/warn-on-use.h index 171e59916..1736a1bd7 100644 --- a/build-aux/warn-on-use.h +++ b/build-aux/snippet/warn-on-use.h @@ -1,5 +1,5 @@ /* A C macro for emitting warnings if a function is used. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -9,7 +9,7 @@ This program is distributed in the hope that 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. + 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 . */ @@ -55,7 +55,7 @@ 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; } + static char ***rpl_environ (void) { return &environ; } _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); # undef environ # define environ (*rpl_environ ()) diff --git a/conf/Makefile.common b/conf/Makefile.common index b5615a14b..39d2f4d60 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -3,40 +3,29 @@ CFLAGS_PLATFORM= export LC_COLLATE := C -export LC_CTYPE := C unexport LC_ALL # Platform specific options -if COND_i386_pc - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_i386_efi - LDFLAGS_PLATFORM = -Wl,-melf_i386 -endif -if COND_x86_64_efi - LDFLAGS_PLATFORM = -Wl,-melf_x86_64 -endif -if COND_i386_qemu - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_i386_coreboot - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_i386_ieee1275 - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif if COND_mips_loongson CFLAGS_PLATFORM += -mexplicit-relocs - CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK + CPPFLAGS_PLATFORM = -DUSE_ASCII_FALLBACK endif if COND_mips - CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache + CFLAGS_PLATFORM += -mflush-func=grub_red_herring CCASFLAGS_PLATFORM = -march=mips3 endif if COND_sparc64_ieee1275 CFLAGS_PLATFORM += -mno-app-regs LDFLAGS_PLATFORM = -Wl,-melf64_sparc -mno-relax endif +if COND_arm + CFLAGS_PLATFORM += -mthumb-interwork -mlong-calls + CCASFLAGS_PLATFORM = -mthumb-interwork + LDFLAGS_PLATFORM = -Wl,--wrap=__clear_cache +endif + +#FIXME: discover and check XEN headers +CPPFLAGS_XEN = -I/usr/include # Other options @@ -47,29 +36,16 @@ CPPFLAGS_DEFAULT += -I$(top_builddir) CPPFLAGS_DEFAULT += -I$(top_srcdir) CPPFLAGS_DEFAULT += -I$(top_srcdir)/include CPPFLAGS_DEFAULT += -I$(top_builddir)/include -CCASFLAGS_DEFAULT = -DASM_FILE=1 +CPPFLAGS_DEFAULT += -I$(top_srcdir)/grub-core/lib/libgcrypt-grub/include +CPPFLAGS_DEFAULT += -I$(top_srcdir)/grub-core/lib/libgcrypt-grub/src/ +CCASFLAGS_DEFAULT = $(CPPFLAGS_DEFAULT) -DASM_FILE=1 +BUILD_CPPFLAGS += $(CPPFLAGS_DEFAULT) -LDADD_KERNEL = - -if ! COND_i386_pc -if ! COND_i386_efi -if ! COND_i386_qemu -if ! COND_i386_coreboot -if ! COND_i386_multiboot -if ! COND_i386_ieee1275 -if ! COND_x86_64_efi -LDADD_KERNEL += -lgcc -endif -endif -endif -endif -endif -endif -endif +LDADD_KERNEL = $(TARGET_LIBGCC) CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding -LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -static-libgcc -CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) +LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC) +CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) if COND_CYGWIN STRIPFLAGS_KERNEL = -F elf32-i386 -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version @@ -102,15 +78,15 @@ grubconfdir = $(sysconfdir)/grub.d platformdir = $(pkglibdir)/$(target_cpu)-$(platform) starfielddir = $(pkgdatadir)/themes/starfield -CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers -CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap - -CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition -Wno-unsafe-loop-optimizations +CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/gnulib -I$(top_srcdir)/grub-core/gnulib CFLAGS_POSIX = -fno-builtin CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap +CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX) +CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -I$(top_srcdir)/include/grub/gcrypt + CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime # List file macros for recognizing /interesting/ modules @@ -144,7 +120,7 @@ bin_PROGRAMS = platform_DATA = sbin_PROGRAMS = check_SCRIPTS = -grubconf_DATA = +dist_grubconf_DATA = check_PROGRAMS = noinst_SCRIPTS = noinst_PROGRAMS = @@ -167,12 +143,12 @@ $(top_srcdir)/Makefile.tpl: $(top_srcdir)/gentpl.py 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) +$(top_srcdir)/Makefile.util.am: $(top_srcdir)/Makefile.util.def $(top_srcdir)/Makefile.utilgcry.def $(top_srcdir)/Makefile.tpl + cat $(top_srcdir)/Makefile.util.def $(top_srcdir)/Makefile.utilgcry.def | 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) + cat $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def | autogen -T $(top_srcdir)/Makefile.tpl | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) mv $@.new $@ diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist index c862206bc..bf52487f8 100644 --- a/conf/Makefile.extra-dist +++ b/conf/Makefile.extra-dist @@ -26,7 +26,8 @@ EXTRA_DIST += grub-core/gensymlist.sh EXTRA_DIST += grub-core/genemuinit.sh EXTRA_DIST += grub-core/genemuinitheader.sh -EXTRA_DIST += grub-core/lib/libgcrypt/cipher +EXTRA_DIST += grub-core/lib/libgcrypt +EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h') EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h') EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/gnulib -name '*.h') @@ -34,8 +35,16 @@ EXTRA_DIST += grub-core/efiemu/runtime/config.h EXTRA_DIST += grub-core/lib/LzmaDec.c +EXTRA_DIST += grub-core/fs/cpio_common.c + EXTRA_DIST += BUGS EXTRA_DIST += util/i386/efi/grub-dumpdevtree +EXTRA_DIST += util/spkmodem-recv.c +EXTRA_DIST += util/import_gcrypth.sed +EXTRA_DIST += util/bin2h.c +EXTRA_DIST += util/grub-gen-asciih.c +EXTRA_DIST += util/grub-gen-widthspec.c +EXTRA_DIST += util/grub-pe2elf.c EXTRA_DIST += m4/gnulib-cache.m4 EXTRA_DIST += m4/glibc2.m4 @@ -51,3 +60,46 @@ EXTRA_DIST += m4/printf-posix.m4 EXTRA_DIST += m4/threadlib.m4 EXTRA_DIST += m4/uintmax_t.m4 EXTRA_DIST += m4/visibility.m4 +EXTRA_DIST += m4/math_h.m4 + +EXTRA_DIST += grub-core/osdep/apple/hostdisk.c +EXTRA_DIST += grub-core/osdep/aros/hostdisk.c +EXTRA_DIST += grub-core/osdep/basic/hostdisk.c +EXTRA_DIST += grub-core/osdep/bsd/hostdisk.c +EXTRA_DIST += grub-core/osdep/freebsd/hostdisk.c +EXTRA_DIST += grub-core/osdep/hurd/hostdisk.c +EXTRA_DIST += grub-core/osdep/linux/hostdisk.c +EXTRA_DIST += grub-core/osdep/windows/hostdisk.c +EXTRA_DIST += grub-core/osdep/sun/hostdisk.c +EXTRA_DIST += grub-core/osdep/haiku/hostdisk.c + +EXTRA_DIST += grub-core/osdep/basic/init.c +EXTRA_DIST += grub-core/osdep/windows/init.c + +EXTRA_DIST += grub-core/osdep/apple/getroot.c +EXTRA_DIST += grub-core/osdep/aros/getroot.c +EXTRA_DIST += grub-core/osdep/basic/getroot.c +EXTRA_DIST += grub-core/osdep/bsd/getroot.c +EXTRA_DIST += grub-core/osdep/windows/getroot.c +EXTRA_DIST += grub-core/osdep/freebsd/getroot.c +EXTRA_DIST += grub-core/osdep/hurd/getroot.c +EXTRA_DIST += grub-core/osdep/linux/getroot.c +EXTRA_DIST += grub-core/osdep/sun/getroot.c +EXTRA_DIST += grub-core/osdep/haiku/getroot.c + +EXTRA_DIST += grub-core/osdep/basic/random.c +EXTRA_DIST += grub-core/osdep/basic/ofpath.c + +EXTRA_DIST += grub-core/osdep/unix/password.c +EXTRA_DIST += grub-core/osdep/unix/random.c +EXTRA_DIST += grub-core/osdep/unix/sleep.c + +EXTRA_DIST += grub-core/osdep/linux/ofpath.c + +EXTRA_DIST += grub-core/osdep/windows/password.c +EXTRA_DIST += grub-core/osdep/windows/random.c +EXTRA_DIST += grub-core/osdep/windows/sleep.c + +EXTRA_DIST += tests/dfly-mbr-mbexample.mbr.img.gz +EXTRA_DIST += tests/dfly-mbr-mbexample.dfly.img.gz + diff --git a/config.h.in b/config.h.in index 5b1a5aaef..fe34051a1 100644 --- a/config.h.in +++ b/config.h.in @@ -5,9 +5,30 @@ #if defined(__PPC__) && !defined(__powerpc__) #define __powerpc__ 1 #endif -#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) + +#define GCRYPT_NO_DEPRECATED 1 + +/* Define to 1 to enable disk cache statistics. */ +#define DISK_CACHE_STATS @DISK_CACHE_STATS@ +#define BOOT_TIME_STATS @BOOT_TIME_STATS@ +/* Define to 1 to make GRUB quieter at boot time. */ +#define QUIET_BOOT @QUIET_BOOT@ + +#if defined (GRUB_BUILD) +#undef ENABLE_NLS +#define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ +#define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ +#if defined __APPLE__ +# if defined __BIG_ENDIAN__ +# define BUILD_WORDS_BIGENDIAN 1 +# else +# define BUILD_WORDS_BIGENDIAN 0 +# endif +#else +#define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ +#endif +#elif defined (GRUB_UTIL) || !defined (GRUB_MACHINE) #include -#define NESTED_FUNC_ATTR #else /* Define if C symbols get an underscore after compilation. */ #define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ @@ -35,24 +56,14 @@ #define GRUB_BOOT_DIR_NAME "@bootdirname@" /* Default grub directory name */ #define GRUB_DIR_NAME "@grubdirname@" -/* Define to 1 if GCC generates calls to __enable_execute_stack(). */ -#define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@ /* Define to 1 if GCC generates calls to __register_frame_info(). */ #define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@ -/* Define to 1 to enable disk cache statistics. */ -#define DISK_CACHE_STATS @DISK_CACHE_STATS@ -/* Define to 1 to make GRUB quieter at boot time. */ -#define QUIET_BOOT @QUIET_BOOT@ #define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" #define GRUB_PLATFORM "@GRUB_PLATFORM@" #define RE_ENABLE_I18N 1 -#if defined(__i386__) -#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) -#else -#define NESTED_FUNC_ATTR -#endif +#define _GNU_SOURCE 1 #endif diff --git a/configure.ac b/configure.ac index 5c0f88805..f504e559f 100644 --- a/configure.ac +++ b/configure.ac @@ -41,21 +41,42 @@ AC_CONFIG_AUX_DIR([build-aux]) # Checks for host and target systems. AC_CANONICAL_HOST +save_program_prefix="${program_prefix}" AC_CANONICAL_TARGET +program_prefix="${save_program_prefix}" -AM_INIT_AUTOMAKE() +AM_INIT_AUTOMAKE([1.10.1]) AC_PREREQ(2.60) AC_CONFIG_SRCDIR([include/grub/dl.h]) AC_CONFIG_HEADER([config-util.h]) # Program name transformations AC_ARG_PROGRAM +grub_TRANSFORM([grub-bios-setup]) +grub_TRANSFORM([grub-editenv]) +grub_TRANSFORM([grub-install]) +grub_TRANSFORM([grub-mkconfig]) +grub_TRANSFORM([grub-mkfont]) +grub_TRANSFORM([grub-mkimage]) +grub_TRANSFORM([grub-glue-efi]) +grub_TRANSFORM([grub-mklayout]) +grub_TRANSFORM([grub-mkpasswd-pbkdf2]) +grub_TRANSFORM([grub-mkrelpath]) +grub_TRANSFORM([grub-mkrescue]) +grub_TRANSFORM([grub-probe]) +grub_TRANSFORM([grub-reboot]) +grub_TRANSFORM([grub-script-check]) +grub_TRANSFORM([grub-set-default]) +grub_TRANSFORM([grub-sparc64-setup]) +grub_TRANSFORM([grub-render-label]) # Optimization flag. Allow user to override. if test "x$TARGET_CFLAGS" = x; then TARGET_CFLAGS="$TARGET_CFLAGS -Os" fi +BUILD_CPPFLAGS="$BUILD_CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\"" + # Default HOST_CPPFLAGS HOST_CPPFLAGS="$HOST_CPPFLAGS -Wall -W" HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include" @@ -79,6 +100,9 @@ case "$target_cpu" in target_cpu=mips; machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS=1"; ;; + arm*) + target_cpu=arm; + ;; esac # Specify the platform (such as firmware). @@ -99,6 +123,7 @@ if test "x$with_platform" = x; then mipsel-*) platform=loongson ;; mips-*) platform=arc ;; ia64-*) platform=efi ;; + arm-*) platform=uboot ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else @@ -108,6 +133,7 @@ fi case "$target_cpu"-"$platform" in x86_64-efi) ;; x86_64-emu) ;; + x86_64-xen) ;; x86_64-*) target_cpu=i386 ;; powerpc64-ieee1275) target_cpu=powerpc ;; esac @@ -116,6 +142,8 @@ esac case "$target_cpu"-"$platform" in i386-efi) ;; x86_64-efi) ;; + i386-xen) ;; + x86_64-xen) ;; i386-pc) ;; i386-multiboot) ;; i386-coreboot) ;; @@ -128,22 +156,27 @@ case "$target_cpu"-"$platform" in mips-qemu_mips) ;; mips-qemu-mips) platform=qemu_mips;; mips-arc) ;; + mipsel-arc) ;; mipsel-qemu_mips) ;; mipsel-qemu-mips) platform=qemu_mips;; mipsel-yeeloong) platform=loongson ;; mipsel-fuloong) platform=loongson ;; mipsel-loongson) ;; + arm-uboot) ;; + arm-efi) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac -case "$target_cpu" in - i386 | powerpc) target_m32=1 ;; - x86_64 | sparc64) target_m64=1 ;; -esac +if test x$platform != xemu ; then + case "$target_cpu" in + i386 | powerpc) target_m32=1 ;; + x86_64 | sparc64) target_m64=1 ;; + esac +fi -case "$host_os" in - mingw32*) host_os=cygwin ;; +case "$target_os" in + windows* | mingw32*) target_os=cygwin ;; esac # This normalizes the names, and creates a new variable ("host_kernel") @@ -156,14 +189,16 @@ case "$host_os" in netbsd*) host_kernel=netbsd ;; solaris*) host_kernel=illumos ;; darwin*) host_kernel=xnu ;; - cygwin) host_kernel=windows ;; + cygwin | windows* | mingw32*) host_kernel=windows ;; esac case "$platform" in coreboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_COREBOOT=1" ;; multiboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MULTIBOOT=1" ;; efi) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EFI=1" ;; + xen) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_XEN=1" ;; ieee1275) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_IEEE1275=1" ;; + uboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_UBOOT=1" ;; qemu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_QEMU=1" ;; pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; @@ -172,6 +207,7 @@ case "$platform" in arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; esac case "$target_cpu" in + arm) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARM=1" ;; mips |mipsel) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;; esac @@ -181,6 +217,23 @@ else machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,` -DGRUB_TARGET_CPU_`echo ${target_cpu} | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`=1" fi +case "${target_cpu}-$platform" in + mips-arc) + TARGET_LINK_ADDR=0x88200000 + TARGET_DECOMPRESSOR_LINK_ADDR=0x88100000 + ;; + mipsel-arc) + TARGET_LINK_ADDR=0x80700000 + TARGET_DECOMPRESSOR_LINK_ADDR=0x80600000 + ;; + mips*-qemu_mips | mips*-loongson) + TARGET_DECOMPRESSOR_LINK_ADDR=0x80100000 + ;; +esac + +AC_SUBST(TARGET_LINK_ADDR) +AC_SUBST(TARGET_DECOMPRESSOR_LINK_ADDR) + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $machine_CPPFLAGS" AC_SUBST(host_cpu) @@ -239,23 +292,6 @@ if test "x$YACC" = x; then AC_MSG_ERROR([bison is not found]) fi -FONT_SOURCE= - -for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do - for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont; do - if test -f "$dir/unifont.$ext"; then - FONT_SOURCE="$dir/unifont.$ext" - break 2 - fi - done -done - -if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips); then - AC_MSG_ERROR([qemu and loongson ports need unifont]) -fi - -AC_SUBST([FONT_SOURCE]) - AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_AWK @@ -285,26 +321,33 @@ AC_PATH_PROGS(MAKEINFO, makeinfo true) AC_PROG_CC gl_EARLY +AC_PROG_CXX AM_PROG_CC_C_O AM_PROG_AS # Must be GCC. test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required]) +AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no) + AC_GNU_SOURCE AM_GNU_GETTEXT([external]) AC_SYS_LARGEFILE # Identify characteristics of the host architecture. +unset ac_cv_c_bigendian + AC_C_BIGENDIAN AC_CHECK_SIZEOF(void *) AC_CHECK_SIZEOF(long) -grub_apple_cc -if test x$grub_cv_apple_cc = xyes ; then - HOST_CPPFLAGS="$HOST_CPPFLAGS -fnested-functions" - HOST_LDFLAGS="$HOST_LDFLAGS -Wl,-allow_stack_execute" -fi +case "$host_os" in + cygwin | windows* | mingw32*) + HOST_CPPFLAGS="$HOST_CPPFLAGS -DUNICODE=1 -D_WIN32_WINNT=0x0500" + CPPFLAGS="$CPPFLAGS -DUNICODE=1 -D_WIN32_WINNT=0x0500" + AC_CHECK_SIZEOF(TCHAR,,[#include ]) + ;; +esac if test x$USE_NLS = xno; then HOST_CFLAGS="$HOST_CFLAGS -fno-builtin-gettext" @@ -317,7 +360,7 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent) +AC_CHECK_FUNCS(posix_memalign memalign getextmntent) AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h) AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default @@ -342,13 +385,32 @@ AC_CHECK_HEADER([util.h], [ ]) AC_SUBST([LIBUTIL]) +AC_CACHE_CHECK([whether -Wtrampolines work], [grub_cv_host_cc_wtrampolines], [ + SAVED_CFLAGS="$CFLAGS" + CFLAGS="$HOST_CFLAGS -Wtrampolines -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +int va_arg_func (int fixed, va_list args);]], [[]])], + [grub_cv_host_cc_wtrampolines=yes], + [grub_cv_host_cc_wtrampolines=no]) + CFLAGS="$SAVED_CFLAGS" +]) + +if test x"$grub_host_cv_cc_wtrampolines" = xyes ; then + HOST_CFLAGS="$HOST_CFLAGS -Wtrampolines" +fi + # # Check for host and build compilers. # HOST_CC=$CC -AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc], - [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.])]) +AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc]) +test -z "$BUILD_CC" && AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.]) +BUILD_CPP="$BUILD_CC -E" +case "$build_os" in + haiku*) BUILD_LIBM= ;; + *) BUILD_LIBM=-lm ;; +esac # For gnulib. gl_INIT @@ -363,22 +425,31 @@ if test "x$target_alias" != x && test "x$host_alias" != "x$target_alias"; then AC_CHECK_TOOLS(TARGET_CC, [gcc egcs cc], [AC_MSG_ERROR([none of gcc, egcs and cc is found. set TARGET_CC manually.])]) - AC_CHECK_TOOL(OBJCOPY, objcopy) - AC_CHECK_TOOL(STRIP, strip) - AC_CHECK_TOOL(NM, nm) + AC_CHECK_TOOL(TARGET_OBJCOPY, objcopy) + AC_CHECK_TOOL(TARGET_STRIP, strip) + AC_CHECK_TOOL(TARGET_NM, nm) + AC_CHECK_TOOL(TARGET_RANLIB, ranlib) ac_tool_prefix="$tmp_ac_tool_prefix" else if test "x$TARGET_CC" = x; then TARGET_CC=$CC fi - AC_CHECK_TOOL(OBJCOPY, objcopy) - AC_CHECK_TOOL(STRIP, strip) - AC_CHECK_TOOL(NM, nm) + AC_CHECK_TOOL(TARGET_OBJCOPY, objcopy) + AC_CHECK_TOOL(TARGET_STRIP, strip) + AC_CHECK_TOOL(TARGET_NM, nm) + AC_CHECK_TOOL(TARGET_RANLIB, ranlib) fi + AC_SUBST(HOST_CC) AC_SUBST(BUILD_CC) +AC_SUBST(BUILD_CFLAGS) +AC_SUBST(BUILD_CPPFLAGS) AC_SUBST(TARGET_CC) +AC_SUBST(TARGET_NM) +AC_SUBST(TARGET_RANLIB) +AC_SUBST(TARGET_STRIP) +AC_SUBST(TARGET_OBJCOPY) # Test the C compiler for the target environment. tmp_CC="$CC" @@ -392,152 +463,40 @@ CPPFLAGS="$TARGET_CPPFLAGS" LDFLAGS="$TARGET_LDFLAGS" LIBS="" +grub_PROG_NM_MINUS_P +grub_PROG_NM_DEFINED_ONLY +AC_SUBST(TARGET_NMFLAGS_MINUS_P) +AC_SUBST(TARGET_NMFLAGS_DEFINED_ONLY) + # debug flags. -WARN_FLAGS="-Wall -W -Wshadow -Wold-style-definition -Wpointer-arith -Wundef -Wextra -Waddress -Wattributes -Wcast-align -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wempty-body -Wendif-labels -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-noreturn -Wmultichar -Wnonnull -Woverflow -Wparentheses -Wpointer-arith -Wpointer-to-int-cast -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstrict-aliasing -Wswitch -Wtrigraphs -Wundef -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings -Wnested-externs -Wstrict-prototypes -Wpointer-sign" -HOST_CFLAGS="$HOST_CFLAGS $WARN_FLAGS" +WARN_FLAGS="-Wall -W -Wshadow -Wold-style-definition -Wpointer-arith -Wundef -Wextra -Wattributes -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wendif-labels -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmultichar -Wnonnull -Woverflow -Wparentheses -Wpointer-arith -Wpointer-to-int-cast -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstrict-aliasing -Wswitch -Wtrigraphs -Wundef -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings -Wnested-externs -Wstrict-prototypes -Wpointer-sign" +HOST_CFLAGS="$HOST_CFLAGS $WARN_FLAGS -Wcast-align" TARGET_CFLAGS="$TARGET_CFLAGS $WARN_FLAGS -g -Wredundant-decls -Wmissing-prototypes -Wmissing-declarations" TARGET_CCASFLAGS="$TARGET_CCASFLAGS -g" -# Force no alignment to save space on i386. -if test "x$target_cpu" = xi386; then - AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [ - CFLAGS="$CFLAGS -falign-loops=1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_falign_loop=yes], - [grub_cv_cc_falign_loop=no]) - ]) - - if test "x$grub_cv_cc_falign_loop" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1" - else - TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" - fi - - # Some toolchains enable these features by default, but they need - # registers that aren't set up properly in GRUB. - TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-3dnow" +if test "x$target_cpu" != xi386 && test "x$target_cpu" != xx86_64; then +TARGET_CFLAGS="$TARGET_CFLAGS -Wcast-align" fi -# By default, GCC 4.4 generates .eh_frame sections containing unwind -# information in some cases where it previously did not. GRUB doesn't need -# these and they just use up vital space. Restore the old compiler -# behaviour. -AC_CACHE_CHECK([whether -fno-dwarf2-cfi-asm works], [grub_cv_cc_fno_dwarf2_cfi_asm], [ - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_fno_dwarf2_cfi_asm=yes], - [grub_cv_cc_fno_dwarf2_cfi_asm=no]) - CFLAGS="$SAVE_CFLAGS" -]) +AC_CACHE_CHECK([if compiling with clang], [grub_cv_cc_target_clang] +[AC_COMPILE_IFELSE( +[AC_LANG_PROGRAM([], [[ +#ifdef __clang__ +#error "is clang" +#endif +]])], +[grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])]) -if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" +# on x86 clang doesn't support .code16 +# on arm clang doesn't support .arch directive +if test "x$grub_cv_cc_target_clang" = xyes && ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 || test "x$target_cpu" = xarm ); then + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -no-integrated-as" fi -# By default, GCC 4.6 generates .eh_frame sections containing unwind -# information in some cases where it previously did not. GRUB doesn't need -# these and they just use up vital space. Restore the old compiler -# behaviour. -AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [ - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_fno_asynchronous_unwind_tables=yes], - [grub_cv_cc_fno_asynchronous_unwind_tables=no]) - CFLAGS="$SAVE_CFLAGS" -]) - -if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" +if test "x$target_cpu" = xi386 && test "x$platform" != xemu; then + TARGET_CFLAGS="$TARGET_CFLAGS -march=i386" fi -grub_apple_target_cc -if test x$grub_cv_apple_target_cc = xyes ; then - TARGET_CPPFLAGS="$TARGET_CPPFLAGS -fnested-functions" - - CFLAGS="$CFLAGS -fnested-functions" - TARGET_APPLE_CC=1 - AC_CHECK_PROG([OBJCONV], [objconv], [objconv], []) - if test "x$OBJCONV" = x ; then - AC_CHECK_PROG([OBJCONV], [objconv], [./objconv], [], [.]) - fi - if test "x$OBJCONV" = x ; then - AC_MSG_ERROR([objconv not found which is required when building with apple compiler]) - fi - TARGET_IMG_LDSCRIPT= - TARGET_IMG_CFLAGS="-static" - TARGET_IMG_LDFLAGS='-nostdlib -static -Wl,-preload -Wl,-segalign,20' - TARGET_IMG_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20' - TARGET_IMG_BASE_LDOPT="-Wl,-image_base" - TARGET_LDFLAGS_OLDMAGIC="" -else - TARGET_APPLE_CC=0 - TARGET_LDFLAGS_OLDMAGIC="-Wl,-N" -# Use linker script if present, otherwise use builtin -N script. -if test -f "${srcdir}/${grub_coredir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"; then - TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/${grub_coredir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc" - TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT}" - TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/${grub_coredir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc" - TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" -else - TARGET_IMG_LDSCRIPT= - TARGET_IMG_LDFLAGS='-Wl,-N' - TARGET_IMG_LDFLAGS_AC='-Wl,-N' - TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" -fi -TARGET_IMG_CFLAGS= -fi - -AC_SUBST(TARGET_LDFLAGS_OLDMAGIC) - -# For platforms where ELF is not the default link format. -AC_MSG_CHECKING([for command to convert module to ELF format]) -case "${host_os}" in - cygwin) TARGET_OBJ2ELF='$(top_builddir)/grub-pe2elf'; -# FIXME: put proper test here - NEED_REGISTER_FRAME_INFO=1 - ;; - *) NEED_REGISTER_FRAME_INFO=0 ;; -esac -AC_MSG_RESULT([$TARGET_OBJ2ELF]) - - -AC_ARG_ENABLE([efiemu], - [AS_HELP_STRING([--enable-efiemu], - [build and install the efiemu runtimes (default=guessed)])]) -if test x"$enable_efiemu" = xno ; then - efiemu_excuse="explicitly disabled" -fi -if test x"$target_cpu" != xi386 ; then - efiemu_excuse="only available on i386" -fi -if test x"$platform" = xefi ; then - efiemu_excuse="not available on efi" -fi -if test x"$efiemu_excuse" = x ; then - AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [ - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_efiemu=yes], - [grub_cv_cc_efiemu=no]) - CFLAGS="$SAVED_CFLAGS" - ]) - if test x$grub_cv_cc_efiemu = xno; then - efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib" - fi -fi -if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then - AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled]) -fi -if test x"$efiemu_excuse" = x ; then -enable_efiemu=yes -else -enable_efiemu=no -fi -AC_SUBST([enable_efiemu]) - if test "x$target_m32" = x1; then # Force 32-bit mode. TARGET_CFLAGS="$TARGET_CFLAGS -m32" @@ -556,11 +515,218 @@ if test "x$target_m64" = x1; then TARGET_MODULE_FORMAT="elf64" fi -if test "$target_cpu"-"$platform" = x86_64-efi; then +if test "x$grub_cv_cc_target_clang" = xno && test "x$target_cpu" = xi386 && test "x$platform" != xemu && test "x$platform" != xefi; then + TARGET_CFLAGS="$TARGET_CFLAGS -mrtd -mregparm=3" +fi + +# Force no alignment to save space on i386. +if test "x$target_cpu" = xi386; then + AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [ + CFLAGS="$TARGET_CFLAGS -falign-loops=1 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_falign_loop=yes], + [grub_cv_cc_falign_loop=no]) + ]) + + AC_CACHE_CHECK([whether -malign-loops works], [grub_cv_cc_malign_loop], [ + CFLAGS="$TARGET_CFLAGS -malign-loops=1 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_malign_loop=yes], + [grub_cv_cc_malign_loop=no]) + ]) + + if test "x$grub_cv_cc_falign_loop" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1" + elif test "x$grub_cv_cc_malign_loop" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" + fi +fi + +AC_CACHE_CHECK([whether -freg-struct-return works], [grub_cv_cc_freg_struct_return], [ + CFLAGS="$TARGET_CFLAGS -freg-struct-return -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_freg_struct_return=yes], + [grub_cv_cc_freg_struct_return=no]) +]) + +if test "x$grub_cv_cc_freg_struct_return" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -freg-struct-return" +fi + +if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$platform" != xemu; then + # Some toolchains enable these features by default, but they need + # registers that aren't set up properly in GRUB. + TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-3dnow" +fi + +# By default, GCC 4.4 generates .eh_frame sections containing unwind +# information in some cases where it previously did not. GRUB doesn't need +# these and they just use up vital space. Restore the old compiler +# behaviour. +AC_CACHE_CHECK([whether -fno-dwarf2-cfi-asm works], [grub_cv_cc_fno_dwarf2_cfi_asm], [ + CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_dwarf2_cfi_asm=yes], + [grub_cv_cc_fno_dwarf2_cfi_asm=no]) +]) + +if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" +fi + +if test x"$target_os" = xcygwin; then + AC_CACHE_CHECK([whether option -fno-reorder-functions works], grub_cv_cc_no_reorder_functions, [ + CFLAGS="$TARGET_CFLAGS -fno-reorder-functions" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_no_reorder_functions=yes], + [grub_cv_cc_no_reorder_functions=no]) + ]) +fi + +if test x"$target_os" = xcygwin && test "x$grub_cv_cc_no_reorder_functions" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-reorder-functions" +fi + +# By default, GCC 4.6 generates .eh_frame sections containing unwind +# information in some cases where it previously did not. GRUB doesn't need +# these and they just use up vital space. Restore the old compiler +# behaviour. +AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [ + CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_asynchronous_unwind_tables=yes], + [grub_cv_cc_fno_asynchronous_unwind_tables=no]) +]) + +if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" +fi + +grub_apple_target_cc +if test x$grub_cv_apple_target_cc = xyes ; then + TARGET_APPLE_CC=1 + AC_CHECK_PROG([TARGET_OBJCONV], [objconv], [objconv], []) + if test "x$TARGET_OBJCONV" = x ; then + AC_CHECK_PROG([TARGET_OBJCONV], [objconv], [./objconv], [], [.]) + fi + if test "x$TARGET_OBJCONV" = x ; then + AC_MSG_ERROR([objconv not found which is required when building with apple compiler]) + fi + TARGET_IMG_LDSCRIPT= + TARGET_IMG_CFLAGS="-static" + TARGET_IMG_LDFLAGS='-nostdlib -static -Wl,-preload -Wl,-segalign,20' + TARGET_IMG_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20' + TARGET_IMG_BASE_LDOPT="-Wl,-image_base" + TARGET_LDFLAGS_OLDMAGIC="" +else + TARGET_APPLE_CC=0 + TARGET_LDFLAGS_OLDMAGIC="-Wl,-N" +# Use linker script if present, otherwise use builtin -N script. +if test -f "${srcdir}/${grub_coredir}/conf/${target_cpu}-${platform}-${target_os}-img-ld.sc"; then + TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/${grub_coredir}/conf/${target_cpu}-${platform}-${target_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}-${target_os}-img-ld.sc" + TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" +else + TARGET_IMG_LDSCRIPT= + TARGET_IMG_LDFLAGS='-Wl,-N' + TARGET_IMG_LDFLAGS_AC='-Wl,-N' + TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" +fi +TARGET_IMG_CFLAGS= +fi + +AC_SUBST(TARGET_LDFLAGS_OLDMAGIC) + +# For platforms where ELF is not the default link format. +AC_MSG_CHECKING([for command to convert module to ELF format]) +case "${target_os}" in + cygwin) TARGET_OBJ2ELF='./build-grub-pe2elf'; +# FIXME: put proper test here + NEED_REGISTER_FRAME_INFO=1 + ;; + *) NEED_REGISTER_FRAME_INFO=0 ;; +esac +AC_MSG_RESULT([$TARGET_OBJ2ELF]) + + +AC_ARG_ENABLE([efiemu], + [AS_HELP_STRING([--enable-efiemu], + [build and install the efiemu runtimes (default=guessed)])]) +if test x"$enable_efiemu" = xno ; then + efiemu_excuse="explicitly disabled" +fi +if test x"$target_os" = xcygwin ; then + efiemu_excuse="not available on cygwin" +fi +if test x"$target_cpu" != xi386 ; then + efiemu_excuse="only available on i386" +fi +if test x"$platform" = xefi ; then + efiemu_excuse="not available on efi" +fi +if test x"$efiemu_excuse" = x ; then + AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [ + CFLAGS="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_efiemu=yes], + [grub_cv_cc_efiemu=no]) + ]) + if test x$grub_cv_cc_efiemu = xno; then + efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib" + fi +fi +if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then + AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled]) +fi +if test x"$efiemu_excuse" = x ; then +enable_efiemu=yes +else +enable_efiemu=no +fi +AC_SUBST([enable_efiemu]) + +case "$target_os" in + cygwin) + ;; + freebsd | kfreebsd*-gnu) + if test x"$target_cpu" = xi386; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_i386_fbsd" + fi + if test x"$target_cpu" = xx86_64; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_x86_64_fbsd" + fi + ;; + openbsd*) + if test x"$target_cpu" = xi386; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_i386_obsd" + fi + if test x"$target_cpu" = xx86_64; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_x86_64_obsd" + fi + ;; + haiku*) + if test x"$target_cpu" = xi386; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_i386_haiku" + fi + if test x"$target_cpu" = xx86_64; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_x86_64_haiku" + fi + ;; + *) + if test x"$target_cpu" = xi386; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_i386" + fi + if test x"$target_cpu" = xx86_64; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,-melf_x86_64" + fi + ;; +esac + +if test "$target_cpu" = x86_64; then # Use large model to support 4G memory AC_CACHE_CHECK([whether option -mcmodel=large works], grub_cv_cc_mcmodel, [ - SAVED_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -m64 -mcmodel=large" + CFLAGS="$TARGET_CFLAGS -m64 -mcmodel=large" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_mcmodel=yes], [grub_cv_cc_mcmodel=no]) @@ -570,10 +736,12 @@ if test "$target_cpu"-"$platform" = x86_64-efi; then else TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=large" fi +fi +if test "$target_cpu"-"$platform" = x86_64-efi; then # EFI writes to stack below %rsp, we must not use the red zone AC_CACHE_CHECK([whether option -mno-red-zone works], grub_cv_cc_no_red_zone, [ - CFLAGS="$CFLAGS -m64 -mno-red-zone" + CFLAGS="$TARGET_CFLAGS -m64 -mno-red-zone" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_no_red_zone=yes], [grub_cv_cc_no_red_zone=no]) @@ -589,8 +757,7 @@ fi # Compiler features. # -# Need __enable_execute_stack() for nested function trampolines? -grub_CHECK_ENABLE_EXECUTE_STACK +CFLAGS="$TARGET_CFLAGS" # Position independent executable. grub_CHECK_PIE @@ -600,6 +767,8 @@ if [ x"$pie_possible" = xyes ]; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE" fi] +CFLAGS="$TARGET_CFLAGS" + # Position independent executable. grub_CHECK_PIC [# Need that, because some distributions ship compilers that include @@ -608,6 +777,8 @@ if [ x"$pic_possible" = xyes ]; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIC" fi] +CFLAGS="$TARGET_CFLAGS" + # Smashing stack protector. grub_CHECK_STACK_PROTECTOR # Need that, because some distributions ship compilers that include @@ -615,6 +786,9 @@ grub_CHECK_STACK_PROTECTOR if test "x$ssp_possible" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector" fi + +CFLAGS="$TARGET_CFLAGS" + grub_CHECK_STACK_ARG_PROBE # Cygwin's GCC uses alloca() to probe the stackframe on static # stack allocations above some threshold. @@ -622,45 +796,16 @@ if test x"$sap_possible" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe" fi -AC_ARG_ENABLE([werror], - [AS_HELP_STRING([--disable-werror], - [do not use -Werror when building GRUB])]) -if test x"$enable_werror" != xno ; then - TARGET_CFLAGS="$TARGET_CFLAGS -Werror" - HOST_CFLAGS="$HOST_CFLAGS -Werror" +CFLAGS="$TARGET_CFLAGS" + +# -mno-unaligned-access +if test "$target_cpu" = arm; then + grub_CHECK_NO_UNALIGNED_ACCESS + if test x"$nua_possible" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mno-unaligned-access" + fi fi -TARGET_CPP="$TARGET_CC -E" -TARGET_CCAS=$TARGET_CC - -GRUB_TARGET_CPU="${target_cpu}" -GRUB_PLATFORM="${platform}" - -AC_SUBST(GRUB_TARGET_CPU) -AC_SUBST(GRUB_PLATFORM) - -AC_SUBST(OBJCONV) -AC_SUBST(TARGET_CPP) -AC_SUBST(TARGET_CCAS) -AC_SUBST(TARGET_OBJ2ELF) -AC_SUBST(TARGET_APPLE_CC) -AC_SUBST(TARGET_MODULE_FORMAT) - -AC_SUBST(TARGET_CFLAGS) -AC_SUBST(TARGET_LDFLAGS) -AC_SUBST(TARGET_CPPFLAGS) -AC_SUBST(TARGET_CCASFLAGS) - -AC_SUBST(TARGET_IMG_LDSCRIPT) -AC_SUBST(TARGET_IMG_LDFLAGS) -AC_SUBST(TARGET_IMG_CFLAGS) -AC_SUBST(TARGET_IMG_BASE_LDOPT) - -AC_SUBST(HOST_CFLAGS) -AC_SUBST(HOST_LDFLAGS) -AC_SUBST(HOST_CPPFLAGS) -AC_SUBST(HOST_CCASFLAGS) - # Set them to their new values for the tests below. CC="$TARGET_CC" if test "x$TARGET_APPLE_CC" = x1 ; then @@ -669,21 +814,23 @@ else CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100 -Wno-error" fi CPPFLAGS="$TARGET_CPPFLAGS" -if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 ; then -LIBS= +if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test "x$grub_cv_cc_target_clang" = xyes ; then +TARGET_LIBGCC= else -LIBS=-lgcc +TARGET_LIBGCC=-lgcc fi +LIBS="$TARGET_LIBGCC" + grub_ASM_USCORE if test x$grub_cv_asm_uscore = xyes; then -CFLAGS="$CFLAGS -Wl,--defsym,_abort=_main" +CFLAGS="$TARGET_CFLAGS -Wl,--defsym,_abort=_main" else -CFLAGS="$CFLAGS -Wl,--defsym,abort=main" +CFLAGS="$TARGET_CFLAGS -Wl,--defsym,abort=main" fi # Check for libgcc symbols -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __ucmpdi2 _restgpr_14_x __ctzdi2 __ctzsi2) if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" @@ -702,7 +849,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} ${TARGET_IMG_BASE_LDOPT},8000 -Wl,--defsym,___main=0x8100" + CFLAGS="$TARGET_CFLAGS -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},0x8000 -Wl,--defsym,___main=0x8100" fi grub_CHECK_BSS_START_SYMBOL grub_CHECK_END_SYMBOL @@ -717,6 +864,7 @@ AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [ SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$TARGET_CPPFLAGS -nostdinc -isystem `$TARGET_CC -print-file-name=include`" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +#include int va_arg_func (int fixed, va_list args);]], [[]])], [grub_cv_cc_isystem=yes], [grub_cv_cc_isystem=no]) @@ -728,21 +876,16 @@ 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" - # Test for -Wtrampolines rather than -Wno-trampolines to reduce confusion - # in the event of later failures (since -Wno-* is always accepted, but - # produces a diagnostic if something else is wrong). - CFLAGS="$TARGET_CFLAGS -Wtrampolines" +AC_CACHE_CHECK([whether -Wtrampolines work], [grub_cv_cc_wtrampolines], [ + CFLAGS="$TARGET_CFLAGS -Wtrampolines -Werror" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include int va_arg_func (int fixed, va_list args);]], [[]])], - [grub_cv_cc_wnotrampolines=yes], - [grub_cv_cc_wnotrampolines=no]) - CFLAGS="$SAVED_CFLAGS" + [grub_cv_cc_wtrampolines=yes], + [grub_cv_cc_wtrampolines=no]) ]) -if test x"$grub_cv_cc_wnotrampolines" = xyes ; then - TARGET_CFLAGS="$TARGET_CFLAGS -Wno-trampolines" +if test x"$grub_cv_cc_wtrampolines" = xyes ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Wtrampolines" fi # Restore the flags. @@ -774,6 +917,17 @@ else fi AC_SUBST([DISK_CACHE_STATS]) +AC_ARG_ENABLE([boot-time], + AS_HELP_STRING([--enable-boot-time], + [enable boot time statistics collection])) + +if test x$enable_boot_time = xyes; then + BOOT_TIME_STATS=1 +else + BOOT_TIME_STATS=0 +fi +AC_SUBST([BOOT_TIME_STATS]) + AC_ARG_ENABLE([grub-emu-usb], [AS_HELP_STRING([--enable-grub-emu-usb], [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) @@ -787,22 +941,6 @@ AC_ARG_ENABLE([grub-emu-pci], [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])]) if test "$platform" = emu; then - missing_ncurses= -[# Check for curses libraries.] - AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"], - [AC_CHECK_LIB([curses], [wgetch], [LIBCURSES="-lcurses"], - [missing_ncurses=[true]])]) - AC_SUBST([LIBCURSES]) -[if [ x"$missing_ncurses" = x ]; then ] - [# Check for headers.] - AC_CHECK_HEADERS([ncurses/curses.h], [], - [AC_CHECK_HEADERS([ncurses.h], [], - [AC_CHECK_HEADERS([curses.h], [], - [missing_ncurses=[true]])])]) -[fi] -if test x"$missing_ncurses" = xtrue ; then - AC_MSG_ERROR([grub-emu can't be compiled without ncurses]) -fi if test x"$enable_grub_emu_usb" != xyes ; then grub_emu_usb_excuse="not enabled" @@ -887,6 +1025,13 @@ fi AC_SUBST([enable_grub_emu_sdl]) AC_SUBST([enable_grub_emu_usb]) AC_SUBST([enable_grub_emu_pci]) + +else + +# Ignore --enable-emu-* if platform is not emu +enable_grub_emu_sdl=no +enable_grub_emu_usb=no +enable_grub_emu_pci=no fi AC_ARG_ENABLE([grub-mkfont], @@ -898,16 +1043,18 @@ fi if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. - AC_CHECK_PROGS([FREETYPE], [freetype-config]) + AC_CHECK_TOOLS([FREETYPE], [freetype-config]) if test "x$FREETYPE" = x ; then grub_mkfont_excuse=["need freetype2 library"] fi fi +unset ac_cv_header_ft2build_h + if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. - freetype_cflags=`freetype-config --cflags` - freetype_libs=`freetype-config --libs` + freetype_cflags=`$FREETYPE --cflags` + freetype_libs=`$FREETYPE --libs` SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $freetype_cflags" AC_CHECK_HEADERS([ft2build.h], [], @@ -923,19 +1070,87 @@ enable_grub_mkfont=yes else enable_grub_mkfont=no fi -if test x"$enable_grub_mkfont" = xno && test "x$platform" = xloongson; then - AC_MSG_ERROR([loongson port needs grub-mkfont]) -fi AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) +SAVED_CC="$CC" +SAVED_CPP="$CPP" +SAVED_CFLAGS="$CFLAGS" +SAVED_CPPFLAGS="$CPPFLAGS" +CC="$BUILD_CC" +CPP="$BUILD_CPP" +CFLAGS="$BUILD_CFLAGS" +CPPFLAGS="$BUILD_CPPFLAGS" + +unset ac_cv_c_bigendian +unset ac_cv_header_ft2build_h + +AC_COMPUTE_INT([BUILD_SIZEOF_VOID_P], [sizeof (void *)]) +AC_COMPUTE_INT([BUILD_SIZEOF_LONG], [sizeof (long)]) +AC_C_BIGENDIAN([BUILD_WORDS_BIGENDIAN=1], [BUILD_WORDS_BIGENDIAN=0], [BUILD_WORDS_BIGENDIAN=err], [BUILD_WORDS_BIGENDIAN=err]) + +if test x$BUILD_WORDS_BIGENDIAN = xerr ; then + AC_MSG_ERROR([couldnt determine build endianness]) +fi + +AC_SUBST([BUILD_SIZEOF_LONG]) +AC_SUBST([BUILD_SIZEOF_VOID_P]) +AC_SUBST([BUILD_WORDS_BIGENDIAN]) + +if test x"$grub_build_mkfont_excuse" = x ; then + # Check for freetype libraries. + AC_CHECK_PROGS([BUILD_FREETYPE], [freetype-config]) + if test "x$BUILD_FREETYPE" = x ; then + grub_build_mkfont_excuse=["need freetype2 library"] + fi +fi + +if test x"$grub_build_mkfont_excuse" = x ; then + # Check for freetype libraries. + build_freetype_cflags=`$BUILD_FREETYPE --cflags` + build_freetype_libs=`$BUILD_FREETYPE --libs` + SAVED_CPPFLAGS_2="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $build_freetype_cflags" + AC_CHECK_HEADERS([ft2build.h], [], + [grub_build_mkfont_excuse=["need freetype2 headers"]]) + CPPFLAGS="$SAVED_CPPFLAGS_2" +fi + +if test x"$enable_build_grub_mkfont" = xyes && test x"$grub_build_mkfont_excuse" != x ; then + AC_MSG_ERROR([build-grub-mkfont was explicitly requested but can't be compiled]) +fi +if test x"$grub_build_mkfont_excuse" = x ; then + enable_build_grub_mkfont=yes +else + enable_build_grub_mkfont=no +fi +if test x"$enable_build_grub_mkfont" = xno && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$target_cpu"-"$platform" = xpowerpc-ieee1275 ); then + AC_MSG_ERROR([qemu, powerpc-ieee1275 and loongson ports needs build-time grub-mkfont]) +fi + +AC_SUBST([build_freetype_cflags]) +AC_SUBST([build_freetype_libs]) + +CC="$SAVED_CC" +CPP="$SAVED_CPP" +CFLAGS="$SAVED_CFLAGS" +CPPFLAGS="$SAVED_CPPFLAGS" + + DJVU_FONT_SOURCE= starfield_excuse= -if test x$enable_grub_mkfont = xno; then - starfield_excuse="No grub-mkfont" +AC_ARG_ENABLE([grub-themes], + [AS_HELP_STRING([--enable-grub-themes], + [build and install GRUB themes (default=guessed)])]) +if test x"$enable_grub_themes" = xno ; then + starfield_excuse="explicitly disabled" +fi + +if test x"$starfield_excuse" = x && test x"$enable_build_grub_mkfont" = xno ; then + starfield_excuse="No build-time grub-mkfont" fi if test x"$starfield_excuse" = x; then @@ -953,8 +1168,38 @@ if test x"$starfield_excuse" = x; then fi fi +if test x"$enable_grub_themes" = xyes && test x"$starfield_excuse" != x; then + AC_MSG_ERROR([themes were explicitly requested but requirements are not satisfied]) +fi + AC_SUBST([DJVU_FONT_SOURCE]) +FONT_SOURCE= + +for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do + for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont /usr/share/fonts/uni /usr/share/fonts/truetype/unifont /usr/share/fonts/misc; do + if test -f "$dir/unifont.$ext"; then + FONT_SOURCE="$dir/unifont.$ext" + break 2 + fi + done +done + +if test x"$enable_build_grub_mkfont" = xno ; then + FONT_SOURCE= +fi + +if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$target_cpu"-"$platform" = xpowerpc-ieee1275 ); then + AC_MSG_ERROR([qemu, powerpc-ieee1275 and loongson ports need unifont]) +fi + +AC_SUBST([FONT_SOURCE]) + +if test x"$FONT_SOURCE" = x && test x"$DJVU_FONT_SOURCE" = x && test x"$grub_build_mkfont_excuse" = x; then + grub_build_mkfont_excuse="no fonts" +fi + + AC_ARG_ENABLE([grub-mount], [AS_HELP_STRING([--enable-grub-mount], [build and install the `grub-mount' utility (default=guessed)])]) @@ -1029,10 +1274,32 @@ fi AC_SUBST([LIBGEOM]) +AC_ARG_ENABLE([liblzma], + [AS_HELP_STRING([--enable-liblzma], + [enable liblzma integration (default=guessed)])]) +if test x"$enable_liblzma" = xno ; then + liblzma_excuse="explicitly disabled" +fi + +if test x"$liblzma_excuse" = x ; then AC_CHECK_LIB([lzma], [lzma_code], - [LIBLZMA="-llzma" - AC_DEFINE([HAVE_LIBLZMA], [1], - [Define to 1 if you have the LZMA library.])],) + [],[liblzma_excuse="need lzma library"]) +fi +if test x"$liblzma_excuse" = x ; then +AC_CHECK_HEADER([lzma.h], [], [liblzma_excuse="need lzma header"]) +fi + +if test x"$enable_liblzma" = xyes && test x"$liblzma_excuse" != x ; then + AC_MSG_ERROR([liblzma support was explicitly requested but requirements are not satisfied]) +fi + + +if test x"$liblzma_excuse" = x ; then + LIBLZMA="-llzma" + AC_DEFINE([USE_LIBLZMA], [1], + [Define to 1 if you have the LZMA library.]) +fi + AC_SUBST([LIBLZMA]) AC_ARG_ENABLE([libzfs], @@ -1054,7 +1321,7 @@ if test x"$libzfs_excuse" = x ; then fi if test x"$libzfs_excuse" = x ; then - AC_CHECK_LIB([nvpair], [nvlist_print], + AC_CHECK_LIB([nvpair], [nvlist_lookup_string], [], [libzfs_excuse="need nvpair library"]) fi @@ -1146,14 +1413,63 @@ AC_SUBST(BSS_START_SYMBOL) AC_SUBST(END_SYMBOL) AC_SUBST(PACKAGE) AC_SUBST(VERSION) -AC_SUBST(NEED_ENABLE_EXECUTE_STACK) AC_SUBST(NEED_REGISTER_FRAME_INFO) +AC_ARG_ENABLE([werror], + [AS_HELP_STRING([--disable-werror], + [do not use -Werror when building GRUB])]) +if test x"$enable_werror" != xno ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Werror" + HOST_CFLAGS="$HOST_CFLAGS -Werror" +fi + +if test "x$grub_cv_cc_target_clang" = xno; then + TARGET_LDFLAGS_STATIC_LIBGCC="-static-libgcc" +else + TARGET_LDFLAGS_STATIC_LIBGCC= +fi + +TARGET_CPP="$TARGET_CC -E" +TARGET_CCAS=$TARGET_CC + +GRUB_TARGET_CPU="${target_cpu}" +GRUB_PLATFORM="${platform}" + +AC_SUBST(GRUB_TARGET_CPU) +AC_SUBST(GRUB_PLATFORM) + +AC_SUBST(TARGET_OBJCONV) +AC_SUBST(TARGET_LIBGCC) +AC_SUBST(TARGET_LDFLAGS_STATIC_LIBGCC) +AC_SUBST(TARGET_CPP) +AC_SUBST(TARGET_CCAS) +AC_SUBST(TARGET_OBJ2ELF) +AC_SUBST(TARGET_APPLE_CC) +AC_SUBST(TARGET_MODULE_FORMAT) + +AC_SUBST(TARGET_CFLAGS) +AC_SUBST(TARGET_LDFLAGS) +AC_SUBST(TARGET_CPPFLAGS) +AC_SUBST(TARGET_CCASFLAGS) + +AC_SUBST(TARGET_IMG_LDSCRIPT) +AC_SUBST(TARGET_IMG_LDFLAGS) +AC_SUBST(TARGET_IMG_CFLAGS) +AC_SUBST(TARGET_IMG_BASE_LDOPT) + +AC_SUBST(HOST_CFLAGS) +AC_SUBST(HOST_LDFLAGS) +AC_SUBST(HOST_CPPFLAGS) +AC_SUBST(HOST_CCASFLAGS) + +AC_SUBST(BUILD_LIBM) + # # Automake conditionals # AM_CONDITIONAL([COND_emu], [test x$platform = xemu]) +AM_CONDITIONAL([COND_clang], [test x$grub_cv_cc_target_clang = xyes]) AM_CONDITIONAL([COND_i386_pc], [test x$target_cpu = xi386 -a x$platform = xpc]) AM_CONDITIONAL([COND_i386_efi], [test x$target_cpu = xi386 -a x$platform = xefi]) AM_CONDITIONAL([COND_ia64_efi], [test x$target_cpu = xia64 -a x$platform = xefi]) @@ -1162,14 +1478,19 @@ AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = AM_CONDITIONAL([COND_i386_coreboot], [test x$target_cpu = xi386 -a x$platform = xcoreboot]) AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = xmultiboot]) AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_i386_xen], [test x$target_cpu = xi386 -a x$platform = xxen]) +AM_CONDITIONAL([COND_x86_64_xen], [test x$target_cpu = xx86_64 -a x$platform = xxen]) AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmipsel -a x$platform = xloongson]) AM_CONDITIONAL([COND_mips_qemu_mips], [test "(" x$target_cpu = xmips -o x$target_cpu = xmipsel ")" -a x$platform = xqemu_mips]) -AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc]) +AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu = xmipsel ")" -a x$platform = xarc]) AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) +AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ]) +AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot]) +AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) @@ -1186,13 +1507,15 @@ AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) -AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1]) +AM_CONDITIONAL([COND_ENABLE_BOOT_TIME_STATS], [test x$BOOT_TIME_STATS = x1]) + +AM_CONDITIONAL([COND_HAVE_CXX], [test x$HAVE_CXX = xyes]) AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) -AM_CONDITIONAL([COND_CYGWIN], [test x$host_os = xcygwin]) +AM_CONDITIONAL([COND_CYGWIN], [test x$target_os = xcygwin]) AM_CONDITIONAL([COND_STARFIELD], [test "x$starfield_excuse" = x]) # Output files. @@ -1262,6 +1585,13 @@ echo With disk cache statistics: Yes else echo With disk cache statistics: No fi + +if [ x"$enable_boot_time" = xyes ]; then +echo With boot time statistics: Yes +else +echo With boot time statistics: No +fi + if [ x"$efiemu_excuse" = x ]; then echo efiemu runtime: Yes else @@ -1287,6 +1617,22 @@ echo With libzfs support: Yes else echo With libzfs support: No "($libzfs_excuse)" fi +if [ x"$grub_build_mkfont_excuse" = x ]; then + echo Build-time grub-mkfont: Yes + if test "x$FONT_SOURCE" = x ; then + echo "Without unifont" + else + echo "With unifont from $FONT_SOURCE" + fi +else + echo Build-time grub-mkfont: No "($grub_build_mkfont_excuse)" + echo "Without unifont (no build-time grub-mkfont)" +fi +if test x"$liblzma_excuse" != x ; then +echo "Without liblzma (no support for XZ-compressed mips images) ($liblzma_excuse)" +else +echo "With liblzma from $LIBLZMA (support for XZ-compressed mips images)" +fi if [ x"$enable_quiet_boot" = xyes ]; then echo With quiet boot: Yes else diff --git a/debian/changelog b/debian/changelog index 6a9fc99b5..a431c1919 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +grub2 (2.00+20131114-1) UNRELEASED; urgency=low + + * New upstream snapshot. + + -- Colin Watson Fri, 15 Nov 2013 10:18:57 +0000 + grub2 (2.00-20) unstable; urgency=low * Backport from upstream: diff --git a/debian/patches/acpihalt_improvements.patch b/debian/patches/acpihalt_improvements.patch deleted file mode 100644 index 3a9b5d304..000000000 --- a/debian/patches/acpihalt_improvements.patch +++ /dev/null @@ -1,191 +0,0 @@ -Description: acpihalt: expand parser to handle SSDTs and some more opcodes -Author: Colin Watson -Forwarded: https://lists.gnu.org/archive/html/grub-devel/2013-03/msg00060.html -Last-Update: 2013-05-09 - -Index: b/grub-core/commands/acpihalt.c -=================================================================== ---- a/grub-core/commands/acpihalt.c -+++ b/grub-core/commands/acpihalt.c -@@ -41,6 +41,7 @@ - #endif - - #ifndef GRUB_DSDT_TEST -+#include - #include - #include - #include -@@ -146,6 +147,10 @@ - ptr += skip_name_string (ptr, end); - ptr++; - break; -+ case GRUB_ACPI_EXTOPCODE_EVENT_OP: -+ ptr++; -+ ptr += skip_name_string (ptr, end); -+ break; - case GRUB_ACPI_EXTOPCODE_OPERATION_REGION: - ptr++; - ptr += skip_name_string (ptr, end); -@@ -158,7 +163,12 @@ - return 0; - break; - case GRUB_ACPI_EXTOPCODE_FIELD_OP: -+ case GRUB_ACPI_EXTOPCODE_DEVICE_OP: -+ case GRUB_ACPI_EXTOPCODE_PROCESSOR_OP: -+ case GRUB_ACPI_EXTOPCODE_POWER_RES_OP: -+ case GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP: - case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP: -+ case GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP: - ptr++; - ptr += decode_length (ptr, 0); - break; -@@ -170,12 +180,14 @@ - } - - static int --get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) -+get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, -+ grub_uint8_t *scope, int scope_len) - { -- grub_uint8_t *ptr, *prev = table; -- int sleep_type = -1; -+ grub_uint8_t *prev = table; -+ int sleep_type = -2; - -- ptr = table + sizeof (struct grub_acpi_table_header); -+ if (!ptr) -+ ptr = table + sizeof (struct grub_acpi_table_header); - while (ptr < end && prev < ptr) - { - int add; -@@ -202,7 +214,8 @@ - } - case GRUB_ACPI_OPCODE_NAME: - ptr++; -- if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0) -+ if ((!scope || memcmp (scope, "\\", scope_len) == 0) && -+ (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0)) - { - int ll; - grub_uint8_t *ptr2 = ptr; -@@ -241,6 +254,25 @@ - return -1; - break; - case GRUB_ACPI_OPCODE_SCOPE: -+ { -+ int scope_sleep_type; -+ int ll; -+ grub_uint8_t *name; -+ int name_len; -+ -+ ptr++; -+ add = decode_length (ptr, &ll); -+ name = ptr + ll; -+ name_len = skip_name_string (name, ptr + add); -+ if (!name_len) -+ return -1; -+ scope_sleep_type = get_sleep_type (table, name + name_len, -+ ptr + add, name, name_len); -+ if (scope_sleep_type != -2) -+ return scope_sleep_type; -+ ptr += add; -+ break; -+ } - case GRUB_ACPI_OPCODE_IF: - case GRUB_ACPI_OPCODE_METHOD: - { -@@ -291,7 +323,7 @@ - return 2; - } - -- printf ("Sleep type = %d\n", get_sleep_type (buf, buf + len)); -+ printf ("Sleep type = %d\n", get_sleep_type (buf, NULL, buf + len, NULL, 0)); - free (buf); - fclose (f); - return 0; -@@ -304,8 +336,10 @@ - { - struct grub_acpi_rsdp_v20 *rsdp2; - struct grub_acpi_rsdp_v10 *rsdp1; -- struct grub_acpi_table_header *rsdt; -- grub_uint32_t *entry_ptr; -+ struct grub_acpi_table_header *rsdt; -+ grub_uint32_t *entry_ptr; -+ grub_uint32_t port = 0; -+ int sleep_type = -1; - - rsdp2 = grub_acpi_get_rsdpv2 (); - if (rsdp2) -@@ -324,33 +358,39 @@ - { - if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0) - { -- grub_uint32_t port; - struct grub_acpi_fadt *fadt - = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr); - struct grub_acpi_table_header *dsdt - = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr; -- int sleep_type = -1; -+ grub_uint8_t *buf = (grub_uint8_t *) dsdt; - - port = fadt->pm1a; - - grub_dprintf ("acpi", "PM1a port=%x\n", port); - - if (grub_memcmp (dsdt->signature, "DSDT", -- sizeof (dsdt->signature)) != 0) -- break; -+ sizeof (dsdt->signature)) == 0) -+ sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length, -+ NULL, 0); -+ } -+ else if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "SSDT", 4) == 0) -+ { -+ struct grub_acpi_table_header *ssdt -+ = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; -+ grub_uint8_t *buf = (grub_uint8_t *) ssdt; - -- sleep_type = get_sleep_type ((grub_uint8_t *) dsdt, -- (grub_uint8_t *) dsdt + dsdt->length); -+ grub_dprintf ("acpi", "SSDT = %p\n", ssdt); - -- if (sleep_type < 0 || sleep_type >= 8) -- break; -+ sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0); -+ } -+ } - -- grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", -- sleep_type, port); -+ if (port && sleep_type >= 0 && sleep_type < 8) -+ { -+ grub_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_outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), -+ port & 0xffff); - } - - grub_millisleep (1500); -Index: b/include/grub/acpi.h -=================================================================== ---- a/include/grub/acpi.h -+++ b/include/grub/acpi.h -@@ -174,9 +174,15 @@ - enum - { - GRUB_ACPI_EXTOPCODE_MUTEX = 0x01, -+ GRUB_ACPI_EXTOPCODE_EVENT_OP = 0x02, - GRUB_ACPI_EXTOPCODE_OPERATION_REGION = 0x80, - GRUB_ACPI_EXTOPCODE_FIELD_OP = 0x81, -+ GRUB_ACPI_EXTOPCODE_DEVICE_OP = 0x82, -+ GRUB_ACPI_EXTOPCODE_PROCESSOR_OP = 0x83, -+ GRUB_ACPI_EXTOPCODE_POWER_RES_OP = 0x84, -+ GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP = 0x85, - GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP = 0x86, -+ GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP = 0x87, - }; - - #endif /* ! GRUB_ACPI_HEADER */ diff --git a/debian/patches/blacklist_1440x900x32.patch b/debian/patches/blacklist_1440x900x32.patch index 40c9d41f2..1c383f46a 100644 --- a/debian/patches/blacklist_1440x900x32.patch +++ b/debian/patches/blacklist_1440x900x32.patch @@ -2,13 +2,13 @@ Description: Blacklist 1440x900x32 from VBE preferred mode handling Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/701111 Forwarded: no -Last-Update: 2013-01-03 +Last-Update: 2013-11-14 Index: b/grub-core/video/i386/pc/vbe.c =================================================================== --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c -@@ -1055,6 +1055,15 @@ +@@ -1053,6 +1053,15 @@ || vbe_mode_info.y_resolution > height) /* Resolution exceeds that of preferred mode. */ continue; diff --git a/debian/patches/core_in_fs.patch b/debian/patches/core_in_fs.patch index 30b06b2b9..691866511 100644 --- a/debian/patches/core_in_fs.patch +++ b/debian/patches/core_in_fs.patch @@ -1,16 +1,17 @@ -Index: b/util/grub-setup.c +Index: b/util/setup.c =================================================================== ---- a/util/grub-setup.c -+++ b/util/grub-setup.c -@@ -85,6 +85,7 @@ +--- a/util/setup.c ++++ b/util/setup.c +@@ -58,6 +58,8 @@ + + #include - #define DEFAULT_BOOT_FILE "boot.img" - #define DEFAULT_CORE_FILE "core.img" +#define CORE_IMG_IN_FS "setup_left_core_image_in_filesystem" - - #ifdef GRUB_SETUP_SPARC64 - #define grub_target_to_host16(x) grub_be_to_cpu16(x) -@@ -556,6 +557,8 @@ ++ + /* On SPARC this program fills in various fields inside of the 'boot' and 'core' + * image files. + * +@@ -577,6 +579,8 @@ grub_free (sectors); @@ -19,13 +20,13 @@ Index: b/util/grub-setup.c goto finish; } -@@ -598,6 +601,9 @@ +@@ -619,6 +623,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); + - /* 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); + grub_util_biosdisk_flush (root_dev->disk); + + /* Clean out the blocklists. */ diff --git a/debian/patches/default_grub_d.patch b/debian/patches/default_grub_d.patch index 08834792c..45dc7299c 100644 --- a/debian/patches/default_grub_d.patch +++ b/debian/patches/default_grub_d.patch @@ -2,13 +2,13 @@ Description: Read /etc/default/grub.d/*.cfg after /etc/default/grub Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/901600 Forwarded: no -Last-Update: 2013-01-02 +Last-Update: 2013-11-14 Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -68,6 +68,11 @@ +@@ -46,6 +46,11 @@ if test -f "${sysconfdir}/default/grub" ; then . "${sysconfdir}/default/grub" fi @@ -24,7 +24,7 @@ Index: b/util/grub-mkconfig.in =================================================================== --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in -@@ -150,6 +150,11 @@ +@@ -149,6 +149,11 @@ if test -f ${sysconfdir}/default/grub ; then . ${sysconfdir}/default/grub fi diff --git a/debian/patches/disable_floppies.patch b/debian/patches/disable_floppies.patch index 16c6fe27b..f539b8468 100644 --- a/debian/patches/disable_floppies.patch +++ b/debian/patches/disable_floppies.patch @@ -7,7 +7,7 @@ Index: b/grub-core/kern/emu/hostdisk.c =================================================================== --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c -@@ -1331,6 +1331,18 @@ +@@ -532,6 +532,18 @@ continue; } @@ -23,6 +23,6 @@ Index: b/grub-core/kern/emu/hostdisk.c + } + } + - #ifdef __linux__ /* On Linux, the devfs uses symbolic links horribly, and that confuses the interface very much, so use realpath to expand + symbolic links. */ diff --git a/debian/patches/dpkg_version_comparison.patch b/debian/patches/dpkg_version_comparison.patch index d835eae42..3a99ba813 100644 --- a/debian/patches/dpkg_version_comparison.patch +++ b/debian/patches/dpkg_version_comparison.patch @@ -7,7 +7,7 @@ Index: b/util/grub-mkconfig_lib.in =================================================================== --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in -@@ -229,8 +229,9 @@ +@@ -235,8 +235,9 @@ version_test_gt () { @@ -19,7 +19,7 @@ Index: b/util/grub-mkconfig_lib.in version_test_gt_cmp=gt if [ "x$version_test_gt_b" = "x" ] ; then return 0 -@@ -240,7 +241,7 @@ +@@ -246,7 +247,7 @@ *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;; *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;; esac diff --git a/debian/patches/efi_disk_cache.patch b/debian/patches/efi_disk_cache.patch deleted file mode 100644 index cb58155f8..000000000 --- a/debian/patches/efi_disk_cache.patch +++ /dev/null @@ -1,26 +0,0 @@ -Description: Bump the values of GRUB_DISK_CACHE_SIZE and GRUB_DISK_CACHE_BITS - on EFI systems (and only on EFI sytems) to dramatically reduce the load times - for vmlinux and initrd. Forwarding this isn't required as upstream trunk - has completely rewritten how this all works. -Author: Adam Conrad -Origin: other, http://blog.fpmurphy.com/2010/03/grub2-efi-support.html -Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/944347 -Forwarded: not-needed -Last-Update: 2012-03-05 - -Index: b/include/grub/disk.h -=================================================================== ---- a/include/grub/disk.h -+++ b/include/grub/disk.h -@@ -146,7 +146,11 @@ - - /* The size of a disk cache in 512B units. Must be at least as big as the - largest supported sector size, currently 16K. */ -+#ifdef GRUB_MACHINE_EFI -+#define GRUB_DISK_CACHE_BITS 10 -+#else - #define GRUB_DISK_CACHE_BITS 6 -+#endif - #define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS) - - /* Return value of grub_disk_get_size() in case disk size is unknown. */ diff --git a/debian/patches/efi_mmap_size.patch b/debian/patches/efi_mmap_size.patch deleted file mode 100644 index a215b4158..000000000 --- a/debian/patches/efi_mmap_size.patch +++ /dev/null @@ -1,37 +0,0 @@ -Description: Don't decrease efi_mmap_size -Author: Vladimir Serbinenko -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4545 -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1046429 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4545 -Last-Update: 2012-09-06 - -Index: b/grub-core/loader/i386/linux.c -=================================================================== ---- a/grub-core/loader/i386/linux.c -+++ b/grub-core/loader/i386/linux.c -@@ -118,12 +118,13 @@ - int ret; - grub_efi_memory_descriptor_t *mmap; - grub_efi_uintn_t desc_size; -+ grub_efi_uintn_t cur_mmap_size = mmap_size; - -- mmap = grub_malloc (mmap_size); -+ mmap = grub_malloc (cur_mmap_size); - if (! mmap) - return 0; - -- ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); -+ ret = grub_efi_get_memory_map (&cur_mmap_size, mmap, 0, &desc_size, 0); - grub_free (mmap); - - if (ret < 0) -@@ -134,6 +135,8 @@ - else if (ret > 0) - break; - -+ if (mmap_size < cur_mmap_size) -+ mmap_size = cur_mmap_size; - mmap_size += (1 << 12); - } - diff --git a/debian/patches/efidisk_non_512_sectors.patch b/debian/patches/efidisk_non_512_sectors.patch deleted file mode 100644 index 823e23f7c..000000000 --- a/debian/patches/efidisk_non_512_sectors.patch +++ /dev/null @@ -1,56 +0,0 @@ -Description: Handle partitions on non-512B EFI disks -Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4795 -Author: Peter Jones -Author: Vladimir Serbinenko -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1065281 -Forwarded: not-needed -Last-Update: 2013-09-18 - -Index: b/grub-core/disk/efi/efidisk.c -=================================================================== ---- a/grub-core/disk/efi/efidisk.c -+++ b/grub-core/disk/efi/efidisk.c -@@ -668,9 +668,11 @@ - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) - == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) - && (grub_partition_get_start (disk->partition) -- == hd.partition_start) -+ == (hd.partition_start << (disk->log_sector_size -+ - GRUB_DISK_SECTOR_BITS))) - && (grub_partition_get_len (disk->partition) -- == hd.partition_size)) -+ == (hd.partition_size << (disk->log_sector_size -+ - GRUB_DISK_SECTOR_BITS)))) - { - handle = c->handle; - return 1; -@@ -763,11 +765,14 @@ - auto int find_partition (grub_disk_t disk, const grub_partition_t part); - - /* Find the identical partition. */ -- int find_partition (grub_disk_t disk __attribute__ ((unused)), -- const grub_partition_t part) -+ int find_partition (grub_disk_t disk, const grub_partition_t part) - { -- if (grub_partition_get_start (part) == hd.partition_start -- && grub_partition_get_len (part) == hd.partition_size) -+ if (grub_partition_get_start (part) -+ == (hd.partition_start << (disk->log_sector_size -+ - GRUB_DISK_SECTOR_BITS)) -+ && grub_partition_get_len (part) -+ == (hd.partition_size << (disk->log_sector_size -+ - GRUB_DISK_SECTOR_BITS))) - { - partition_name = grub_partition_get_name (part); - return 1; -@@ -799,7 +804,9 @@ - /* Find a partition which matches the hard drive device path. */ - grub_memcpy (&hd, ldp, sizeof (hd)); - if (hd.partition_start == 0 -- && hd.partition_size == grub_disk_get_size (parent)) -+ && (hd.partition_size << (parent->log_sector_size -+ - GRUB_DISK_SECTOR_BITS)) -+ == grub_disk_get_size (parent)) - { - dev_name = grub_strdup (parent->name); - } diff --git a/debian/patches/efifwsetup.patch b/debian/patches/efifwsetup.patch deleted file mode 100644 index 5b1e1ae96..000000000 --- a/debian/patches/efifwsetup.patch +++ /dev/null @@ -1,241 +0,0 @@ -Description: Add efifwsetup module to reboot into firmware setup menu -Author: Peter Jones -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4575 -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4579 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4575 -Last-Update: 2012-09-19 - -Index: b/grub-core/Makefile.core.def -=================================================================== ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -573,6 +573,12 @@ - }; - - module = { -+ name = efifwsetup; -+ efi = commands/efi/efifwsetup.c; -+ enable = efi; -+}; -+ -+module = { - name = blocklist; - common = commands/blocklist.c; - }; -Index: b/grub-core/commands/efi/efifwsetup.c -=================================================================== ---- /dev/null -+++ b/grub-core/commands/efi/efifwsetup.c -@@ -0,0 +1,90 @@ -+/* fwsetup.c - Reboot into firmware setup menu. */ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2012 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+static grub_err_t -+grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), -+ int argc __attribute__ ((unused)), -+ char **args __attribute__ ((unused))) -+{ -+ grub_efi_uint64_t *old_os_indications; -+ grub_efi_uint64_t os_indications = GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI; -+ grub_err_t status; -+ grub_size_t oi_size; -+ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; -+ -+ old_os_indications = grub_efi_get_variable ("OsIndications", &global, -+ &oi_size); -+ -+ if (old_os_indications != NULL && oi_size == sizeof (os_indications)) -+ os_indications |= *old_os_indications; -+ -+ status = grub_efi_set_variable ("OsIndications", &global, &os_indications, -+ sizeof (os_indications)); -+ if (status != GRUB_ERR_NONE) -+ return status; -+ -+ grub_reboot (); -+ -+ return GRUB_ERR_BUG; -+} -+ -+static grub_command_t cmd = NULL; -+ -+static grub_efi_boolean_t -+efifwsetup_is_supported (void) -+{ -+ grub_efi_uint64_t *os_indications_supported = NULL; -+ grub_size_t oi_size = 0; -+ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; -+ -+ os_indications_supported = grub_efi_get_variable ("OsIndicationsSupported", -+ &global, &oi_size); -+ -+ if (!os_indications_supported) -+ return 0; -+ -+ if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) -+ return 1; -+ -+ return 0; -+} -+ -+GRUB_MOD_INIT (efifwsetup) -+{ -+ if (efifwsetup_is_supported ()) -+ cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, -+ N_("Reboot into firmware setup menu.")); -+ -+} -+ -+GRUB_MOD_FINI (efifwsetup) -+{ -+ if (cmd) -+ grub_unregister_command (cmd); -+} -Index: b/grub-core/efiemu/runtime/efiemu.c -=================================================================== ---- a/grub-core/efiemu/runtime/efiemu.c -+++ b/grub-core/efiemu/runtime/efiemu.c -@@ -78,7 +78,7 @@ - - grub_efi_status_t - efiemu_set_variable (grub_efi_char16_t *variable_name, -- grub_efi_guid_t *vendor_guid, -+ const grub_efi_guid_t *vendor_guid, - grub_efi_uint32_t attributes, - grub_efi_uintn_t data_size, - void *data); -@@ -131,11 +131,11 @@ - - /* Some standard functions because we need to be standalone */ - static void --efiemu_memcpy (void *to, void *from, int count) -+efiemu_memcpy (void *to, const void *from, int count) - { - int i; - for (i = 0; i < count; i++) -- ((grub_uint8_t *) to)[i] = ((grub_uint8_t *) from)[i]; -+ ((grub_uint8_t *) to)[i] = ((const grub_uint8_t *) from)[i]; - } - - static int -@@ -503,10 +503,10 @@ - - grub_efi_status_t - EFI_FUNC (efiemu_set_variable) (grub_efi_char16_t *variable_name, -- grub_efi_guid_t *vendor_guid, -- grub_efi_uint32_t attributes, -- grub_efi_uintn_t data_size, -- void *data) -+ const grub_efi_guid_t *vendor_guid, -+ grub_efi_uint32_t attributes, -+ grub_efi_uintn_t data_size, -+ void *data) - { - struct efi_variable *efivar; - grub_uint8_t *ptr; -Index: b/grub-core/kern/efi/efi.c -=================================================================== ---- a/grub-core/kern/efi/efi.c -+++ b/grub-core/kern/efi/efi.c -@@ -181,6 +181,36 @@ - return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed"); - } - -+grub_err_t -+grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, -+ void *data, grub_size_t datasize) -+{ -+ grub_efi_status_t status; -+ grub_efi_runtime_services_t *r; -+ grub_efi_char16_t *var16; -+ grub_size_t len, len16; -+ -+ len = grub_strlen (var); -+ len16 = len * GRUB_MAX_UTF16_PER_UTF8; -+ var16 = grub_malloc ((len16 + 1) * sizeof (var16[0])); -+ if (!var16) -+ return grub_errno; -+ len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL); -+ var16[len16] = 0; -+ -+ r = grub_efi_system_table->runtime_services; -+ -+ status = efi_call_5 (r->set_variable, var16, guid, -+ (GRUB_EFI_VARIABLE_NON_VOLATILE -+ | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS -+ | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), -+ datasize, data); -+ if (status == GRUB_EFI_SUCCESS) -+ return GRUB_ERR_NONE; -+ -+ return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var); -+} -+ - void * - grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, - grub_size_t *datasize_out) -Index: b/include/grub/efi/api.h -=================================================================== ---- a/include/grub/efi/api.h -+++ b/include/grub/efi/api.h -@@ -58,6 +58,8 @@ - #define GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 - #define GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE 0x00000020 - -+#define GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL -+ - #define GRUB_EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 - #define GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 - #define GRUB_EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 -@@ -1066,7 +1068,7 @@ - - grub_efi_status_t - (*set_variable) (grub_efi_char16_t *variable_name, -- grub_efi_guid_t *vendor_guid, -+ const grub_efi_guid_t *vendor_guid, - grub_efi_uint32_t attributes, - grub_efi_uintn_t data_size, - void *data); -Index: b/include/grub/efi/efi.h -=================================================================== ---- a/include/grub/efi/efi.h -+++ b/include/grub/efi/efi.h -@@ -64,6 +64,11 @@ - void *EXPORT_FUNC (grub_efi_get_variable) (const char *variable, - const grub_efi_guid_t *guid, - grub_size_t *datasize_out); -+grub_err_t -+EXPORT_FUNC (grub_efi_set_variable) (const char *var, -+ const grub_efi_guid_t *guid, -+ void *data, -+ grub_size_t datasize); - int - EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, - const grub_efi_device_path_t *dp2); diff --git a/debian/patches/emu_freebsd.patch b/debian/patches/emu_freebsd.patch deleted file mode 100644 index 420fb2585..000000000 --- a/debian/patches/emu_freebsd.patch +++ /dev/null @@ -1,88 +0,0 @@ -Description: Fix grub-emu build on FreeBSD -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4587 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4587 -Last-Update: 2012-09-22 - -Index: b/Makefile.util.def -=================================================================== ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -266,7 +266,7 @@ - ldadd = libgrubgcry.a; - ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; -- ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; -+ ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) -lfuse'; - condition = COND_GRUB_MOUNT; - }; - -Index: b/grub-core/net/drivers/emu/emunet.c -=================================================================== ---- a/grub-core/net/drivers/emu/emunet.c -+++ b/grub-core/net/drivers/emu/emunet.c -@@ -21,8 +21,10 @@ - #include - #include - #include --#include --#include -+#ifdef __linux__ -+# include -+# include -+#endif /* __linux__ */ - #include - #include - #include -@@ -97,6 +99,7 @@ - - GRUB_MOD_INIT(emunet) - { -+#ifdef __linux__ - struct ifreq ifr; - fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); - if (fd < 0) -@@ -110,6 +113,10 @@ - return; - } - grub_net_card_register (&emucard); -+#else /* !__linux__ */ -+ fd = -1; -+ return; -+#endif /* __linux__ */ - } - - GRUB_MOD_FINI(emunet) -Index: b/util/getroot.c -=================================================================== ---- a/util/getroot.c -+++ b/util/getroot.c -@@ -220,6 +220,9 @@ - - #if !defined (__MINGW32__) && !defined (__CYGWIN__) && !defined (__GNU__) - -+#if (defined (__linux__) || \ -+ !defined (HAVE_LIBZFS) || !defined (HAVE_LIBNVPAIR)) -+ - static pid_t - exec_pipe (char **argv, int *fd) - { -@@ -258,6 +261,8 @@ - } - } - -+#endif -+ - static char ** - find_root_devices_from_poolname (char *poolname) - { -@@ -269,7 +274,7 @@ - zpool_handle_t *zpool; - libzfs_handle_t *libzfs; - nvlist_t *config, *vdev_tree; -- nvlist_t **children, **path; -+ nvlist_t **children; - unsigned int nvlist_count; - unsigned int i; - char *device = 0; diff --git a/debian/patches/fix_powerpc_emu.patch b/debian/patches/fix_powerpc_emu.patch deleted file mode 100644 index 34225550d..000000000 --- a/debian/patches/fix_powerpc_emu.patch +++ /dev/null @@ -1,52 +0,0 @@ -Description: Only fix up powerpc key repeat on IEEE1275 machines. - Fixes powerpc-emu compilation. -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4580 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4580 -Last-Update: 2012-09-14 - -Index: b/grub-core/term/terminfo.c -=================================================================== ---- a/grub-core/term/terminfo.c -+++ b/grub-core/term/terminfo.c -@@ -33,7 +33,7 @@ - #include - #include - #include --#ifdef __powerpc__ -+#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275) - #include - #endif - -@@ -563,7 +563,7 @@ - grub_terminfo_readkey (termi, data->input_buf, - &data->npending, data->readkey); - --#ifdef __powerpc__ -+#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275) - if (data->npending == 1 && data->input_buf[0] == '\e' - && grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_REPEAT) - && grub_get_time_ms () - data->last_key_time < 1000 -@@ -580,7 +580,7 @@ - int ret; - data->npending--; - ret = data->input_buf[0]; --#ifdef __powerpc__ -+#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275) - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_REPEAT)) - { - data->last_key = ret; -Index: b/include/grub/terminfo.h -=================================================================== ---- a/include/grub/terminfo.h -+++ b/include/grub/terminfo.h -@@ -32,7 +32,7 @@ - { - int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN]; - int npending; --#ifdef __powerpc__ -+#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275) - int last_key; - grub_uint64_t last_key_time; - #endif diff --git a/debian/patches/gettext_quiet.patch b/debian/patches/gettext_quiet.patch index 688f33a04..e06b1bc23 100644 --- a/debian/patches/gettext_quiet.patch +++ b/debian/patches/gettext_quiet.patch @@ -2,23 +2,20 @@ Description: Silence error messages when translations are unavailable Author: Colin Watson Bug: https://savannah.gnu.org/bugs/?35880 Forwarded: https://savannah.gnu.org/bugs/?35880 -Last-Update: 2012-09-06 +Last-Update: 2013-11-14 Index: b/grub-core/gettext/gettext.c =================================================================== --- a/grub-core/gettext/gettext.c +++ b/grub-core/gettext/gettext.c -@@ -412,6 +412,14 @@ - - grub_free (lang); - } +@@ -427,6 +427,11 @@ + if (locale[0] == 'e' && locale[1] == 'n' + && (locale[2] == '\0' || locale[2] == '_')) + grub_errno = err = GRUB_ERR_NONE; + + /* If no translations are available, fall back to untranslated text. */ + if (err == GRUB_ERR_FILE_NOT_FOUND) -+ { -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } ++ grub_errno = err = GRUB_ERR_NONE; + return err; } diff --git a/debian/patches/gfxpayload_dynamic.patch b/debian/patches/gfxpayload_dynamic.patch index e29d0e0c3..3b3fa0a41 100644 --- a/debian/patches/gfxpayload_dynamic.patch +++ b/debian/patches/gfxpayload_dynamic.patch @@ -5,13 +5,13 @@ Description: Add configure option to enable gfxpayload=keep dynamically Author: Evan Broder Author: Colin Watson Forwarded: no -Last-Update: 2013-11-13 +Last-Update: 2013-11-15 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1109,6 +1109,17 @@ +@@ -1376,6 +1376,17 @@ fi AC_SUBST([QUICK_BOOT]) @@ -33,7 +33,7 @@ Index: b/grub-core/Makefile.core.def =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -704,6 +704,15 @@ +@@ -888,6 +888,15 @@ }; module = { diff --git a/debian/patches/gnulib_gets.patch b/debian/patches/gnulib_gets.patch deleted file mode 100644 index 7e501fcdc..000000000 --- a/debian/patches/gnulib_gets.patch +++ /dev/null @@ -1,41 +0,0 @@ -Description: Avoid assuming that gets is declared -Origin: backport, http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=66712c23388e93e5c518ebc8515140fa0c807348 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4611 -Last-Update: 2012-12-28 - -Index: b/grub-core/gnulib/stdio.in.h -=================================================================== ---- a/grub-core/gnulib/stdio.in.h -+++ b/grub-core/gnulib/stdio.in.h -@@ -138,10 +138,12 @@ - #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. */ -+ so any use of gets warrants an unconditional warning; besides, C11 -+ removed it. */ - #undef gets -+#if HAVE_RAW_DECL_GETS - _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); -+#endif - - #if @GNULIB_FOPEN@ - # if @REPLACE_FOPEN@ -Index: b/m4/stdio_h.m4 -=================================================================== ---- a/m4/stdio_h.m4 -+++ b/m4/stdio_h.m4 -@@ -35,9 +35,9 @@ - - 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. -+ dnl guaranteed by both C89 and C11. - gl_WARN_ON_USE_PREPARE([[#include -- ]], [dprintf fpurge fseeko ftello getdelim getline popen renameat -+ ]], [dprintf fpurge fseeko ftello getdelim getline gets popen renameat - snprintf tmpfile vdprintf vsnprintf]) - ]) - diff --git a/debian/patches/grub_legacy_0_based_partitions.patch b/debian/patches/grub_legacy_0_based_partitions.patch index 4b616b767..efaadbd0a 100644 --- a/debian/patches/grub_legacy_0_based_partitions.patch +++ b/debian/patches/grub_legacy_0_based_partitions.patch @@ -1,43 +1,31 @@ +Description: Support running grub-probe in grub-legacy's update-grub +Author: Robert Millan +Author: Colin Watson +Forwarded: not-needed +Last-Update: 2013-11-14 + Index: b/util/getroot.c =================================================================== --- a/util/getroot.c +++ b/util/getroot.c -@@ -2144,7 +2144,7 @@ - } - *ptr = 0; - if (dos_part >= 0) -- snprintf (ptr, end - ptr, ",%d", dos_part + 1); -+ snprintf (ptr, end - ptr, ",%d", dos_part + (getenv ("GRUB_LEGACY_0_BASED_PARTITIONS") ? 0 : 1)); - ptr += strlen (ptr); - if (bsd_part >= 0) - snprintf (ptr, end - ptr, ",%d", bsd_part + 1); -@@ -2241,6 +2241,29 @@ +@@ -239,6 +239,20 @@ - if (start == part_start) - { -+ if (getenv ("GRUB_LEGACY_0_BASED_PARTITIONS")) -+ { -+ int dos_part, bsd_part; -+ char *fullname, *comma; + if (ctx->start == part_start) + { ++ /* This is dreadfully hardcoded, but there's a limit to what GRUB ++ Legacy was able to deal with anyway. */ ++ if (getenv ("GRUB_LEGACY_0_BASED_PARTITIONS")) ++ { ++ if (partition->parent) ++ /* Probably a BSD slice. */ ++ ctx->partname = xasprintf ("%d,%d", partition->parent->number, ++ partition->number + 1); ++ else ++ ctx->partname = xasprintf ("%d", partition->number); + -+ if (partition->parent) -+ { -+ dos_part = partition->parent->number; -+ bsd_part = partition->number; -+ } -+ else -+ { -+ dos_part = partition->number; -+ bsd_part = -1; -+ } ++ return 1; ++ } + -+ fullname = make_device_name (drive, dos_part, bsd_part); -+ comma = strchr (fullname, ','); -+ partname = comma ? xstrdup (comma + 1) : NULL; -+ free (fullname); -+ return 1; -+ } -+ - partname = grub_partition_get_name (partition); - return 1; - } + ctx->partname = grub_partition_get_name (partition); + return 1; + } diff --git a/debian/patches/initrd_addr_min.patch b/debian/patches/initrd_addr_min.patch deleted file mode 100644 index 944006179..000000000 --- a/debian/patches/initrd_addr_min.patch +++ /dev/null @@ -1,25 +0,0 @@ -Description: Fix incorrect initrd minimum address calculation - Don't add the initrd size to addr_min, since the initrd will be allocated - after this address. Fixes failure to load initrd on systems where the - 64MiB-128MiB range of physical memory is reserved, such as Windows Azure - guests. -Author: Colin Watson -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1055686 -Forwarded: https://lists.gnu.org/archive/html/grub-devel/2012-10/msg00023.html -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4664 -Last-Update: 2013-01-20 - -Index: b/grub-core/loader/i386/linux.c -=================================================================== ---- a/grub-core/loader/i386/linux.c -+++ b/grub-core/loader/i386/linux.c -@@ -1101,8 +1101,7 @@ - worse than that of Linux 2.3.xx, so avoid the last 64kb. */ - addr_max -= 0x10000; - -- addr_min = (grub_addr_t) prot_mode_target + prot_init_space -- + page_align (size); -+ addr_min = (grub_addr_t) prot_mode_target + prot_init_space; - - /* Put the initrd as high as possible, 4KiB aligned. */ - addr = (addr_max - size) & ~0xFFF; diff --git a/debian/patches/install_bios_setup_path.patch b/debian/patches/install_bios_setup_path.patch index 228b9d043..3583b6391 100644 --- a/debian/patches/install_bios_setup_path.patch +++ b/debian/patches/install_bios_setup_path.patch @@ -2,18 +2,18 @@ Description: Look for grub-bios-setup in /usr/lib/grub/i386-pc/ as well Author: Colin Watson Bug-Debian: http://bugs.debian.org/705636 Forwarded: no -Last-Update: 2013-04-17 +Last-Update: 2013-11-15 Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -363,6 +363,9 @@ +@@ -322,6 +322,9 @@ if test "x$grub_setup" = x && [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = "i386-pc" ]; then - grub_setup="${sbindir}/`echo grub-bios-setup | sed ${transform}`" + grub_setup="${sbindir}/@grub_bios_setup@" + if [ ! -e "$grub_setup" ]; then -+ grub_setup="${source_dir}/`echo grub-bios-setup | sed ${transform}`" ++ grub_setup="${source_dir}/@grub_bios_setup@" + fi fi diff --git a/debian/patches/install_efi_fallback.patch b/debian/patches/install_efi_fallback.patch index ddfbbb61b..8f0303be8 100644 --- a/debian/patches/install_efi_fallback.patch +++ b/debian/patches/install_efi_fallback.patch @@ -5,13 +5,13 @@ Description: Fall back to i386-pc if booted using EFI but -efi is missing better than returning a confusing error. Author: Colin Watson Forwarded: no -Last-Update: 2012-09-14 +Last-Update: 2013-11-14 Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -292,7 +292,8 @@ +@@ -249,7 +249,8 @@ linux*) modprobe -q efivars 2>/dev/null || true ;; esac @@ -21,7 +21,7 @@ Index: b/util/grub-install.in target="x86_64-efi" else target=i386-pc -@@ -308,7 +309,8 @@ +@@ -265,7 +266,8 @@ linux*) modprobe -q efivars 2>/dev/null || true ;; esac diff --git a/debian/patches/install_efi_ubuntu_flavours.patch b/debian/patches/install_efi_ubuntu_flavours.patch index 392736c31..50ea6d03f 100644 --- a/debian/patches/install_efi_ubuntu_flavours.patch +++ b/debian/patches/install_efi_ubuntu_flavours.patch @@ -5,13 +5,13 @@ Description: Cope with Kubuntu setting GRUB_DISTRIBUTOR Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/1242417 Forwarded: not-needed -Last-Update: 2013-11-12 +Last-Update: 2013-11-15 Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -471,6 +471,10 @@ +@@ -434,6 +434,10 @@ # not collide with other vendors. To minimise collisions, we use the # name of our distributor if possible. efi_distributor="$bootloader_id" diff --git a/debian/patches/install_locale_langpack.patch b/debian/patches/install_locale_langpack.patch index 9b71cad09..35e5440bf 100644 --- a/debian/patches/install_locale_langpack.patch +++ b/debian/patches/install_locale_langpack.patch @@ -1,19 +1,28 @@ -Description: Prefer translations from language packs +Description: Prefer translations from Ubuntu language packs if available Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998 Forwarded: not-needed -Last-Update: 2012-09-26 +Last-Update: 2013-11-14 -Index: b/util/grub-install.in +Index: b/util/grub-install_header =================================================================== ---- a/util/grub-install.in -+++ b/util/grub-install.in -@@ -543,7 +543,7 @@ - - # Copy gettext files - mkdir -p "${grubdir}"/locale/ --for dir in "${localedir}"/*; do -+for dir in "${localedir}"/* "${localedir}-langpack"/*; do - if test -f "$dir/LC_MESSAGES/grub.mo"; then - cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" - fi +--- a/util/grub-install_header ++++ b/util/grub-install_header +@@ -118,7 +118,7 @@ + grub_compress_file "$file" "${grub_install_files_target_directory}"/locale/"$(basename "$file")" + fi + done +- for dir in "${localedir}"/*; do ++ for dir in "${localedir}"/* "${localedir}-langpack"/*; do + if test -f "$dir/LC_MESSAGES/@PACKAGE@.mo" && ! test -f "${grub_install_files_target_directory}"/locale/"${dir##*/}.mo"; then + grub_compress_file "$dir/LC_MESSAGES/@PACKAGE@.mo" "${grub_install_files_target_directory}"/locale/"${dir##*/}.mo" + fi +@@ -127,6 +127,8 @@ + for locale in $install_locales; do + if test -f "${grub_install_files_source_directory}"/po/$locale.mo; then + grub_compress_file "${grub_install_files_source_directory}"/po/locale.mo "${grub_install_files_target_directory}"/locale/$locale.mo ++ elif test -f "${localedir}-langpack/$locale/LC_MESSAGES/@PACKAGE@.mo"; then ++ grub_compress_file "${localedir}-langpack/$locale/LC_MESSAGES/@PACKAGE@.mo" "${grub_install_files_target_directory}"/locale/$locale.mo + elif test -f "${localedir}/$locale/LC_MESSAGES/@PACKAGE@.mo"; then + grub_compress_file "${localedir}/$locale/LC_MESSAGES/@PACKAGE@.mo" "${grub_install_files_target_directory}"/locale/$locale.mo + fi diff --git a/debian/patches/install_signed.patch b/debian/patches/install_signed.patch index c1a4ea4cd..b7c147082 100644 --- a/debian/patches/install_signed.patch +++ b/debian/patches/install_signed.patch @@ -3,21 +3,21 @@ Author: Colin Watson Author: Stéphane Graber Author: Steve Langasek Forwarded: no -Last-Update: 2013-11-12 +Last-Update: 2013-11-15 Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -63,6 +63,7 @@ +@@ -41,6 +41,7 @@ removable=no - efi_quiet= + efi_quiet=-q +uefi_secure_boot=yes # Get GRUB_DISTRIBUTOR. if test -f "${sysconfdir}/default/grub" ; then -@@ -117,6 +118,8 @@ +@@ -92,6 +93,8 @@ print_option_help "--removable" "$(gettext "the installation device is removable. This option is only available on EFI.")" print_option_help "--bootloader-id=$(gettext "ID")" "$(gettext "the ID of bootloader. This option is only available on EFI.")" print_option_help "--efi-directory=$(gettext "DIR")" "$(gettext "use DIR as the EFI System Partition root.")" @@ -26,7 +26,7 @@ Index: b/util/grub-install.in echo gettext "INSTALL_DEVICE must be system device filename.";echo echo -@@ -258,6 +261,11 @@ +@@ -215,6 +218,11 @@ -f | --force) setup_force="--force" ;; @@ -38,7 +38,7 @@ Index: b/util/grub-install.in -*) gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 usage -@@ -460,39 +468,32 @@ +@@ -423,43 +431,34 @@ # not collide with other vendors. To minimise collisions, we use the # name of our distributor if possible. efi_distributor="$bootloader_id" @@ -54,6 +54,8 @@ Index: b/util/grub-install.in + # expansion. + ia64) + efi_suffix=ia64 ;; ++ arm) ++ efi_suffix=arm ;; + *) + efi_suffix= ;; + esac @@ -73,6 +75,8 @@ Index: b/util/grub-install.in - # expansion. - ia64) - efi_file=BOOTIA64.EFI ;; +- arm) +- efi_file=BOOTARM.EFI ;; - esac + efi_file="BOOT$(printf %s "$efi_suffix" | tr a-z A-Z).EFI" else @@ -88,14 +92,16 @@ Index: b/util/grub-install.in - # expansion. - ia64) - efi_file=grubia64.efi ;; +- arm) +- efi_file=grubarm.efi ;; - *) - efi_file=grub.efi ;; - esac + efi_file="grub$efi_suffix.efi" - # TODO: We should also use efibootmgr, if available, to add a Boot - # entry for ourselves. fi -@@ -634,7 +635,15 @@ + efidir="$efidir/EFI/$efi_distributor" + mkdir -p "$efidir" || exit 1 +@@ -575,7 +574,15 @@ config_opt_file="${grubdir}/${grub_modinfo_target_cpu}-$grub_modinfo_platform/load.cfg" fi @@ -112,7 +118,7 @@ Index: b/util/grub-install.in if [ x"${install_device}" != x ]; then if echo "${install_device}" | grep -qx "(.*)" ; then install_drive="${install_device}" -@@ -653,7 +662,7 @@ +@@ -594,7 +601,7 @@ install_drive="$grub_drive" fi @@ -121,7 +127,7 @@ Index: b/util/grub-install.in # generic method (used on coreboot and ata mod) uuid= if [ x"$force_file_id" != xy ]; then -@@ -828,10 +837,31 @@ +@@ -776,10 +783,31 @@ gettext "You will have to set \`SystemPartition' and \`OSLoader' manually." 1>&2 echo 1>&2 elif [ x"$grub_modinfo_platform" = xefi ]; then diff --git a/debian/patches/install_stage2_confusion.patch b/debian/patches/install_stage2_confusion.patch index 2f4aef481..29d9a123e 100644 --- a/debian/patches/install_stage2_confusion.patch +++ b/debian/patches/install_stage2_confusion.patch @@ -2,13 +2,13 @@ Description: If GRUB Legacy is still around, tell packaging to ignore it Author: Colin Watson Bug-Debian: http://bugs.debian.org/586143 Forwarded: not-needed -Last-Update: 2010-06-18 +Last-Update: 2013-11-14 Index: b/util/grub-install.in =================================================================== --- a/util/grub-install.in +++ b/util/grub-install.in -@@ -863,6 +863,13 @@ +@@ -823,6 +823,13 @@ echo 1>&2 fi diff --git a/debian/patches/kfreebsd_9.1.patch b/debian/patches/kfreebsd_9.1.patch deleted file mode 100644 index befab6544..000000000 --- a/debian/patches/kfreebsd_9.1.patch +++ /dev/null @@ -1,57 +0,0 @@ -Description: Fix booting FreeBSD >= 9.1 amd64 kernels -Author: Vladimir Serbinenko -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4556 -Bug-Debian: http://bugs.debian.org/699002 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4556 -Last-Update: 2013-01-28 - -Index: b/grub-core/loader/i386/bsd.c -=================================================================== ---- a/grub-core/loader/i386/bsd.c -+++ b/grub-core/loader/i386/bsd.c -@@ -1309,7 +1309,7 @@ - && phdr->p_type != PT_DYNAMIC) - return 0; - -- paddr = phdr->p_paddr & 0xFFFFFF; -+ paddr = phdr->p_paddr & 0xFFFFFFF; - - if (paddr < kern_start) - kern_start = paddr; -@@ -1333,7 +1333,7 @@ - } - - *do_load = 1; -- phdr->p_paddr &= 0xFFFFFF; -+ phdr->p_paddr &= 0xFFFFFFF; - paddr = phdr->p_paddr; - - *addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src); -@@ -1351,7 +1351,7 @@ - && phdr->p_type != PT_DYNAMIC) - return 0; - -- paddr = phdr->p_paddr & 0xffffff; -+ paddr = phdr->p_paddr & 0xfffffff; - - if (paddr < kern_start) - kern_start = paddr; -@@ -1375,7 +1375,7 @@ - } - - *do_load = 1; -- paddr = phdr->p_paddr & 0xffffff; -+ paddr = phdr->p_paddr & 0xfffffff; - - *addr = (grub_addr_t) (paddr - kern_start + (grub_uint8_t *) kern_chunk_src); - -@@ -1394,7 +1394,7 @@ - { - grub_relocator_chunk_t ch; - -- entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; -+ entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFFF; - err = grub_elf32_phdr_iterate (elf, filename, - grub_bsd_elf32_size_hook, NULL); - if (err) diff --git a/debian/patches/linuxefi.patch b/debian/patches/linuxefi.patch index 0ab79964f..e84c3a2b5 100644 --- a/debian/patches/linuxefi.patch +++ b/debian/patches/linuxefi.patch @@ -2,13 +2,13 @@ Description: Add "linuxefi" loader which avoids ExitBootServices Author: Matthew Garrett Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub2-linuxefi.patch Forwarded: no -Last-Update: 2012-10-05 +Last-Update: 2013-11-14 Index: b/grub-core/Makefile.core.def =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -1421,6 +1421,14 @@ +@@ -1681,6 +1681,14 @@ }; module = { diff --git a/debian/patches/linuxefi_amd64_only.patch b/debian/patches/linuxefi_amd64_only.patch index 7ea771dcf..58aa1409d 100644 --- a/debian/patches/linuxefi_amd64_only.patch +++ b/debian/patches/linuxefi_amd64_only.patch @@ -1,13 +1,13 @@ Description: Only build linuxefi on amd64 Author: Colin Watson Forwarded: no -Last-Update: 2012-10-05 +Last-Update: 2013-11-14 Index: b/grub-core/Makefile.core.def =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -1424,7 +1424,6 @@ +@@ -1684,7 +1684,6 @@ name = linuxefi; efi = loader/i386/efi/linux.c; efi = lib/cmdline.c; diff --git a/debian/patches/linuxefi_non_sb_fallback.patch b/debian/patches/linuxefi_non_sb_fallback.patch index e743ef776..59567ad57 100644 --- a/debian/patches/linuxefi_non_sb_fallback.patch +++ b/debian/patches/linuxefi_non_sb_fallback.patch @@ -2,7 +2,7 @@ Description: If running under UEFI secure boot, attempt to use linuxefi loader Author: Colin Watson Author: Steve Langasek Forwarded: no -Last-Update: 2012-10-05 +Last-Update: 2013-11-14 Index: b/grub-core/loader/i386/efi/linux.c =================================================================== @@ -21,7 +21,7 @@ Index: b/grub-core/loader/i386/linux.c =================================================================== --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c -@@ -75,6 +75,8 @@ +@@ -76,6 +76,8 @@ static struct linux_kernel_params linux_params; static char *linux_cmdline; #ifdef GRUB_MACHINE_EFI @@ -30,7 +30,7 @@ Index: b/grub-core/loader/i386/linux.c static grub_efi_uintn_t efi_mmap_size; #else static const grub_size_t efi_mmap_size = 0; -@@ -684,6 +686,41 @@ +@@ -688,6 +690,41 @@ grub_dl_ref (my_mod); @@ -73,8 +73,8 @@ Index: b/grub-core/loader/i386/linux.c { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); @@ -1050,6 +1087,12 @@ - int nfiles = 0; - grub_uint8_t *ptr; + grub_err_t err; + struct grub_linux_initrd_context initrd_ctx; +#ifdef GRUB_MACHINE_EFI + /* If we're using linuxefi, just forward to initrdefi. */ diff --git a/debian/patches/maybe_quiet.patch b/debian/patches/maybe_quiet.patch index c5df5581c..332d80ad8 100644 --- a/debian/patches/maybe_quiet.patch +++ b/debian/patches/maybe_quiet.patch @@ -25,26 +25,26 @@ Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/386922 Bug-Ubuntu: https://bugs.launchpad.net/bugs/861048 Forwarded: (partial) http://lists.gnu.org/archive/html/grub-devel/2009-09/msg00056.html -Last-Update: 2013-08-26 +Last-Update: 2013-11-15 Index: b/config.h.in =================================================================== --- a/config.h.in +++ b/config.h.in -@@ -41,6 +41,8 @@ - #define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@ +@@ -11,6 +11,8 @@ /* Define to 1 to enable disk cache statistics. */ #define DISK_CACHE_STATS @DISK_CACHE_STATS@ + #define BOOT_TIME_STATS @BOOT_TIME_STATS@ +/* Define to 1 to make GRUB quieter at boot time. */ +#define QUIET_BOOT @QUIET_BOOT@ - #define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" - #define GRUB_PLATFORM "@GRUB_PLATFORM@" + #if defined (GRUB_BUILD) + #undef ENABLE_NLS Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1087,6 +1087,17 @@ +@@ -1354,6 +1354,17 @@ fi AC_SUBST([UBUNTU_RECOVERY]) @@ -62,9 +62,9 @@ Index: b/configure.ac LIBS="" AC_SUBST([FONT_SOURCE]) -@@ -1243,5 +1254,10 @@ +@@ -1589,5 +1600,10 @@ else - echo With libzfs support: No "($libzfs_excuse)" + echo "With liblzma from $LIBLZMA (support for XZ-compressed mips images)" fi +if [ x"$enable_quiet_boot" = xyes ]; then +echo With quiet boot: Yes @@ -87,7 +87,7 @@ Index: b/grub-core/boot/i386/pc/boot.S /* * defines for the code go here -@@ -150,9 +153,17 @@ +@@ -242,9 +245,17 @@ /* save drive reference first thing! */ pushw %dx @@ -189,7 +189,7 @@ Index: b/grub-core/kern/main.c =================================================================== --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c -@@ -207,13 +207,23 @@ +@@ -251,15 +251,25 @@ void __attribute__ ((noreturn)) grub_main (void) { @@ -200,6 +200,8 @@ Index: b/grub-core/kern/main.c /* First of all, initialize the machine. */ grub_machine_init (); + grub_boot_time ("After machine init."); + +#ifdef QUIET_BOOT + /* Disable the cursor until we need it. */ + FOR_ACTIVE_TERM_OUTPUTS(term) @@ -211,11 +213,11 @@ Index: b/grub-core/kern/main.c grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); +#endif - /* Load pre-loaded modules and free the space. */ - grub_register_exported_symbols (); -@@ -232,5 +242,12 @@ - grub_load_config (); + +@@ -295,5 +305,12 @@ + grub_boot_time ("After execution of embedded config. Attempt to go to normal mode"); + grub_load_normal_mode (); + +#ifdef QUIET_BOOT @@ -230,7 +232,7 @@ Index: b/grub-core/kern/rescue_reader.c =================================================================== --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c -@@ -77,7 +77,9 @@ +@@ -78,7 +78,9 @@ void __attribute__ ((noreturn)) grub_rescue_run (void) { @@ -244,7 +246,7 @@ Index: b/grub-core/normal/main.c =================================================================== --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c -@@ -399,6 +399,15 @@ +@@ -428,6 +428,15 @@ grub_normal_read_line_real (char **line, int cont, int nested) { const char *prompt; @@ -260,7 +262,7 @@ Index: b/grub-core/normal/main.c if (cont) /* TRANSLATORS: it's command line prompt. */ -@@ -446,7 +455,9 @@ +@@ -476,7 +485,9 @@ return; } @@ -274,7 +276,7 @@ Index: b/grub-core/normal/menu.c =================================================================== --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c -@@ -669,12 +669,18 @@ +@@ -674,12 +674,18 @@ /* Callback invoked immediately before a menu entry is executed. */ static void @@ -294,7 +296,7 @@ Index: b/grub-core/normal/menu.c } /* Callback invoked when a default menu entry executed because of a timeout -@@ -722,6 +728,9 @@ +@@ -727,6 +733,9 @@ int boot_entry; grub_menu_entry_t e; int auto_boot; @@ -304,7 +306,7 @@ Index: b/grub-core/normal/menu.c boot_entry = run_menu (menu, nested, &auto_boot); if (boot_entry < 0) -@@ -731,7 +740,11 @@ +@@ -736,7 +745,11 @@ if (! e) continue; /* Menu is empty. */ diff --git a/debian/patches/mkconfig_emacs_autosave.patch b/debian/patches/mkconfig_emacs_autosave.patch deleted file mode 100644 index b63c0cb9c..000000000 --- a/debian/patches/mkconfig_emacs_autosave.patch +++ /dev/null @@ -1,20 +0,0 @@ -Description: Fix detection of Emacs autosave files -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5089 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5089 -Last-Update: 2013-08-11 - -Index: b/util/grub-mkconfig.in -=================================================================== ---- a/util/grub-mkconfig.in -+++ b/util/grub-mkconfig.in -@@ -253,7 +253,7 @@ - # emacsen backup files. FIXME: support other editors - *~) ;; - # emacsen autosave files. FIXME: support other editors -- \#*\#) ;; -+ */\#*\#) ;; - *) - if grub_file_is_not_garbage "$i" && test -x "$i" ; then - echo diff --git a/debian/patches/mkconfig_hurd_sort.patch b/debian/patches/mkconfig_hurd_sort.patch deleted file mode 100644 index 740f383f6..000000000 --- a/debian/patches/mkconfig_hurd_sort.patch +++ /dev/null @@ -1,31 +0,0 @@ -Description: Sort gnumach kernels in version order -Author: Samuel Thibault -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5232 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5232 -Last-Update: 2013-10-07 - -Index: b/util/grub.d/10_hurd.in -=================================================================== ---- a/util/grub.d/10_hurd.in -+++ b/util/grub.d/10_hurd.in -@@ -153,8 +153,8 @@ - submenu_indentation="" - is_first_entry=true - --for kernel in ${kernels} --do -+while [ "x$kernels" != "x" ] ; do -+ kernel=`version_find_latest $kernels` - - if [ "x$is_first_entry" = xtrue ]; then - hurd_entry "$kernel" simple -@@ -166,6 +166,8 @@ - - hurd_entry "$kernel" advanced - hurd_entry "$kernel" recovery -+ -+ kernels=`echo $kernels | tr ' ' '\n' | grep -vx $kernel | tr '\n' ' '` - is_first_entry=false - done - diff --git a/debian/patches/mkconfig_loopback.patch b/debian/patches/mkconfig_loopback.patch index e07306679..ec913c9db 100644 --- a/debian/patches/mkconfig_loopback.patch +++ b/debian/patches/mkconfig_loopback.patch @@ -13,7 +13,7 @@ Index: b/util/grub-mkconfig_lib.in =================================================================== --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in -@@ -129,6 +129,21 @@ +@@ -130,6 +130,21 @@ esac done @@ -35,9 +35,9 @@ Index: b/util/grub-mkconfig_lib.in if dmsetup status $device 2>/dev/null | grep -q 'crypt[[:space:]]$'; then grub_warn \ "$device is a crypto device, which GRUB cannot read directly. Some" \ -@@ -169,6 +184,14 @@ - echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}" - echo "fi" +@@ -240,6 +255,14 @@ + else + return 1 fi + + if [ "x${loop_file}" != x ]; then @@ -49,7 +49,7 @@ Index: b/util/grub-mkconfig_lib.in + fi } - grub_get_device_id () + version_test_gt () Index: b/util/grub.d/10_linux.in =================================================================== --- a/util/grub.d/10_linux.in diff --git a/debian/patches/mkconfig_mid_upgrade.patch b/debian/patches/mkconfig_mid_upgrade.patch index 49ac497a4..3c58dc33e 100644 --- a/debian/patches/mkconfig_mid_upgrade.patch +++ b/debian/patches/mkconfig_mid_upgrade.patch @@ -8,13 +8,13 @@ Description: Bail out if trying to run grub-mkconfig during upgrade to 2.00 problem. Author: Colin Watson Forwarded: no -Last-Update: 2012-09-13 +Last-Update: 2013-11-14 Index: b/util/grub-mkconfig.in =================================================================== --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in -@@ -99,6 +99,13 @@ +@@ -98,6 +98,13 @@ esac done diff --git a/debian/patches/mkconfig_nonexistent_loopback.patch b/debian/patches/mkconfig_nonexistent_loopback.patch index 62c49067b..c8831716b 100644 --- a/debian/patches/mkconfig_nonexistent_loopback.patch +++ b/debian/patches/mkconfig_nonexistent_loopback.patch @@ -2,13 +2,13 @@ Description: Avoid getting confused by inaccessible loop device backing paths Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/938724 Forwarded: no -Last-Update: 2012-09-07 +Last-Update: 2013-11-14 Index: b/util/grub-mkconfig_lib.in =================================================================== --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in -@@ -138,7 +138,7 @@ +@@ -139,7 +139,7 @@ /dev/*) ;; *) loop_device="${device}" @@ -21,26 +21,26 @@ Index: b/util/grub.d/30_os-prober.in =================================================================== --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in -@@ -169,6 +169,11 @@ +@@ -200,6 +200,11 @@ LINITRD="${LINITRD#/boot}" fi + if [ -z "${prepare_boot_cache}" ]; then -+ prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | sed -e "s/^/\t/")" ++ prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)" + [ "${prepare_boot_cache}" ] || continue + fi + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true counter=1 -@@ -180,10 +185,6 @@ +@@ -211,10 +216,6 @@ fi used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'" - if [ -z "${prepare_boot_cache}" ]; then -- prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | sed -e "s/^/\t/")" +- prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)" - fi - - if [ "x$is_first_entry" = xtrue ]; then + if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then cat << EOF - menuentry '$(echo "$OS" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' { + menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' { diff --git a/debian/patches/mkconfig_overescaping.patch b/debian/patches/mkconfig_overescaping.patch deleted file mode 100644 index 7fea31eee..000000000 --- a/debian/patches/mkconfig_overescaping.patch +++ /dev/null @@ -1,129 +0,0 @@ -Description: Remove extra layer of escaping from grub_probe - Also add missing quoting to various grub.d scripts. -Author: Vladimir Serbinenko -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4558 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4558 -Last-Update: 2012-09-17 - -Index: b/util/grub-mkconfig_lib.in -=================================================================== ---- a/util/grub-mkconfig_lib.in -+++ b/util/grub-mkconfig_lib.in -@@ -288,19 +288,19 @@ - echo "$version_find_latest_a" - } - --# One layer of quotation is eaten by "", the second by sed, and the third by --# printf; so this turns ' into \'. Note that you must use the output of -+# One layer of quotation is eaten by "" and the second by -+# sed; so this turns ' into \'. Note that you must use the output of - # this function in a printf format string. - - grub_quote () { -- sed "s/'/'\\\\\\\\''/g" -+ sed "s/'/'\\\\''/g" - } - - gettext_quoted () { -- gettext "$@" | sed "s/'/'\\\\\\\\''/g" -+ gettext "$@" | grub_quote - } - --# Run the first argument through gettext_quoted, and then pass that and all -+# Run the first argument through gettext, and then pass that and all - # remaining arguments to printf. This is a useful abbreviation and tends to - # be easier to type. - gettext_printf () { -Index: b/util/grub.d/10_hurd.in -=================================================================== ---- a/util/grub.d/10_hurd.in -+++ b/util/grub.d/10_hurd.in -@@ -117,7 +117,7 @@ - opts= - fi - sed "s/^/$submenu_indentation/" << EOF -- echo '$message' -+ echo '$(echo "$message" | grub_quote)' - multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} $opts ${GRUB_CMDLINE_GNUMACH} - EOF - -@@ -133,7 +133,7 @@ - fi - - sed "s/^/$submenu_indentation/" << EOF -- echo '$message' -+ echo '$(echo "$message" | grub_quote)' - module /hurd/${hurd_fs}.static ${hurd_fs} $opts \\ - --multiboot-command-line='\${kernel-command-line}' \\ - --host-priv-port='\${host-port}' \\ -Index: b/util/grub.d/10_illumos.in -=================================================================== ---- a/util/grub.d/10_illumos.in -+++ b/util/grub.d/10_illumos.in -@@ -46,6 +46,7 @@ - ISADIR= - fi - zfs-bootfs $($grub_mkrelpath /) ZFS_BOOTFS -+ echo '$(echo "$message" | grub_quote)' - multiboot $($grub_mkrelpath /platform/i86pc/kernel)/\$ISADIR/unix /platform/i86pc/kernel/\$ISADIR/unix -B \$ZFS_BOOTFS,console=text - module $($grub_mkrelpath /platform/i86pc)/\$ISADIR/boot_archive /platform/i86pc/\$ISADIR/boot_archive - } -Index: b/util/grub.d/10_kfreebsd.in -=================================================================== ---- a/util/grub.d/10_kfreebsd.in -+++ b/util/grub.d/10_kfreebsd.in -@@ -100,7 +100,7 @@ - printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" - message="$(gettext_printf "Loading kernel of FreeBSD %s ..." ${version})" - sed "s/^/$submenu_indentation/" << EOF -- echo '$message' -+ echo '$(echo "$message" | grub_quote)' - kfreebsd ${rel_dirname}/${basename} ${args} - EOF - -Index: b/util/grub.d/10_linux.in -=================================================================== ---- a/util/grub.d/10_linux.in -+++ b/util/grub.d/10_linux.in -@@ -135,14 +135,14 @@ - fi - message="$(gettext_printf "Loading Linux %s ..." ${version})" - sed "s/^/$submenu_indentation/" << EOF -- echo '$message' -+ echo '$(echo "$message" | grub_quote)' - linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} - EOF - if test -n "${initrd}" ; then - # TRANSLATORS: ramdisk isn't identifier. Should be translated. - message="$(gettext_printf "Loading initial ramdisk ...")" - sed "s/^/$submenu_indentation/" << EOF -- echo '$message' -+ echo '$(echo "$message" | grub_quote)' - initrd ${rel_dirname}/${initrd} - EOF - fi -Index: b/util/grub.d/20_linux_xen.in -=================================================================== ---- a/util/grub.d/20_linux_xen.in -+++ b/util/grub.d/20_linux_xen.in -@@ -125,16 +125,16 @@ - xmessage="$(gettext_printf "Loading Xen %s ..." ${xen_version})" - lmessage="$(gettext_printf "Loading Linux %s ..." ${version})" - sed "s/^/$submenu_indentation/" << EOF -- echo '$xmessage' -+ echo '$(echo "$xmessage" | grub_quote)' - multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} -- echo '$lmessage' -+ echo '$(echo "$lmessage" | grub_quote)' - module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} - EOF - if test -n "${initrd}" ; then - # TRANSLATORS: ramdisk isn't identifier. Should be translated. - message="$(gettext_printf "Loading initial ramdisk ...")" - sed "s/^/$submenu_indentation/" << EOF -- echo '$message' -+ echo '$(echo "$message" | grub_quote)' - module ${rel_dirname}/${initrd} - EOF - fi diff --git a/debian/patches/mkconfig_signed_kernel.patch b/debian/patches/mkconfig_signed_kernel.patch index 062cce0b8..53c75c994 100644 --- a/debian/patches/mkconfig_signed_kernel.patch +++ b/debian/patches/mkconfig_signed_kernel.patch @@ -1,7 +1,7 @@ Description: Generate configuration for signed UEFI kernels if available Author: Colin Watson Forwarded: no -Last-Update: 2013-11-13 +Last-Update: 2013-11-14 Index: b/util/grub.d/10_linux.in =================================================================== @@ -25,7 +25,7 @@ Index: b/util/grub.d/10_linux.in # TRANSLATORS: ramdisk isn't identifier. Should be translated. message="$(gettext_printf "Loading initial ramdisk ...")" @@ -202,6 +210,13 @@ - is_first_entry=true + is_top_level=true while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` + case $linux in diff --git a/debian/patches/mkconfig_skip_dmcrypt.patch b/debian/patches/mkconfig_skip_dmcrypt.patch index 700b7d133..b52da7ed2 100644 --- a/debian/patches/mkconfig_skip_dmcrypt.patch +++ b/debian/patches/mkconfig_skip_dmcrypt.patch @@ -12,7 +12,7 @@ Index: b/util/grub-mkconfig_lib.in =================================================================== --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in -@@ -129,6 +129,15 @@ +@@ -130,6 +130,15 @@ esac done @@ -26,5 +26,5 @@ Index: b/util/grub-mkconfig_lib.in + fi + # Abstraction modules aren't auto-loaded. - abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" + abstraction="`"${grub_probe}" --device $@ --target=abstraction`" for module in ${abstraction} ; do diff --git a/debian/patches/mkconfig_stderr_handling.patch b/debian/patches/mkconfig_stderr_handling.patch deleted file mode 100644 index ce624e1b7..000000000 --- a/debian/patches/mkconfig_stderr_handling.patch +++ /dev/null @@ -1,20 +0,0 @@ -Description: Fix stderr leakage from grub-probe in is_path_readable_by_grub -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4590 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4590 -Last-Update: 2012-09-26 - -Index: b/util/grub-mkconfig_lib.in -=================================================================== ---- a/util/grub-mkconfig_lib.in -+++ b/util/grub-mkconfig_lib.in -@@ -65,7 +65,7 @@ - - # ... or if we can't figure out the abstraction module, for example if - # memberlist fails on an LVM volume group. -- if abstractions="`"${grub_probe}" -t abstraction "$path"`" 2>&1 ; then -+ if abstractions="`"${grub_probe}" -t abstraction "$path"`" 2> /dev/null ; then - : - else - return 1 diff --git a/debian/patches/mkconfig_ubuntu_distributor.patch b/debian/patches/mkconfig_ubuntu_distributor.patch index e8e04fe70..c853a108d 100644 --- a/debian/patches/mkconfig_ubuntu_distributor.patch +++ b/debian/patches/mkconfig_ubuntu_distributor.patch @@ -4,7 +4,7 @@ Author: Mario Limonciello Author: Colin Watson Author: Harald Sitter Forwarded: not-needed -Last-Update: 2013-11-13 +Last-Update: 2013-11-14 Index: b/util/grub.d/10_linux.in =================================================================== @@ -23,6 +23,6 @@ Index: b/util/grub.d/10_linux.in + OS="${GRUB_DISTRIBUTOR} GNU/Linux" + ;; + esac - CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}" fi diff --git a/debian/patches/mkconfig_ubuntu_recovery.patch b/debian/patches/mkconfig_ubuntu_recovery.patch index 68863157f..1d65ba3fc 100644 --- a/debian/patches/mkconfig_ubuntu_recovery.patch +++ b/debian/patches/mkconfig_ubuntu_recovery.patch @@ -12,7 +12,7 @@ Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1076,6 +1076,17 @@ +@@ -1343,6 +1343,17 @@ AC_SUBST([LIBZFS]) AC_SUBST([LIBNVPAIR]) @@ -69,7 +69,7 @@ Index: b/util/grub.d/10_linux.in fi echo " insmod gzio" | sed "s/^/$submenu_indentation/" -@@ -244,7 +256,7 @@ +@@ -245,7 +257,7 @@ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then linux_entry "${OS}" "${version}" recovery \ @@ -82,7 +82,7 @@ Index: b/util/grub.d/30_os-prober.in =================================================================== --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in -@@ -170,7 +170,7 @@ +@@ -201,7 +201,7 @@ fi onstr="$(gettext_printf "(on %s)" "${DEVICE}")" diff --git a/debian/patches/mkrescue_diet.patch b/debian/patches/mkrescue_diet.patch index 409b47d68..fbef704e2 100644 --- a/debian/patches/mkrescue_diet.patch +++ b/debian/patches/mkrescue_diet.patch @@ -4,29 +4,29 @@ Description: Allow reducing size of xorriso-created rescue images Author: Thomas Schmitt Origin: other, http://lists.gnu.org/archive/html/grub-devel/2010-05/msg00100.html Forwarded: yes -Last-Update: 2010-06-02 +Last-Update: 2013-11-14 Index: b/util/grub-mkrescue.in =================================================================== --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in -@@ -52,6 +52,7 @@ - grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" +@@ -43,6 +43,7 @@ + product_version="${PACKAGE_VERSION}" xorriso=xorriso +diet=no - export TEXTDOMAIN=@PACKAGE@ - export TEXTDOMAINDIR="@localedir@" -@@ -76,6 +77,7 @@ - # TRANSLATORS: xorriso is a program for creating ISOs and burning CDs - print_option_help "--xorriso=$filetrans" "$(gettext "use FILE as xorriso [optional]")" - print_option_help "--grub-mkimage=$filetrans" "$(gettext "use FILE as grub-mkimage")" + localedir="@datadir@/locale" + +@@ -69,6 +70,7 @@ + print_option_help "--product-version=$(gettext "STRING")" "$(gettext "use STRING as product version")" + print_option_help "--sparc-boot" "$(gettext "enable sparc boot. Disables HFS+, APM, ARCS and boot as disk image for i386-pc")" + print_option_help "--arcs-boot" "$(gettext "enable ARCS (big-endian mips machines, mostly SGI) boot. Disables HFS+, APM, sparc64 and boot as disk image for i386-pc")" + print_option_help "--diet" "$(gettext "apply size reducing measures [optional]")" echo gettext_printf "%s generates a bootable rescue image with specified source files, source directories, or mkisofs options listed by the output of \`%s'\n" "xorriso -as mkisofs -help" "$self" | grub_fmt echo -@@ -148,6 +150,9 @@ +@@ -160,6 +162,9 @@ --xorriso=*) xorriso=`echo "${option}" | sed 's/--xorriso=//'` ;; @@ -36,7 +36,7 @@ Index: b/util/grub-mkrescue.in *) source="${source} ${option} $@"; break ;; esac -@@ -368,7 +373,14 @@ +@@ -487,7 +492,14 @@ fi # build iso image @@ -51,4 +51,4 @@ Index: b/util/grub-mkrescue.in +fi rm -rf "${iso9660_dir}" - rm -f "${embed_img}" + rm -f "${sysarea_img}" diff --git a/debian/patches/mkrescue_efi_modules.patch b/debian/patches/mkrescue_efi_modules.patch index 0ecade337..484fcc503 100644 --- a/debian/patches/mkrescue_efi_modules.patch +++ b/debian/patches/mkrescue_efi_modules.patch @@ -2,21 +2,21 @@ Description: Build part_msdos and vfat into EFI boot images Author: Mario Limonciello Bug-Ubuntu: https://bugs.launchpad.net/bugs/677758 Forwarded: http://lists.gnu.org/archive/html/grub-devel/2011-01/msg00028.html -Last-Update: 2011-04-11 +Last-Update: 2013-11-14 Index: b/util/grub-mkrescue.in =================================================================== --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in -@@ -326,9 +326,9 @@ +@@ -377,9 +377,9 @@ # build bootia64.efi - make_image "${ia64_dir}" ia64-efi "${efi_dir}"/efi/boot/bootia64.efi "" + make_image_fwdisk "${ia64_dir}" ia64-efi "${efi_dir}"/efi/boot/bootia64.efi "" # build bootx64.efi -- make_image "${efi64_dir}" x86_64-efi "${efi_dir}"/efi/boot/bootx64.efi "" -+ make_image "${efi64_dir}" x86_64-efi "${efi_dir}"/efi/boot/bootx64.efi "part_msdos fat" +- make_image_fwdisk "${efi64_dir}" x86_64-efi "${efi_dir}"/efi/boot/bootx64.efi "" ++ make_image_fwdisk "${efi64_dir}" x86_64-efi "${efi_dir}"/efi/boot/bootx64.efi "part_msdos fat" # build bootia32.efi -- make_image "${efi32_dir}" i386-efi "${efi_dir}"/efi/boot/bootia32.efi "" -+ make_image "${efi32_dir}" i386-efi "${efi_dir}"/efi/boot/bootia32.efi "part_msdos fat" +- make_image_fwdisk "${efi32_dir}" i386-efi "${efi_dir}"/efi/boot/bootia32.efi "" ++ make_image_fwdisk "${efi32_dir}" i386-efi "${efi_dir}"/efi/boot/bootia32.efi "part_msdos fat" if [ -e "${efi_dir}"/efi/boot/bootia32.efi ]; then # For old macs. Suggested by Peter Jones. cp "${efi_dir}"/efi/boot/bootia32.efi "${efi_dir}"/efi/boot/boot.efi diff --git a/debian/patches/mount_readdir_symlink_failures.patch b/debian/patches/mount_readdir_symlink_failures.patch deleted file mode 100644 index d213f6d8b..000000000 --- a/debian/patches/mount_readdir_symlink_failures.patch +++ /dev/null @@ -1,31 +0,0 @@ -Description: Ignore symlink traversal failures in grub-mount readdir -Author: Colin Watson -Forwarded: https://lists.gnu.org/archive/html/grub-devel/2012-10/msg00021.html -Last-Update: 2012-10-12 - -Index: b/util/grub-mount.c -=================================================================== ---- a/util/grub-mount.c -+++ b/util/grub-mount.c -@@ -292,7 +292,20 @@ - file = grub_file_open (tmp); - free (tmp); - if (! file) -- return translate_error (); -+ { -+ /* We cannot handle symlinks properly yet, and symlinks to -+ directories will cause us to reach here. Symlink loops or -+ dangling symlinks will also cause an error. For the -+ meantime, while treating these as zero-length files is wrong, -+ it's better than failing the whole readdir call by returning -+ translate_error (). -+ -+ Ultimately, we should be able to tell from the -+ grub_dirhook_info that this is a symlink, and fill in the -+ attributes of the symlink rather than its target. */ -+ grub_errno = GRUB_ERR_NONE; -+ return 0; -+ } - st.st_size = file->size; - grub_file_close (file); - } diff --git a/debian/patches/msdos_embed_off_by_one.patch b/debian/patches/msdos_embed_off_by_one.patch deleted file mode 100644 index 1ccdb5f66..000000000 --- a/debian/patches/msdos_embed_off_by_one.patch +++ /dev/null @@ -1,30 +0,0 @@ -Description: Revert incorrect off-by-one fix when embedding in MBR - A 62-sector core image should fit before end == 63. -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4586 -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1051154 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4586 -Last-Update: 2012-09-19 - -Index: b/grub-core/partmap/msdos.c -=================================================================== ---- a/grub-core/partmap/msdos.c -+++ b/grub-core/partmap/msdos.c -@@ -316,14 +316,14 @@ - break; - } - -- if (end >= *nsectors + 2) -+ if (end >= *nsectors + 1) - { - unsigned i, j; - char *embed_signature_check; - unsigned int orig_nsectors, avail_nsectors; - - orig_nsectors = *nsectors; -- *nsectors = end - 2; -+ *nsectors = end - 1; - avail_nsectors = *nsectors; - if (*nsectors > max_nsectors) - *nsectors = max_nsectors; diff --git a/debian/patches/no_insmod_on_sb.patch b/debian/patches/no_insmod_on_sb.patch index 9b6e18974..b2f33d657 100644 --- a/debian/patches/no_insmod_on_sb.patch +++ b/debian/patches/no_insmod_on_sb.patch @@ -3,7 +3,7 @@ Author: Matthew Garrett Author: Colin Watson Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub-2.00-no-insmod-on-sb.patch Forwarded: no -Last-Update: 2013-01-02 +Last-Update: 2013-11-14 Index: b/grub-core/kern/dl.c =================================================================== @@ -20,7 +20,7 @@ Index: b/grub-core/kern/dl.c #pragma GCC diagnostic ignored "-Wcast-align" -@@ -668,6 +672,15 @@ +@@ -653,6 +657,15 @@ void *core = 0; grub_dl_t mod = 0; diff --git a/debian/patches/olpc_prefix_hack.patch b/debian/patches/olpc_prefix_hack.patch index 3099d5880..bcca401a1 100644 --- a/debian/patches/olpc_prefix_hack.patch +++ b/debian/patches/olpc_prefix_hack.patch @@ -5,7 +5,7 @@ Index: b/grub-core/kern/ieee1275/init.c =================================================================== --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c -@@ -61,6 +61,7 @@ +@@ -65,6 +65,7 @@ grub_ieee1275_exit (); } @@ -13,7 +13,7 @@ Index: b/grub-core/kern/ieee1275/init.c /* Translate an OF filesystem path (separated by backslashes), into a GRUB path (separated by forward slashes). */ static void -@@ -75,10 +76,19 @@ +@@ -79,10 +80,19 @@ backslash = grub_strchr (filepath, '\\'); } } @@ -33,9 +33,9 @@ Index: b/grub-core/kern/ieee1275/init.c void grub_machine_get_bootlocation (char **device, char **path) { -@@ -133,6 +143,7 @@ - } +@@ -150,6 +160,7 @@ } + grub_free (bootpath); } +#endif diff --git a/debian/patches/os_prober_efi.patch b/debian/patches/os_prober_efi.patch deleted file mode 100644 index 54952edcf..000000000 --- a/debian/patches/os_prober_efi.patch +++ /dev/null @@ -1,36 +0,0 @@ -Index: b/util/grub.d/30_os-prober.in -=================================================================== ---- a/util/grub.d/30_os-prober.in -+++ b/util/grub.d/30_os-prober.in -@@ -35,6 +35,11 @@ - exit 0 - fi - -+# Try to load the efivars module, in case it's needed for EFI support -+# to work below. Hide the errors in case it's not available, there is -+# no need to scare people here. -+modprobe efivars >/dev/null 2>&1 || true -+ - OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`" - if [ -z "${OSPROBED}" ] ; then - # empty os-prober output, nothing doing -@@ -144,6 +149,19 @@ - } - EOF - ;; -+ efi) -+ EFIPATH=${DEVICE#*@} -+ DEVICE=${DEVICE%@*} -+ cat << EOF -+menuentry "${LONGNAME} (UEFI on ${DEVICE})" --class windows --class os { -+EOF -+ save_default_entry | sed -e "s/^/\t/" -+ prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" -+ cat < Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/803658 Forwarded: no -Last-Update: 2013-11-12 +Last-Update: 2013-11-15 -Index: b/util/getroot.c +Index: b/grub-core/osdep/devmapper/getroot.c =================================================================== ---- a/util/getroot.c -+++ b/util/getroot.c -@@ -1929,6 +1929,12 @@ - grub_util_info ("%s child has no DM name", path); - goto devmapper_out; - } -+ if (strstr (child_name, "-") != 0) -+ { -+ grub_util_info ("%s child %s looks like a sub-layer\n", -+ path, child_name); -+ goto devmapper_out; -+ } - mapper_name = child_name; - - devmapper_out: +--- a/grub-core/osdep/devmapper/getroot.c ++++ b/grub-core/osdep/devmapper/getroot.c +@@ -294,6 +294,12 @@ + grub_util_info ("%s child has no DM name", path); + goto devmapper_out; + } ++ if (strstr (child_name, "-") != 0) ++ { ++ grub_util_info ("%s child %s looks like a sub-layer\n", ++ path, child_name); ++ goto devmapper_out; ++ } + mapper_name = child_name; + *is_part = 1; + node = child; diff --git a/debian/patches/probe_error_handling.patch b/debian/patches/probe_error_handling.patch deleted file mode 100644 index 53985a460..000000000 --- a/debian/patches/probe_error_handling.patch +++ /dev/null @@ -1,22 +0,0 @@ -Description: Fix spurious failure on Xen partition devices without disk devices - Zero out grub_errno in the case where we handle GRUB_ERR_UNKNOWN_DEVICE by - falling back to the partition device, otherwise a later call to this - function may fail spuriously. -Author: Colin Watson -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5092 -Bug-Debian: http://bugs.debian.org/708614 -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5092 -Last-Update: 2013-08-13 - -Index: b/util/getroot.c -=================================================================== ---- a/util/getroot.c -+++ b/util/getroot.c -@@ -2316,6 +2316,7 @@ - grub_util_warn - (_("disk does not exist, so falling back to partition device %s"), - os_dev); -+ grub_errno = GRUB_ERR_NONE; - - canon = canonicalize_file_name (os_dev); - drive = find_system_device (canon ? : os_dev, &st, 0, 1); diff --git a/debian/patches/probe_fusionio.patch b/debian/patches/probe_fusionio.patch index c549ad34d..43607442f 100644 --- a/debian/patches/probe_fusionio.patch +++ b/debian/patches/probe_fusionio.patch @@ -2,8 +2,32 @@ Description: Probe FusionIO devices Author: Colin Watson Bug-Ubuntu: https://bugs.launchpad.net/bugs/1237519 Forwarded: no -Last-Update: 2013-11-13 +Last-Update: 2013-11-15 +Index: b/grub-core/osdep/linux/getroot.c +=================================================================== +--- a/grub-core/osdep/linux/getroot.c ++++ b/grub-core/osdep/linux/getroot.c +@@ -885,6 +885,19 @@ + } + } + ++ /* If this is a FusionIO disk. */ ++ if ((strncmp ("fio", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z') ++ { ++ char *pp = p + 3; ++ while (*pp >= 'a' && *pp <= 'z') ++ pp++; ++ if (*pp) ++ *is_part = 1; ++ /* /dev/fio[a-z]+[0-9]* */ ++ *pp = '\0'; ++ return path; ++ } ++ + return path; + } + Index: b/util/deviceiter.c =================================================================== --- a/util/deviceiter.c @@ -24,7 +48,7 @@ Index: b/util/deviceiter.c @@ -852,6 +858,19 @@ if (check_device_readable_unique (name)) { - if (hook (name, 0)) + if (hook (name, 0, hook_data)) + goto out; + } + } @@ -37,31 +61,7 @@ Index: b/util/deviceiter.c + get_fio_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) goto out; } } -Index: b/util/getroot.c -=================================================================== ---- a/util/getroot.c -+++ b/util/getroot.c -@@ -1825,6 +1825,19 @@ - return path; - } - -+ /* If this is a FusionIO disk. */ -+ if ((strncmp ("fio", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z') -+ { -+ char *pp = p + 3; -+ while (*pp >= 'a' && *pp <= 'z') -+ pp++; -+ if (*pp) -+ *is_part = 1; -+ /* /dev/fio[a-z]+[0-9]* */ -+ *pp = '\0'; -+ return path; -+ } -+ - #ifdef HAVE_DEVICE_MAPPER - if ((strncmp ("/dev/mapper/", path, sizeof ("/dev/mapper/") - 1) == 0) - || (strncmp ("/dev/dm-", path, sizeof ("/dev/dm-") - 1) == 0)) diff --git a/debian/patches/quick_boot.patch b/debian/patches/quick_boot.patch index 30e1ad0ab..304200772 100644 --- a/debian/patches/quick_boot.patch +++ b/debian/patches/quick_boot.patch @@ -14,13 +14,13 @@ Description: Add configure option to bypass boot menu if possible Author: Colin Watson Author: Richard Laager Forwarded: no -Last-Update: 2013-11-13 +Last-Update: 2013-11-15 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1098,6 +1098,17 @@ +@@ -1365,6 +1365,17 @@ fi AC_SUBST([QUIET_BOOT]) @@ -42,7 +42,7 @@ Index: b/docs/grub.texi =================================================================== --- a/docs/grub.texi +++ b/docs/grub.texi -@@ -1289,6 +1289,15 @@ +@@ -1483,6 +1483,15 @@ Each module will be loaded as early as possible, at the start of @file{grub.cfg}. @@ -63,11 +63,11 @@ Index: b/util/grub-mkconfig.in --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -228,7 +228,8 @@ - GRUB_INIT_TUNE \ GRUB_SAVEDEFAULT \ GRUB_ENABLE_CRYPTODISK \ -- GRUB_BADRAM -+ GRUB_BADRAM \ + GRUB_BADRAM \ +- GRUB_DISABLE_SUBMENU ++ GRUB_DISABLE_SUBMENU \ + GRUB_RECORDFAIL_TIMEOUT if test "x${grub_cfg}" != "x"; then @@ -76,7 +76,7 @@ Index: b/util/grub.d/00_header.in =================================================================== --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in -@@ -23,6 +23,8 @@ +@@ -21,6 +21,8 @@ exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" grub_lang=`echo $LANG | cut -d . -f 1` @@ -85,7 +85,7 @@ Index: b/util/grub.d/00_header.in export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR="@localedir@" -@@ -46,6 +48,7 @@ +@@ -44,6 +46,7 @@ cat << EOF if [ -s \$prefix/grubenv ]; then @@ -93,7 +93,7 @@ Index: b/util/grub.d/00_header.in load_env fi EOF -@@ -86,7 +89,31 @@ +@@ -96,7 +99,31 @@ save_env saved_entry fi } @@ -125,7 +125,7 @@ Index: b/util/grub.d/00_header.in function load_video { EOF if [ -n "${GRUB_VIDEO_BACKEND}" ]; then -@@ -272,7 +299,15 @@ +@@ -282,7 +309,15 @@ make_timeout () { @@ -162,13 +162,13 @@ Index: b/util/grub.d/10_linux.in + echo "recordfail" | sed "s/^/$submenu_indentation/" + fi if [ x$type != xrecovery ] ; then - save_default_entry | sed -e "s/^/\t/" + save_default_entry | grub_add_tab fi Index: b/util/grub.d/30_os-prober.in =================================================================== --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in -@@ -20,18 +20,78 @@ +@@ -20,28 +20,90 @@ prefix="@prefix@" exec_prefix="@exec_prefix@" datarootdir="@datarootdir@" @@ -247,7 +247,6 @@ Index: b/util/grub.d/30_os-prober.in exit 0 fi -@@ -43,10 +103,12 @@ OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`" if [ -z "${OSPROBED}" ] ; then # empty os-prober output, nothing doing @@ -268,15 +267,15 @@ Index: b/util/grub.d/30_os-prober.in onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' { -@@ -169,6 +232,7 @@ - EOF +@@ -176,6 +239,7 @@ ;; efi) -+ found_other_os=1 - EFIPATH=${DEVICE#*@} - DEVICE=${DEVICE%@*} - cat << EOF -@@ -211,6 +275,7 @@ + ++ found_other_os=1 + EFIPATH=${DEVICE#*@} + DEVICE=${DEVICE%@*} + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" +@@ -224,6 +288,7 @@ [ "${prepare_boot_cache}" ] || continue fi @@ -284,7 +283,7 @@ Index: b/util/grub.d/30_os-prober.in onstr="$(gettext_printf "(on %s)" "${DEVICE}")" recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true counter=1 -@@ -277,6 +342,7 @@ +@@ -290,6 +355,7 @@ osx_entry xnu_kernel64 64 ;; hurd) @@ -292,7 +291,7 @@ Index: b/util/grub.d/30_os-prober.in onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' { -@@ -309,3 +375,5 @@ +@@ -333,3 +399,5 @@ ;; esac done diff --git a/debian/patches/restore_mkdevicemap.patch b/debian/patches/restore_mkdevicemap.patch index 6a83d4379..1ca772a8b 100644 --- a/debian/patches/restore_mkdevicemap.patch +++ b/debian/patches/restore_mkdevicemap.patch @@ -2,7 +2,7 @@ Index: b/Makefile.util.def =================================================================== --- a/Makefile.util.def +++ b/Makefile.util.def -@@ -289,6 +289,22 @@ +@@ -306,6 +306,22 @@ }; program = { @@ -35,8 +35,8 @@ Index: b/include/grub/util/deviceiter.h + +#include + -+void grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), -+ int floppy_disks); ++void grub_util_iterate_devices (int (*hook) (const char *, int), ++ void *hook_data, int floppy_disks); +void grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy, + int *num_fd, int *num_hd); + @@ -568,7 +568,7 @@ Index: b/util/deviceiter.c +#endif /* __linux__ */ + +void -+grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), ++grub_util_iterate_devices (int (*hook) (const char *, int), void *hook_data, + int floppy_disks) +{ + int i; @@ -586,7 +586,7 @@ Index: b/util/deviceiter.c + break; + /* In floppies, write the map, whether check_device_readable_unique + succeeds or not, because the user just may not insert floppies. */ -+ if (hook (name, 1)) ++ if (hook (name, 1, hook_data)) + goto out; + } + @@ -641,7 +641,7 @@ Index: b/util/deviceiter.c + { + if (check_device_readable_unique (devs[dev].stable)) + { -+ if (hook (devs[dev].stable, 0)) ++ if (hook (devs[dev].stable, 0, hook_data)) + goto out; + } + free (devs[dev].stable); @@ -669,7 +669,7 @@ Index: b/util/deviceiter.c + if (realpath (discn, name)) + { + strcat (name, "/disc"); -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -685,7 +685,7 @@ Index: b/util/deviceiter.c + get_ide_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -700,7 +700,7 @@ Index: b/util/deviceiter.c + get_ada_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -713,7 +713,7 @@ Index: b/util/deviceiter.c + get_ataraid_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -726,7 +726,7 @@ Index: b/util/deviceiter.c + get_mfi_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -741,7 +741,7 @@ Index: b/util/deviceiter.c + get_virtio_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -754,7 +754,7 @@ Index: b/util/deviceiter.c + get_ataraid_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -767,7 +767,7 @@ Index: b/util/deviceiter.c + get_xvd_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -781,7 +781,7 @@ Index: b/util/deviceiter.c + get_scsi_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -804,7 +804,7 @@ Index: b/util/deviceiter.c + get_dac960_disk_name (name, controller, drive); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -825,7 +825,7 @@ Index: b/util/deviceiter.c + get_acceleraid_disk_name (name, controller, drive); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -846,7 +846,7 @@ Index: b/util/deviceiter.c + get_cciss_disk_name (name, controller, drive); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -867,7 +867,7 @@ Index: b/util/deviceiter.c + get_ida_disk_name (name, controller, drive); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -885,7 +885,7 @@ Index: b/util/deviceiter.c + get_i2o_disk_name (name, unit); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -899,7 +899,7 @@ Index: b/util/deviceiter.c + get_mmc_disk_name (name, i); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + goto out; + } + } @@ -970,7 +970,7 @@ Index: b/util/deviceiter.c + name = xasprintf ("/dev/mapper/%s", node_name); + if (check_device_readable_unique (name)) + { -+ if (hook (name, 0)) ++ if (hook (name, 0, hook_data)) + { + free (name); + if (task) @@ -1023,7 +1023,7 @@ Index: b/util/grub-mkdevicemap.c =================================================================== --- /dev/null +++ b/util/grub-mkdevicemap.c -@@ -0,0 +1,171 @@ +@@ -0,0 +1,182 @@ +/* grub-mkdevicemap.c - make a device map file automatically */ +/* + * GRUB -- GRand Unified Bootloader @@ -1066,34 +1066,45 @@ Index: b/util/grub-mkdevicemap.c + +#include "progname.h" + ++/* Context for make_device_map. */ ++struct make_device_map_ctx ++{ ++ FILE *fp; ++ int *num_fd; ++ int *num_hd; ++}; ++ ++/* Helper for make_device_map. */ ++static int ++process_device (const char *name, int is_floppy, void *data) ++{ ++ struct make_device_map_ctx *ctx = data; ++ ++ grub_util_emit_devicemap_entry (ctx->fp, (char *) name, ++ is_floppy, ctx->num_fd, ctx->num_hd); ++ return 0; ++} ++ +static void +make_device_map (const char *device_map, int floppy_disks) +{ -+ int num_hd = 0; -+ int num_fd = 0; -+ FILE *fp; -+ -+ auto int NESTED_FUNC_ATTR process_device (const char *name, int is_floppy); -+ -+ int NESTED_FUNC_ATTR process_device (const char *name, int is_floppy) -+ { -+ grub_util_emit_devicemap_entry (fp, (char *) name, -+ is_floppy, &num_fd, &num_hd); -+ return 0; -+ } ++ struct make_device_map_ctx ctx = { ++ .num_fd = 0, ++ .num_hd = 0 ++ }; + + if (strcmp (device_map, "-") == 0) -+ fp = stdout; ++ ctx.fp = stdout; + else -+ fp = fopen (device_map, "w"); ++ ctx.fp = fopen (device_map, "w"); + -+ if (! fp) ++ if (! ctx.fp) + grub_util_error (_("cannot open %s"), device_map); + -+ grub_util_iterate_devices (process_device, floppy_disks); ++ grub_util_iterate_devices (process_device, floppy_disks, &ctx); + -+ if (fp != stdout) -+ fclose (fp); ++ if (ctx.fp != stdout) ++ fclose (ctx.fp); +} + +static struct option options[] = diff --git a/debian/patches/script_check_no_commands.patch b/debian/patches/script_check_no_commands.patch deleted file mode 100644 index 1ecca2d86..000000000 --- a/debian/patches/script_check_no_commands.patch +++ /dev/null @@ -1,87 +0,0 @@ -Description: Guard against scripts containing no commands - Make grub-script-check fail on scripts containing no commands, to guard - against corrupted grub-mkconfig setups that produce no useful output. -Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/5044 -Author: Colin Watson -Bug-Debian: http://bugs.debian.org/713886 -Forwarded: not-needed -Last-Update: 2013-07-13 - -Index: b/Makefile.util.def -=================================================================== ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -701,6 +701,12 @@ - - script = { - testcase; -+ name = grub_script_no_commands; -+ common = tests/grub_script_no_commands.in; -+}; -+ -+script = { -+ testcase; - name = partmap_test; - common = tests/partmap_test.in; - }; -Index: b/tests/grub_script_no_commands.in -=================================================================== ---- /dev/null -+++ b/tests/grub_script_no_commands.in -@@ -0,0 +1,21 @@ -+#! /bin/sh -+set -e -+ -+# grub-script-check refuses to pass a file with no commands; this usually -+# indicates a bug in the code generating that file. -+ -+@builddir@/grub-script-check <cmd) -+ found_cmd = 1; - grub_script_execute (script); - grub_script_free (script); - } -@@ -191,6 +193,12 @@ - fprintf (stderr, _("Syntax error at line %u\n"), lineno); - return 1; - } -+ if (! found_cmd) -+ { -+ fprintf (stderr, _("Script contains no commands and will do nothing\n"), -+ arguments.filename); -+ return 1; -+ } - - return 0; - } diff --git a/debian/patches/series b/debian/patches/series index e554904e7..af66bd131 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,3 @@ -upstream-extra-dist.patch olpc_prefix_hack.patch core_in_fs.patch dpkg_version_comparison.patch @@ -11,29 +10,16 @@ mkconfig_skip_dmcrypt.patch install_stage2_confusion.patch mkrescue_efi_modules.patch mkconfig_loopback.patch -efi_disk_cache.patch restore_mkdevicemap.patch -efi_mmap_size.patch gettext_quiet.patch mkconfig_mid_upgrade.patch -fix_powerpc_emu.patch install_efi_fallback.patch -mkconfig_overescaping.patch -efifwsetup.patch mkconfig_ubuntu_recovery.patch -msdos_embed_off_by_one.patch -emu_freebsd.patch -mkconfig_stderr_handling.patch -tftp_endianness.patch install_locale_langpack.patch mkconfig_nonexistent_loopback.patch -mount_readdir_symlink_failures.patch -initrd_addr_min.patch -gnulib_gets.patch no_insmod_on_sb.patch default_grub_d.patch blacklist_1440x900x32.patch -kfreebsd_9.1.patch uefi_firmware_setup.patch mkconfig_ubuntu_distributor.patch linuxefi.patch @@ -44,17 +30,9 @@ linuxefi_non_sb_fallback.patch mkconfig_signed_kernel.patch install_signed.patch install_bios_setup_path.patch -os_prober_efi.patch -acpihalt_improvements.patch -script_check_no_commands.patch -texinfo_ordering.patch -mkconfig_emacs_autosave.patch sleep_shift.patch -probe_error_handling.patch wubi_no_windows.patch maybe_quiet.patch -efidisk_non_512_sectors.patch -mkconfig_hurd_sort.patch probe_dmraid.patch install_efi_ubuntu_flavours.patch quick_boot.patch diff --git a/debian/patches/texinfo_ordering.patch b/debian/patches/texinfo_ordering.patch deleted file mode 100644 index fd546040f..000000000 --- a/debian/patches/texinfo_ordering.patch +++ /dev/null @@ -1,21 +0,0 @@ -Description: Move @itemize after @subsection to satisfy texinfo-5.1 -Author: Bryan Hundven -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4813 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4813 -Last-Update: 2013-08-11 - -Index: b/docs/grub-dev.texi -=================================================================== ---- a/docs/grub-dev.texi -+++ b/docs/grub-dev.texi -@@ -1394,8 +1394,8 @@ - - @node Bitmap API - @section Bitmap API --@itemize - @subsection grub_video_bitmap_create -+@itemize - @item Prototype: - @example - grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap, unsigned int width, unsigned int height, enum grub_video_blit_format blit_format) diff --git a/debian/patches/tftp_endianness.patch b/debian/patches/tftp_endianness.patch deleted file mode 100644 index 148f15fcf..000000000 --- a/debian/patches/tftp_endianness.patch +++ /dev/null @@ -1,29 +0,0 @@ -Description: Fix tftp endianness problem -Author: Vladimir Serbinenko -Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4548 -Forwarded: not-needed -Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/4548 -Last-Update: 2012-09-26 - -Index: b/grub-core/net/tftp.c -=================================================================== ---- a/grub-core/net/tftp.c -+++ b/grub-core/net/tftp.c -@@ -143,7 +143,7 @@ - - tftph_ack = (struct tftphdr *) nb_ack.data; - tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK); -- tftph_ack->u.ack.block = block; -+ tftph_ack->u.ack.block = grub_cpu_to_be16 (block); - - err = grub_net_send_udp_packet (data->sock, &nb_ack); - if (err) -@@ -225,7 +225,7 @@ - grub_priority_queue_pop (data->pq); - - if (file->device->net->packs.count < 50) -- err = ack (data, tftph->u.data.block); -+ err = ack (data, data->block + 1); - else - { - file->device->net->stall = 1; diff --git a/debian/patches/uefi_firmware_setup.patch b/debian/patches/uefi_firmware_setup.patch index cfe322b99..03c7feaaf 100644 --- a/debian/patches/uefi_firmware_setup.patch +++ b/debian/patches/uefi_firmware_setup.patch @@ -1,12 +1,13 @@ Description: Output a menu entry for firmware setup on UEFI FastBoot systems Author: Steve Langasek Forwarded: no +Last-Update: 2013-11-14 Index: b/Makefile.util.def =================================================================== --- a/Makefile.util.def +++ b/Makefile.util.def -@@ -456,6 +456,12 @@ +@@ -484,6 +484,12 @@ }; script = { @@ -19,18 +20,6 @@ Index: b/Makefile.util.def name = '40_custom'; common = util/grub.d/40_custom.in; installdir = grubconf; -Index: b/po/POTFILES-shell.in -=================================================================== ---- a/po/POTFILES-shell.in -+++ b/po/POTFILES-shell.in -@@ -7,6 +7,7 @@ - util/grub.d/10_windows.in - util/grub.d/20_linux_xen.in - util/grub.d/30_os-prober.in -+util/grub.d/30_uefi-firmware.in - util/grub.d/40_custom.in - util/grub.d/41_custom.in - util/grub-install.in Index: b/util/grub.d/30_uefi-firmware.in =================================================================== --- /dev/null diff --git a/debian/patches/upstream-extra-dist.patch b/debian/patches/upstream-extra-dist.patch deleted file mode 100644 index 6d5dd4579..000000000 --- a/debian/patches/upstream-extra-dist.patch +++ /dev/null @@ -1,173 +0,0 @@ -Description: Files present in upstream branch but missing from upstream tarball - This allows us to maintain the packaging as a branch of upstream more - easily. The build system has been corrected upstream, so this patch can be - dropped after the next upstream release. -Last-Update: 2012-09-04 - -Index: b/grub-core/tests/boot/linux.init-ppc.S -=================================================================== ---- /dev/null -+++ b/grub-core/tests/boot/linux.init-ppc.S -@@ -0,0 +1,61 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2012 Free Software Foundation, Inc. -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#define SYSCALL_WRITE 4 -+#define SYSCALL_RESET 88 -+#define SYSCALL_EXIT 1 -+ -+#define STDOUT 1 -+#define SHUTDOWN_MAGIC1 0xfee1dead -+#define SHUTDOWN_MAGIC2 0x28121969 -+#define SHUTDOWN_MAGIC3 0x4321fedc -+ -+ .text -+ .global start, _start, __start -+__start: -+_start: -+start: -+ /* write. */ -+ li %r0, SYSCALL_WRITE -+ li %r3, STDOUT -+ lis %r4, message@h -+ ori %r4, %r4, message@l -+ lis %r5, messageend@h -+ ori %r5, %r5, messageend@l -+ sub %r5, %r5, %r4 -+ sc -+ -+ /* shutdown. */ -+ li %r0, SYSCALL_RESET -+ lis %r3, SHUTDOWN_MAGIC1@h -+ ori %r3, %r3, SHUTDOWN_MAGIC1@l -+ lis %r4, SHUTDOWN_MAGIC2@h -+ ori %r4, %r4, SHUTDOWN_MAGIC2@l -+ lis %r5, SHUTDOWN_MAGIC3@h -+ ori %r5, %r5, SHUTDOWN_MAGIC3@l -+ sc -+ -+ /* exit(1). Shouldn't be reached. */ -+ li %r0, SYSCALL_EXIT -+ li %r3, 1 -+ sc -+ -+ .data -+message: -+ .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" -+messageend: -Index: b/grub-core/tests/boot/linux.init-mips.S -=================================================================== ---- /dev/null -+++ b/grub-core/tests/boot/linux.init-mips.S -@@ -0,0 +1,61 @@ -+/* -+ * 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 4004 -+#define SYSCALL_RESET 4088 -+#define SYSCALL_EXIT 4001 -+ -+#define STDOUT 1 -+#define SHUTDOWN_MAGIC1 0xfee1dead -+#define SHUTDOWN_MAGIC2 0x28121969 -+#ifdef REBOOT -+#define SHUTDOWN_MAGIC3 0x01234567 -+#else -+#define SHUTDOWN_MAGIC3 0x4321fedc -+#endif -+ .text -+ .global start, _start, __start -+__start: -+_start: -+start: -+ /* write. */ -+ li $v0, SYSCALL_WRITE -+ li $a0, STDOUT -+ lui $a1, %hi(message) -+ addiu $a1, %lo(message) -+ lui $a2, %hi(messageend) -+ addiu $a2, %lo(messageend) -+ subu $a2, $a2, $a1 -+ syscall -+ -+ /* shutdown. */ -+ li $v0, SYSCALL_RESET -+ li $a0, SHUTDOWN_MAGIC1 -+ li $a1, SHUTDOWN_MAGIC2 -+ li $a2, SHUTDOWN_MAGIC3 -+ syscall -+ -+ /* exit(1). Shouldn't be reached. */ -+ li $v0, SYSCALL_EXIT -+ li $a0, 1 -+ syscall -+ -+ .data -+message: -+ .ascii "Boot Test Passed Successfully\n" SUCCESSFUL_BOOT_STRING "\n" -+messageend: -Index: b/grub-core/tests/boot/linux-ppc.cfg -=================================================================== ---- /dev/null -+++ b/grub-core/tests/boot/linux-ppc.cfg -@@ -0,0 +1,5 @@ -+linux /linux console=ttyPZ1 root=/dev/ram0 -+initrd /initrd -+boot -+# Shouln't happen -+halt -Index: b/linguas.sh -=================================================================== ---- /dev/null -+++ b/linguas.sh -@@ -0,0 +1,20 @@ -+#!/bin/sh -+ -+rsync -Lrtvz --exclude=ko.po translationproject.org::tp/latest/grub/ po -+ -+autogenerated="en@quot en@hebrew de@hebrew en@cyrillic en@greek en@arabic en@piglatin de_CH" -+ -+ -+for x in $autogenerated; do -+ rm "po/$x.po"; -+done -+ -+ -+( -+ ( -+ cd po && ls *.po| cut -d. -f1 -+ for x in $autogenerated; do -+ echo "$x"; -+ done -+ ) | sort | uniq | xargs -+) >po/LINGUAS diff --git a/debian/patches/vt_handoff.patch b/debian/patches/vt_handoff.patch index 6dcb67bd9..2c0e7a9d0 100644 --- a/debian/patches/vt_handoff.patch +++ b/debian/patches/vt_handoff.patch @@ -4,13 +4,13 @@ Description: Add configure option to use vt.handoff=7 Author: Colin Watson Author: Andy Whitcroft Forwarded: not-needed -Last-Update: 2013-11-13 +Last-Update: 2013-11-15 Index: b/configure.ac =================================================================== --- a/configure.ac +++ b/configure.ac -@@ -1120,6 +1120,17 @@ +@@ -1387,6 +1387,17 @@ fi AC_SUBST([GFXPAYLOAD_DYNAMIC]) diff --git a/debian/patches/wubi_no_windows.patch b/debian/patches/wubi_no_windows.patch index 1d87353cb..b13697179 100644 --- a/debian/patches/wubi_no_windows.patch +++ b/debian/patches/wubi_no_windows.patch @@ -6,13 +6,13 @@ Description: Skip Windows os-prober entries on Wubi systems https://blueprints.launchpad.net/ubuntu/+spec/foundations-o-wubi Author: Colin Watson Forwarded: not-needed -Last-Update: 2013-08-13 +Last-Update: 2013-11-15 Index: b/util/grub.d/30_os-prober.in =================================================================== --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in -@@ -112,6 +112,8 @@ +@@ -107,6 +107,8 @@ used_osprober_linux_ids= diff --git a/docs/autoiso.cfg b/docs/autoiso.cfg new file mode 100644 index 000000000..9ce51c692 --- /dev/null +++ b/docs/autoiso.cfg @@ -0,0 +1,244 @@ +# Sample GRUB script to autodetect operating systems +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +function pathname { regexp -s 2:"$2" '^(\(.*\))?(/.*)$' "$1"; } +function devname { regexp -s "$2" '^(\(.*\)).*$' "$1"; } + +function loopback_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + if test -f /boot/grub/loopback.cfg; then + cfgpath=/boot/grub/loopback.cfg + elif test -f /grub/loopback.cfg; then + cfgpath=/grub/loopback.cfg + else + return 1; + fi + + echo loopback.cfg $isopath: yes + menuentry "Boot GRUB Loopback Config from ${realdev}${isopath}" "$realdev" "$isopath" "$cfgpath" { + set device="$2" + set iso_path="$3" + set cfg_path="$4" + + export iso_path + loopback loopdev_cfg "${device}${iso_path}" + set root=(loopdev_cfg) + configfile $cfg_path + loopback -d loopdev_cfg + } + return 0 +} + +function grml_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + result=1 + for dir in /boot/grml /boot/grmlsmall /boot/grmlmedium; do + if ! test -f ${dir}/linux26 -a -f ${dir}/initrd.gz; then continue; fi + + echo grml $isopath: yes + result=0 + menuentry "GRML Linux from ${realdev}${isopath}" \ + "$realdev" "$isopath" "$dir" { + set device="$2" + set isopath="$3" + set grmldir="$4" + + loopback loopdev_grml "${device}${isopath}" + set root=(loopdev_grml) + linux $grmldir/linux26 findiso="$isopath" apm=power-off quiet \ + boot=live nomce + initrd $grmldir/initrd.gz + loopback -d loopdev_grml + } + done + return $result +} + +function pmagic_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /pmagic/bzImage -a -f /pmagic/initramfs; then return 1; fi + + echo pmagic $isopath: yes + menuentry "Parted Magic from ${realdev}${isopath}" "$realdev" "$isopath" { + set device="$2" + set isopath="$3" + + loopback loopdev_pmagic "${device}${isopath}" + set root=(loopdev_pmagic) + linux /pmagic/bzImage iso_filename="$isopath" edd=off noapic \ + load_ramdisk=1 prompt_ramdisk=0 rw sleep=10 loglevel=0 \ + keymap=$langcode + initrd /pmagic/initramfs + loopback -d loopdev_pmagic + } + return 0 +} + +function sidux_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + result=1 + for kernel in /boot/vmlinuz-*-sidux-*; do + if ! test -f "$kernel"; then continue; fi + regexp -s 1:v1 -s 2:v2 '/boot/vmlinuz-(.*)-sidux-(.*)' "$kernel" + + initrd="/boot/initrd.img-$v1-sidux-$v2" + if ! test -f "$initrd"; then continue; fi + + result=0 + echo sidux $isopath: yes + menuentry "Sidux vmlinux-$v1-sidux-$v2 from ${realdev}${isopath}" "$realdev" "$isopath" "$kernel" "$initrd" { + set device="$2" + set isopath="$3" + set kernel="$4" + set initrd="$5" + + loopback loopdev_sidux "${device}${isopath}" + set root=(loopdev_sidux) + linux $kernel fromiso=$isopath boot=fll quiet + initrd $initrd + loopback -d loopdev_sidux + } + done + return $result +} + +function slax_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /boot/vmlinuz -a -f /boot/initrd.gz; then return 1; fi + + echo slax $isopath: yes + menuentry "Slax Linux from ${realdev}${isopath}" "$realdev" "$isopath" { + set device="$2" + set isopath="$3" + + loopback loopdev_slax "${device}${isopath}" + set root=(loopdev_slax) + linux /boot/vmlinuz from=$isopath ramdisk_size=6666 root=/dev/ram0 rw + initrd /boot/initrd.gz + loopback -d loopdev_slax + } + return 0 +} + +function tinycore_iso_entry { + realpath="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /boot/bzImage -a -f /boot/tinycore.gz; then return 1; fi + + echo tinycore $isopath: yes + menuentry "Tinycore Linux from ${realdev}${isopath}" "$realdev" "$isopath" { + set device="$2" + set isopath="$3" + + loopback loopdev_tiny "${device}${isopath}" + set root=(loopdev_tiny) + linux /boot/bzImage + initrd /boot/tinycore.gz + loopback -d loopdev_tiny + } + return 0 +} + +function casper_iso_entry { + realpath="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /casper/vmlinuz; then return 1; fi + initrd= + for f in /casper/initrd.*z; do + if ! test -f "$f"; then continue; fi + pathname "$f" initrd + done + if test -z "$initrd"; then return 1; fi + + echo casper $isopath: yes + menuentry "Casper based Linux from ${realdev}${isopath}" "$realdev" "$isopath" "$initrd" { + set device="$2" + set isopath="$3" + set initrd="$4" + + loopback loopdev_casper "${device}${isopath}" + set root=(loopdev_casper) + linux /casper/vmlinuz boot=casper iso-scan/filename="$isopath" quiet splash noprompt keyb="$langcode" \ + debian-installer/language="$langcode" console-setup/layoutcode?="$langcode" -- + initrd $initrd + loopback -d loopdev_casper + } + return 0 +} + +function scan_isos { + isodirs="$1" + + for dev in (*); do + for dir in $isodirs; do + for file in ${dev}${dir}/*.iso ${dev}${dir}/*.ISO; do + if ! test -f "$file"; then continue; fi + + pathname $file isopath + if test -z "$dev" -o -z "$isopath"; then continue; fi + + if ! loopback loopdev_scan "$file"; then continue; fi + saved_root=$root + set root=(loopdev_scan) + + if loopback_iso_entry $dev $isopath (loopdev_scan); then true; + elif grml_iso_entry $dev $isopath (loopdev_scan); then true; + elif pmagic_iso_entry $dev $isopath (loopdev_scan); then true; + elif sidux_iso_entry $dev $isopath (loopdev_scan); then true; + elif slax_iso_entry $dev $isopath (loopdev_scan); then true; + elif tinycore_iso_entry $dev $isopath (loopdev_scan); then true; + elif casper_iso_entry $dev $isopath (loopdev_scan); then true; + else true; fi + + set root=$saved_root + loopback -d loopdev_scan + done + done + done + return 0 +} + +# XXX Remove later +insmod serial +serial +terminal_output --append serial +# terminal_input --append serial + +langcode="$lang" + +insmod regexp +scan_isos /iso /boot/iso + diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi index f74c96602..401f455a3 100644 --- a/docs/grub-dev.texi +++ b/docs/grub-dev.texi @@ -74,12 +74,11 @@ This edition documents version @value{VERSION}. @menu * Getting the source code:: -* Finding your way around:: * Coding style:: +* Finding your way around:: * Contributing Changes:: * Porting:: * Error Handling:: -* CIA:: * BIOS port memory map:: * Video Subsystem:: * PFF2 Font File Format:: @@ -92,24 +91,36 @@ This edition documents version @value{VERSION}. @node Getting the source code @chapter Getting the source code -GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision -control system}. To fetch the primary development branch: +GRUB is maintained using the @uref{GIT revision +control system}. To fetch: @example -bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub +git clone git://git.sv.gnu.org/grub.git @end example -The GRUB developers maintain several other branches with work in progress. -Of these, the most interesting is the experimental branch, which is a -staging area for new code which we expect to eventually merge into trunk but -which is not yet ready: - +Web access is available under @example -bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental +http://git.savannah.gnu.org/cgit/grub.git/ @end example -Once you have used @kbd{bzr get} to fetch an initial copy of a branch, you -can use @kbd{bzr pull} to keep it up to date. If you have modified your +The branches available are: + +@table @samp +@item master + Main developpement branch. +@item grub-legacy + GRUB 0.97 codebase. Kept for reference and legal reasons +@item multiboot + Multiboot specfication +@item multiboot2 + Multiboot2 specfication +@item developper branches + Prefixed with developper name. Every developper of a team manages his own branches. + Developper branches do not need changelog entries. +@end table + +Once you have used @kbd{git clone} to fetch an initial copy of a branch, you +can use @kbd{git pull} to keep it up to date. If you have modified your local version, you may need to resolve conflicts when pulling. @node Coding style @@ -286,14 +297,19 @@ live under @file{grub-core/term/}. @item The @samp{efiemu_*} commands live under @file{grub-core/efiemu/}. + +@item +OS-dependent code should be under @file{grub-core/osdep/} + +@item +Utility programs meant to be run from a full operating system +(except OS-dependent code mentioned previously) are in @file{util/}. + @end itemize There are a few other special-purpose exceptions; grep for them if they matter to you. -Utility programs meant to be run from a full operating system are in -@file{util/}. - @node Contributing Changes @chapter Contributing changes @c By YoshinoriOkuji, VesaJääskeläinen, ColinWatson @@ -329,10 +345,10 @@ anymore. @itemize @item Always use latest GRUB 2 source code. So get that first. -For developers it is recommended always to use the newest development version of GRUB 2. If development takes a long period of time, please remember to keep in sync with newest developments regularly so it is much easier to integrate your change in the future. GRUB 2 is being developed in a Bazaar (bzr) repository. +For developers it is recommended always to use the newest development version of GRUB 2. If development takes a long period of time, please remember to keep in sync with newest developments regularly so it is much easier to integrate your change in the future. GRUB 2 is being developed in a GIT repository. -Please check Savannah's GRUB project page for details how to get newest bzr: -@uref{http://savannah.gnu.org/bzr/?group=grub, GRUB 2 bzr Repository} +Please check Savannah's GRUB project page for details how to get newest git: +@uref{https://savannah.gnu.org/git/?group=grub, GRUB 2 git Repository} @item Compile it and try it out. @@ -890,34 +906,6 @@ if (grub_errno != GRUB_ERR_NONE) grub_error_pop (); @end example -@node CIA -@chapter CIA -@c By Robert Millan and Carles Pina -If you have commit access, please setup CIA in your Bazaar -config so those in IRC receive notification of your commits. - -In @file{~/.bazaar/bazaar.conf}, add "cia_send_revno = true". -Optionally, you can also add "cia_user = myusername" if you'd -like CIA service to use a specific account (for statistical purpose). - -In the @file{.bzr/branch/branch.conf} of your checkout branch, -"set nickname = /path_to_this_branch" and "cia_project = GNU GRUB". - -Additionally, please set cia_send_revno in the [DEFAULT] section -of your @file{~/.bazaar/bazaar.conf}. E.g.: - -@example -[DEFAULT] -cia_send_revno = true -@end example - -Remember to install cia-clients (Debian/Ubuntu package) to be able to use CIA. - -Keep in mind Bazaar sends notifications for all commits to branches that have -this setting, regardless of whether they're bound branches (checkouts) or not. -So if you make local commits in a non-bound branch and it bothers you that -others can read them, do not use this setting. - @node BIOS port memory map @chapter BIOS port memory map @c By Yoshinori K Okuji @@ -948,8 +936,8 @@ driver manager works are not included here. @menu * Video API:: -* Bitmap API:: * Example usage of Video API:: +* Bitmap API:: @end menu @node Video API @@ -1108,6 +1096,47 @@ struct grub_video_palette_data Used to query indexed color palettes. If mode is RGB mode, colors will be copied from emulated palette data. In Indexed Color modes, palettes will be read from hardware. Color values will be converted to suit structure format. @code{start} will tell what hardware color index (or emulated color index) will be used as a source for first indice of @code{palette_data}, after that both hardware color index and @code{palette_data} index will be incremented until @code{count} number of colors have been read. @end itemize +@subsection grub_video_set_area_status +@itemize + +@item Prototype: +@example +grub_err_t +grub_video_set_area_status (grub_video_area_status_t area_status); +@end example +@example +enum grub_video_area_status_t + @{ + GRUB_VIDEO_AREA_DISABLED, + GRUB_VIDEO_AREA_ENABLED + @}; +@end example + +@item Description: + +Used to set area drawing mode for redrawing the specified region. Draw commands +are performed in the intersection of the viewport and the region called area. +Coordinates remain related to the viewport. If draw commands try to draw over +the area, they are clipped. +Set status to DISABLED if you need to draw everything. +Set status to ENABLED and region to the desired rectangle to redraw everything +inside the region leaving everything else intact. +Should be used for redrawing of active elements. +@end itemize + +@subsection grub_video_get_area_status +@itemize + +@item Prototype: +@example +grub_err_r +grub_video_get_area_status (grub_video_area_status_t *area_status); +@end example + +@item Description: +Used to query the area status. +@end itemize + @subsection grub_video_set_viewport @itemize @item Prototype: @@ -1134,6 +1163,37 @@ grub_video_get_viewport (unsigned int *x, unsigned int *y, unsigned int *width, Used to query current viewport dimensions. Software developer can use this to choose best way to render contents of the viewport. @end itemize +@subsection grub_video_set_region +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_set_region (unsigned int x, unsigned int y, unsigned int width, unsigned int height); +@end example +@item Description: + +Used to specify the region of the screen which should be redrawn. Use absolute +values. When the region is set and area status is ENABLE all draw commands will +be performed inside the interseption of region and viewport named area. +If draw commands try to draw over viewport, they are clipped. If developer +requests larger than possible region, width and height will be clamped to fit +screen. Should be used for redrawing of active elements. +@end itemize + +@subsection grub_video_get_region +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_region (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height); +@end example +@item Description: + +Used to query current region dimensions. +@end itemize + @subsection grub_video_map_color @itemize @item Prototype: diff --git a/docs/grub.texi b/docs/grub.texi index 57c3073fd..b44664fb7 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -20,7 +20,7 @@ This manual is for GNU GRUB (version @value{VERSION}, @value{UPDATED}). -Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012 Free Software Foundation, Inc. +Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -36,8 +36,11 @@ Invariant Sections. * grub-install: (grub)Invoking grub-install. Install GRUB on your drive * grub-mkconfig: (grub)Invoking grub-mkconfig. Generate GRUB configuration * grub-mkpasswd-pbkdf2: (grub)Invoking grub-mkpasswd-pbkdf2. +* grub-mkrelpath: (grub)Invoking grub-mkrelpath. * grub-mkrescue: (grub)Invoking grub-mkrescue. Make a GRUB rescue image +* grub-mount: (grub)Invoking grub-mount. Mount a file system using GRUB * grub-probe: (grub)Invoking grub-probe. Probe device information +* grub-script-check: (grub)Invoking grub-script-check. @end direntry @setchapternewpage odd @@ -78,6 +81,9 @@ This edition documents version @value{VERSION}. @menu * Introduction:: Capturing the spirit of GRUB * Naming convention:: Names of your drives in GRUB +* OS-specific notes about grub tools:: + Some notes about OS-specific behaviour of GRUB + tools * Installation:: Installing GRUB on your drive * Booting:: How to boot different operating systems * Configuration:: Writing your own configuration file @@ -86,12 +92,13 @@ This edition documents version @value{VERSION}. * Serial terminal:: Using GRUB via a serial line * Vendor power-on keys:: Changing GRUB behaviour on vendor power-on keys * Images:: GRUB image files +* Core image size limitation:: GRUB image files size limitations * Filesystem:: Filesystem syntax and semantics * Interface:: The menu and the command-line * Environment:: GRUB environment variables * Commands:: The list of available builtin commands * Internationalisation:: Topics relating to language support -* Security:: Authentication and authorisation +* Security:: Authentication, authorisation, and signatures * Platform limitations:: The list of platform-specific limitations * Platform-specific operations:: Platform-specific operations * Supported kernels:: The list of supported kernels @@ -100,8 +107,11 @@ This edition documents version @value{VERSION}. * Invoking grub-mkconfig:: Generate a GRUB configuration file * Invoking grub-mkpasswd-pbkdf2:: Generate GRUB password hashes +* Invoking grub-mkrelpath:: Make system path relative to its root * Invoking grub-mkrescue:: Make a GRUB rescue image +* Invoking grub-mount:: Mount a file system using GRUB * Invoking grub-probe:: Probe device information for GRUB +* Invoking grub-script-check:: Check GRUB script file for syntax errors * Obtaining and Building GRUB:: How to obtain and build GRUB * Reporting bugs:: Where you should send a bug report * Future:: Some future plans on GRUB @@ -311,8 +321,10 @@ tables are also loaded. @item Support non-Multiboot kernels Support many of the various free 32-bit kernels that lack Multiboot -compliance (primarily FreeBSD, NetBSD, OpenBSD, and -Linux). Chain-loading of other boot loaders is also supported. +compliance (primarily FreeBSD, NetBSD@footnote{The NetBSD/i386 kernel +is Multiboot-compliant, but lacks support for Multiboot modules.}, +OpenBSD, and Linux). Chain-loading of other boot loaders is also +supported. @item Load multiples modules Fully support the Multiboot feature of loading multiple modules. @@ -529,6 +541,75 @@ completion works with file names, too. That was easy, admit it. Now read the next chapter, to find out how to actually install GRUB on your drive. +@node OS-specific notes about grub tools +@chapter OS-specific notes about grub tools + +On OS which have device nodes similar to Unix-like OS GRUB tools use the +OS name. E.g. for GNU/Linux: + +@example +# @kbd{grub-install /dev/sda} +@end example + +On AROS we use another syntax. For volumes: + +@example +//: +@end example + +E.g. + +@example +//:DH0 +@end example + +For disks we use syntax: +@example +//:/unit/flags +@end example + +E.g. + +@example +# @kbd{grub-install //:ata.device/0/0} +@end example + +On Windows we use UNC path. For volumes it's typically + +@example +\\?\Volume@{@} +\\?\: +@end example + +E.g. + +@example +\\?\Volume@{17f34d50-cf64-4b02-800e-51d79c3aa2ff@} +\\?\C: +@end example + + +For disks it's + +@example +\\?\PhysicalDrive +@end example + +E.g. + +@example +# @kbd{grub-install \\?\PhysicalDrive0} +@end example + +Beware that you may need to further escape the backslashes depending on your +shell. + +When compiled with cygwin support then cygwin drive names are automatically +when needed. E.g. + +@example +# @kbd{grub-install /dev/sda} +@end example @node Installation @chapter Installation @@ -575,7 +656,7 @@ For example, under Linux the following will install GRUB into the MBR of the first IDE disk: @example -# @kbd{grub-install /dev/hda} +# @kbd{grub-install /dev/sda} @end example Likewise, under GNU/Hurd, this has the same effect: @@ -614,11 +695,31 @@ This install doesn't conflict with standard install as long as they are in separate directories. Note that @command{grub-install} is actually just a shell script and the -real task is done by @command{grub-mkimage} and @command{grub-setup}. -Therefore, you may run those commands directly to install GRUB, without -using @command{grub-install}. Don't do that, however, unless you are very -familiar with the internals of GRUB. Installing a boot loader on a running -OS may be extremely dangerous. +real task is done by other tools such as @command{grub-mkimage}. Therefore, +you may run those commands directly to install GRUB, without using +@command{grub-install}. Don't do that, however, unless you are very familiar +with the internals of GRUB. Installing a boot loader on a running OS may be +extremely dangerous. + +On EFI systems for fixed disk install you have to mount EFI System Partition. +If you mount it at @file{/boot/efi} then you don't need any special arguments: + +@example +# @kbd{grub-install} +@end example + +Otherwise you need to specify where your EFI System partition is mounted: + +@example +# @kbd{grub-install --efi-directory=/mnt/efi} +@end example + +For removable installs you have to use @option{--removable} and specify both +@option{--boot-directory} and @option{--efi-directory}: + +@example +# @kbd{grub-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable} +@end example @node Making a GRUB bootable CD-ROM @section Making a GRUB bootable CD-ROM @@ -680,8 +781,8 @@ storage devices. @section The map between BIOS drives and OS devices If the device map file exists, the GRUB utilities (@command{grub-probe}, -@command{grub-setup}, etc.) read it to map BIOS drives to OS devices. This -file consists of lines like this: +etc.) read it to map BIOS drives to OS devices. This file consists of lines +like this: @example (@var{device}) @var{file} @@ -897,6 +998,7 @@ Here, we describe some caveats on several operating systems. @menu * GNU/Hurd:: * GNU/Linux:: +* NetBSD:: * DOS/Windows:: @end menu @@ -997,6 +1099,63 @@ the size, run the command @command{uppermem} @emph{before} loading the kernel. @xref{uppermem}, for more information. +@node NetBSD +@subsection NetBSD + +Booting a NetBSD kernel from GRUB is also relatively easy: first set +GRUB's root device, then load the kernel and the modules, and finally +run @command{boot}. + +@enumerate +@item +Set GRUB's root device to the partition holding the NetBSD root file +system. For a disk with a NetBSD disk label, this is usually the first +partition (a:). In that case, and assuming that the partition is on the +first hard disk, set GRUB's root device as follows: + +@example +grub> @kbd{insmod part_bsd} +grub> @kbd{set root=(hd0,netbsd1)} +@end example + +For a disk with a GUID Partition Table (GPT), and assuming that the +NetBSD root partition is the third GPT partition, do this: + +@example +grub> @kbd{insmod part_gpt} +grub> @kbd{set root=(hd0,gpt3)} +@end example + +@item +Load the kernel using the command @command{knetbsd}: + +@example +grub> @kbd{knetbsd /netbsd} +@end example + +Various options may be given to @command{knetbsd}. These options are, +for the most part, the same as in the NetBSD boot loader. For instance, +to boot the system in single-user mode and with verbose messages, do +this: + +@example +grub> @kbd{knetbsd /netbsd -s -v} +@end example + +@item +If needed, load kernel modules with the command +@command{knetbsd_module_elf}. A typical example is the module for the +root file system: + +@example +grub> @kbd{knetbsd_module_elf /stand/amd64/6.0/modules/ffs/ffs.kmod} +@end example + +@item +Finally, run the command @command{boot} (@pxref{boot}). +@end enumerate + + @node DOS/Windows @subsection DOS/Windows @@ -1095,14 +1254,14 @@ Valid keys in @file{/etc/default/grub} are as follows: @item GRUB_DEFAULT The default menu entry. This may be a number, in which case it identifies the Nth entry in the generated menu counted from zero, or the title of a -menu entry, or the special string @samp{saved}. Using the title may be +menu entry, or the special string @samp{saved}. Using the id may be useful if you want to set a menu entry as the default even though there may be a variable number of entries before it. For example, if you have: @verbatim -menuentry 'Example GNU/Linux distribution' --class gnu-linux { +menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux { ... } @end verbatim @@ -1110,12 +1269,17 @@ menuentry 'Example GNU/Linux distribution' --class gnu-linux { then you can make this the default using: @example -GRUB_DEFAULT='Example GNU/Linux distribution' +GRUB_DEFAULT=example-gnu-linux @end example +Previously it was documented the way to use entry title. While this still +works it's not recommended since titles often contain unstable device names +and may be translated + If you set this to @samp{saved}, then the default menu entry will be that -saved by @samp{GRUB_SAVEDEFAULT}, @command{grub-set-default}, or -@command{grub-reboot}. +saved by @samp{GRUB_SAVEDEFAULT} or @command{grub-set-default}. This relies on +the environment block, which may not be available in all situations +(@pxref{Environment block}). The default is @samp{0}. @@ -1124,7 +1288,7 @@ If this option is set to @samp{true}, then, when an entry is selected, save it as a new default entry for use by future runs of GRUB. This is only useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because @samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with -@command{grub-set-default} or @command{grub-reboot}. Unset by default. +@command{grub-set-default}. Unset by default. This option relies on the environment block, which may not be available in all situations (@pxref{Environment block}). @@ -1135,11 +1299,12 @@ immediately without displaying the menu, or to @samp{-1} to wait indefinitely. @item GRUB_HIDDEN_TIMEOUT -Wait this many seconds for a key to be pressed before displaying the menu. -If no key is pressed during that time, display the menu for the number of +Wait this many seconds for @key{ESC} to be pressed before displaying the menu. +If no @key{ESC} is pressed during that time, display the menu for the number of seconds specified in GRUB_TIMEOUT before booting the default entry. We expect that most people who use GRUB_HIDDEN_TIMEOUT will want to have GRUB_TIMEOUT set -to @samp{0} so that the menu is not displayed at all unless a key is pressed. +to @samp{0} so that the menu is not displayed at all unless @key{ESC} is +pressed. Unset by default. @item GRUB_HIDDEN_TIMEOUT_QUIET @@ -1163,9 +1328,9 @@ Select the terminal input device. You may select multiple devices here, separated by spaces. Valid terminal input names depend on the platform, but may include -@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal), -@samp{ofconsole} (Open Firmware console), @samp{at_keyboard} (PC AT -keyboard, mainly useful with Coreboot), or @samp{usb_keyboard} (USB keyboard +@samp{console} (native platform console), @samp{serial} (serial terminal), +@samp{serial_} (serial terminal with explicit port selection), +@samp{at_keyboard} (PC AT keyboard), or @samp{usb_keyboard} (USB keyboard using the HID Boot Protocol, for cases where the firmware does not handle this). @@ -1176,9 +1341,21 @@ Select the terminal output device. You may select multiple devices here, separated by spaces. Valid terminal output names depend on the platform, but may include -@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal), -@samp{gfxterm} (graphics-mode output), @samp{ofconsole} (Open Firmware -console), or @samp{vga_text} (VGA text output, mainly useful with Coreboot). +@samp{console} (native platform console), @samp{serial} (serial terminal), +@samp{serial_} (serial terminal with explicit port selection), +@samp{gfxterm} (graphics-mode output), @samp{vga_text} (VGA text output), +@samp{mda_text} (MDA text output), @samp{morse} (Morse-coding using system +beeper) or @samp{spkmodem} (simple data protocol using system speaker). + +@samp{spkmodem} is useful when no serial port is available. Connect the output +of sending system (where GRUB is running) to line-in of receiving system +(usually developer machine). +On receiving system compile @samp{spkmodem-recv} from +@samp{util/spkmodem-recv.c} and run: + +@example +parecord --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv +@end example The default is to use the platform's native terminal output. @@ -1210,9 +1387,8 @@ As @samp{GRUB_CMDLINE_LINUX}, but for GNU Mach. @item GRUB_CMDLINE_XEN @itemx GRUB_CMDLINE_XEN_DEFAULT -The values of these options are appended to the values of -@samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux -and Xen menu entries. +The values of these options are passed to Xen hypervisor Xen menu entries, +for all respectively normal entries. @item GRUB_CMDLINE_LINUX_XEN_REPLACE @item GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT @@ -1275,6 +1451,24 @@ Normally, @command{grub-mkconfig} will try to use the external systems installed on the same system and generate appropriate menu entries for them. Set this option to @samp{true} to disable this. +@item GRUB_DISABLE_SUBMENU +Normally, @command{grub-mkconfig} will generate top level menu entry for +the kernel with highest version number and put all other found kernels +or alternative menu entries for recovery mode in submenu. For entries returned +by @command{os-prober} first entry will be put on top level and all others +in submenu. If this option is set to @samp{y}, flat menu with all entries +on top level will be generated instead. Changing this option will require +changing existing values of @samp{GRUB_DEFAULT}, @samp{fallback} (@pxref{fallback}) +and @samp{default} (@pxref{default}) environment variables as well as saved +default entry using @command{grub-set-default} and value used with +@command{grub-reboot}. + +@item GRUB_ENABLE_CRYPTODISK +If set to @samp{y}, @command{grub-mkconfig} and @command{grub-install} will +check for encrypted disks and generate additional commands needed to access +them during boot. Note that in this case unattended boot is not possible +because GRUB will wait for passphrase to unlock encrypted container. + @item GRUB_INIT_TUNE Play a tune on the speaker when GRUB starts. This is particularly useful for users unable to see the screen. The value of this option is passed @@ -1451,7 +1645,7 @@ definitions do not affect the exit status in @code{$?}. When executed, the exit status of a function is the exit status of the last command executed in the body. -@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--unrestricted}] [@option{--hotkey=key}] @{ @var{command}; @dots{} @} +@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @{ @var{command}; @dots{} @} @xref{menuentry}. @end table @@ -1483,6 +1677,10 @@ Causes a function to exit with the return value specified by @code{n}. If in the function body. If used outside a function the return status is false. +@item setparams [@code{arg}] @dots{} +Replace positional parameters starting with @code{$1} with arguments to +@command{setparams}. + @item shift [@code{n}] The positional parameters from @code{n}+1 @dots{} are renamed to @code{$1}@dots{}. Parameters represented by the numbers @code{$#} down to @@ -1587,7 +1785,7 @@ menuentry "Debian sid installer" @{ Notes: @itemize -@item Argument to search after --label is FS LABEL. You can also use UUIDs with --fs-uuid UUID instead of --label LABEL. You could also use direct @code{root=hd0,msdosX} but this is not recommened due to device name instability. +@item Argument to search after --label is FS LABEL. You can also use UUIDs with --fs-uuid UUID instead of --label LABEL. You could also use direct @code{root=hd0,msdosX} but this is not recommended due to device name instability. @end itemize @node Embedded configuration @@ -1680,8 +1878,8 @@ Colors can be specified in several ways: The fonts GRUB uses ``PFF2 font format'' bitmap fonts. Fonts are specified with full font names. Currently there is no provision for a preference list of fonts, or deriving one font from another. -Fonts are loaded with the ``loadfont'' command in GRUB. To see the list of -loaded fonts, execute the ``lsfonts'' command. If there are too many fonts to +Fonts are loaded with the ``loadfont'' command in GRUB (@ref{loadfont}). To see the list of +loaded fonts, execute the ``lsfonts'' command (@ref{lsfonts}). If there are too many fonts to fit on screen, do ``set pager=1'' before executing ``lsfonts''. @@ -1821,15 +2019,60 @@ In this example, name3 is assigned a color value. @subsection Global Property List @multitable @columnfractions 0.3 0.6 -@item title-text @tab Specifies the text to display at the top center of the screen as a title. -@item title-font @tab Defines the font used for the title message at the top of the screen. -@item title-color @tab Defines the color of the title message. -@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry. -@item message-color @tab Defines the color of the message text. -@item message-bg-color @tab Defines the background color of the message text area. -@item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size. -@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified. -@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty. +@item title-text + @tab Specifies the text to display at the top center of the screen as a title. +@item title-font + @tab Defines the font used for the title message at the top of the screen. +@item title-color + @tab Defines the color of the title message. +@item message-font + @tab Currently unused. Left for backward compatibility. +@item message-color + @tab Currently unused. Left for backward compatibility. +@item message-bg-color + @tab Currently unused. Left for backward compatibility. +@item desktop-image + @tab Specifies the image to use as the background. It will be scaled + to fit the screen size or proportionally scaled depending on the scale + method. +@item desktop-image-scale-method + @tab Specifies the scaling method for the *desktop-image*. Options are + ``stretch``, ``crop``, ``padding``, ``fitwidth``, ``fitheight``. + ``stretch`` for fitting the screen size. Otherwise it is proportional + scaling of a part of *desktop-image* to the part of the screen. + ``crop`` part of the *desktop-image* will be proportionally scaled to + fit the screen sizes. ``padding`` the entire *desktop-image* will be + contained on the screen. ``fitwidth`` for fitting the *desktop-image*'s + width with screen width. ``fitheight`` for fitting the *desktop-image*'s + height with the screen height. Default is ``stretch``. +@item desktop-image-h-align + @tab Specifies the horizontal alignment of the *desktop-image* if + *desktop-image-scale-method* isn't equeal to ``stretch``. Options are + ``left``, ``center``, ``right``. Default is ``center``. +@item desktop-image-v-align + @tab Specifies the vertical alignment of the *desktop-image* if + *desktop-image-scale-method* isn't equeal to ``stretch``. Options are + ``top``, ``center``, ``bottom``. Default is ``center``. +@item desktop-color + @tab Specifies the color for the background if *desktop-image* is not + specified. +@item terminal-box + @tab Specifies the file name pattern for the styled box slices used for the + command line terminal window. For example, ``terminal-box: terminal_*.png`` + will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` + as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) + corner, and so on. If the image for any slice is not found, it will simply + be left empty. +@item terminal-border + @tab Specifies the border width of the terminal window. +@item terminal-left + @tab Specifies the left coordinate of the terminal window. +@item terminal-top + @tab Specifies the top coordinate of the terminal window. +@item terminal-width + @tab Specifies the width of the terminal window. +@item terminal-height + @tab Specifies the height of the terminal window. @end multitable @@ -1863,21 +2106,34 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.2 0.7 - @item text @tab The text to display. - @item font @tab The font to use for text display. - @item color @tab The color of the text. - @item align @tab The horizontal alignment of the text within the component. Options are ``left``, ``center``, and ``right``. + @item id + @tab Set to ``__timeout__`` to display the time elapsed to an automatical + boot of the default entry. + @item text + @tab The text to display. If ``id`` is set to ``__timeout__`` and no + ``text`` property is set then the amount of seconds will be shown. + If set to ``@@KEYMAP_SHORT@@``, ``@@KEYMAP_MIDDLE@@`` or + ``@@KEYMAP_LONG@@`` then predefined hotkey information will be shown. + @item font + @tab The font to use for text display. + @item color + @tab The color of the text. + @item align + @tab The horizontal alignment of the text within the component. + Options are ``left``, ``center`` and ``right``. + @item visible + @tab Set to ``false`` to hide the label. @end multitable @item image - A component that displays an image. The image is scaled to fit the - component, although the preferred size defaults to the image's original - size unless the ``preferred_size`` property is explicitly set. + A component that displays an image. The image is scaled to fit + the component. Properties: @multitable @columnfractions 0.2 0.7 - @item file @tab The full path to the image file to load. + @item file + @tab The full path to the image file to load. @end multitable @item progress_bar @@ -1887,17 +2143,45 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.2 0.7 - @item fg_color @tab The foreground color for plain solid color rendering. - @item bg_color @tab The background color for plain solid color rendering. - @item border_color @tab The border color for plain solid color rendering. - @item text_color @tab The text color. - @item show_text @tab Boolean value indicating whether or not text should be displayed on the progress bar. If set to *false*, then no text will be displayed on the bar. If set to any other value, text will be displayed on the bar. - @item bar_style @tab The styled box specification for the frame of the progress bar. Example: ``progress_frame_*.png`` - @item highlight_style @tab The styled box specification for the highlighted region of the progress bar. This box will be used to paint just the highlighted region of the bar, and will be increased in size as the bar nears completion. Example: ``progress_hl_*.png``. - @item text @tab The text to display on the progress bar. If the progress bar's ID is set to ``__timeout__``, then GRUB will updated this property with an informative message as the timeout approaches. - @item value @tab The progress bar current value. Normally not set manually. - @item start @tab The progress bar start value. Normally not set manually. - @item end @tab The progress bar end value. Normally not set manually. + @item id + @tab Set to ``__timeout__`` to display the time elapsed to an automatical + boot of the default entry. + @item fg_color + @tab The foreground color for plain solid color rendering. + @item bg_color + @tab The background color for plain solid color rendering. + @item border_color + @tab The border color for plain solid color rendering. + @item text_color + @tab The text color. + @item bar_style + @tab The styled box specification for the frame of the progress bar. + Example: ``progress_frame_*.png`` + If the value is equal to ``highlight_style`` then no styled boxes + will be shown. + @item highlight_style + @tab The styled box specification for the highlighted region of the + progress bar. This box will be used to paint just the highlighted region + of the bar, and will be increased in size as the bar nears completion. + Example: ``progress_hl_*.png``. + If the value is equal to ``bar_style`` then no styled boxes + will be shown. + @item highlight_overlay + @tab If this option is set to ``true`` then the highlight box + side slices (every slice except the center slice) will overlay the + frame box side slices. And the center slice of the highlight box + can move all the way (from top to bottom), being drawn on the center + slice of the frame box. That way we can make a progress bar with + round-shaped edges so there won't be a free space from the highlight to + the frame in top and bottom scrollbar positions. Default is ``false``. + @item font + @tab The font to use for progress bar. + @item text + @tab The text to display on the progress bar. If the progress bar's ID + is set to ``__timeout__`` and the value of this property is set to + ``@@TIMEOUT_NOTIFICATION_SHORT@@``, ``@@TIMEOUT_NOTIFICATION_MIDDLE@@`` + or ``@@TIMEOUT_NOTIFICATION_LONG@@``, then GRUB will update this + property with an informative message as the timeout approaches. @end multitable @item circular_progress @@ -1911,6 +2195,9 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.3 0.6 + @item id + @tab Set to ``__timeout__`` to display the time elapsed to an automatical + boot of the default entry. @item center_bitmap @tab The file name of the image to draw in the center of the component. @item tick_bitmap @@ -1920,14 +2207,13 @@ The following is a list of the components and the properties they support. @item ticks_disappear @tab Boolean value indicating whether tick marks should progressively appear, or progressively disappear as *value* approaches *end*. Specify - ``true`` or ``false``. - @item value - @tab The progress indicator current value. Normally not set manually. - @item start - @tab The progress indicator start value. Normally not set manually. - @item end - @tab The progress indicator end value. Normally not set manually. + ``true`` or ``false``. Default is ``false``. + @item start_angle + @tab The position of the first tick mark to appear or disappear. + Measured in "parrots", 1 "parrot" = 1 / 256 of the full circle. + Use values ``xxx deg`` or ``xxx \xc2\xb0`` to set the angle in degrees. @end multitable + @item boot_menu Displays the GRUB boot menu. It allows selecting items and executing them. @@ -1961,6 +2247,8 @@ The following is a list of the components and the properties they support. @tab The image file pattern for the menu frame styled box. Example: ``menu_*.png`` (this will use images such as ``menu_c.png``, ``menu_w.png``, `menu_nw.png``, etc.) + @item item_pixmap_style + @tab The image file pattern for the item styled box. @item selected_item_pixmap_style @tab The image file pattern for the selected item highlight styled box. @item scrollbar @@ -1973,10 +2261,39 @@ The following is a list of the components and the properties they support. @tab The image file pattern for the scroll bar thumb (the part of the scroll bar that moves as scrolling occurs). Example: ``scrollbar_thumb_*.png`` - @item max_items_shown - @tab The maximum number of items to show on the menu. If there are more than - *max_items_shown* items in the menu, the list will scroll to make all - items accessible. + @item scrollbar_thumb_overlay + @tab If this option is set to ``true`` then the scrollbar thumb + side slices (every slice except the center slice) will overlay the + scrollbar frame side slices. And the center slice of the scrollbar_thumb + can move all the way (from top to bottom), being drawn on the center + slice of the scrollbar frame. That way we can make a scrollbar with + round-shaped edges so there won't be a free space from the thumb to + the frame in top and bottom scrollbar positions. Default is ``false``. + @item scrollbar_slice + @tab The menu frame styled box's slice in which the scrollbar will be + drawn. Possible values are ``west``, ``center``, ``east`` (default). + ``west`` - the scrollbar will be drawn in the west slice (right-aligned). + ``east`` - the scrollbar will be drawn in the east slice (left-aligned). + ``center`` - the scrollbar will be drawn in the center slice. + Note: in case of ``center`` slice: + a) If the scrollbar should be drawn then boot menu entry's width is + decreased by the scrollbar's width and the scrollbar is drawn at the + right side of the center slice. + b) If the scrollbar won't be drawn then the boot menu entry's width + is the width of the center slice. + c) We don't necessary need the menu pixmap box to display the scrollbar. + @item scrollbar_left_pad + @tab The left scrollbar padding in pixels. + Unused if ``scrollbar_slice`` is ``west``. + @item scrollbar_right_pad + @tab The right scrollbar padding in pixels. + Unused if ``scrollbar_slice`` is ``east``. + @item scrollbar_top_pad + @tab The top scrollbar padding in pixels. + @item scrollbar_bottom_pad + @tab The bottom scrollbar padding in pixels. + @item visible + @tab Set to ``false`` to hide the boot menu. @end multitable @item canvas @@ -2020,7 +2337,10 @@ The following properties are supported by all components: recognizes: @multitable @columnfractions 0.2 0.7 - @item ``__timeout__`` @tab Any component with this ID will have its *text*, *start*, *end*, *value*, and *visible* properties set by GRUB when it is counting down to an automatic boot of the default menu entry. + @item ``__timeout__`` + @tab Component with this ID will be updated by GRUB and will indicate + time elapsed to an automatical boot of the default entry. + Affected components: ``label``, ``circular_progress``, ``progress_bar``. @end multitable @end table @@ -2029,67 +2349,83 @@ The following properties are supported by all components: @node Network @chapter Booting GRUB from the network -The following instructions only work on PC BIOS systems where the Preboot -eXecution Environment (PXE) is available. +The following instructions don't work for *-emu, i386-qemu, i386-coreboot, +i386-multiboot, mips_loongson, mips-arc and mips_qemu_mips -To generate a PXE boot image, run: +To generate a netbootable directory, run: @example @group -grub-mkimage --format=i386-pc-pxe --output=grub.pxe --prefix='(pxe)/boot/grub' pxe pxecmd +grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/ @end group @end example -Copy @file{grub.pxe}, @file{/boot/grub/*.mod}, and @file{/boot/grub/*.lst} -to the PXE (TFTP) server, ensuring that @file{*.mod} and @file{*.lst} are -accessible via the @file{/boot/grub/} path from the TFTP server root. Set -the DHCP server configuration to offer @file{grub.pxe} as the boot file (the -@samp{filename} option in ISC dhcpd). +E.g. for i386-pc: -You can also use the @command{grub-mknetdir} utility to generate an image -and a GRUB directory tree, rather than copying files around manually. +@example +@group +grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i386-pc +@end group +@end example + +Then follow instructions printed out by grub-mknetdir on configuring your DHCP +server. After GRUB has started, files on the TFTP server will be accessible via the -@samp{(pxe)} device. +@samp{(tftp)} device. -The server and gateway IP address can be controlled by changing the -@samp{(pxe)} device name to @samp{(pxe:@var{server-ip})} or -@samp{(pxe:@var{server-ip}:@var{gateway-ip})}. Note that this should be -changed both in the prefix and in any references to the device name in the -configuration file. +The server IP address can be controlled by changing the +@samp{(tftp)} device name to @samp{(tftp,@var{server-ip})}. Note that +this should be changed both in the prefix and in any references to the +device name in the configuration file. GRUB provides several environment variables which may be used to inspect or -change the behaviour of the PXE device: +change the behaviour of the PXE device. In the following description +@var{} is placeholder for the name of network interface (platform +dependent): @table @samp -@item net_pxe_ip -The IP address of this machine. Read-only. +@item net_@var{}_ip +The network interface's IP address. Read-only. -@item net_pxe_mac +@item net_@var{}_mac The network interface's MAC address. Read-only. -@item net_pxe_hostname +@item net_@var{}_hostname The client host name provided by DHCP. Read-only. -@item net_pxe_domain +@item net_@var{}_domain The client domain name provided by DHCP. Read-only. -@item net_pxe_rootpath +@item net_@var{}_rootpath The path to the client's root disk provided by DHCP. Read-only. -@item net_pxe_extensionspath +@item net_@var{}_extensionspath The path to additional DHCP vendor extensions provided by DHCP. Read-only. -@item net_pxe_boot_file +@item net_@var{}_boot_file The boot file name provided by DHCP. Read-only. -@item net_pxe_dhcp_server_name +@item net_@var{}_dhcp_server_name The name of the DHCP server responsible for these boot parameters. Read-only. +@item net_default_interface +Initially set to name of network interface that was used to load grub. +Read-write, although setting it affects only interpretation of +@samp{net_default_ip} and @samp{net_default_mac} + +@item net_default_ip +The IP address of default interface. Read-only. This is alias for the +@samp{net_$@{net_default_interface@}_ip}. + +@item net_default_mac +The default interface's MAC address. Read-only. This is alias for the +@samp{net_$@{net_default_interface@}_mac}. + @item net_default_server -The default server. Read-write, although setting this is only useful -before opening a network device. +The default server used by network drives (@pxref{Device syntax}). Read-write, +although setting this is only useful before opening a network device. @end table @@ -2157,8 +2493,12 @@ button. @samp{GRUB_BUTTON_CMOS_ADDRESS} is vendor-specific and partially model-specific. Values known to the GRUB team are: @table @key +@item Dell XPS M1330M +121:3 @item Dell XPS M1530 85:3 +@item Dell Latitude E4300 +85:3 @item Asus EeePC 1005PE 84:1 (unconfirmed) @end table @@ -2225,8 +2565,8 @@ bytes. The sole function of @file{boot.img} is to read the first sector of the core image from a local disk and jump to it. Because of the size restriction, @file{boot.img} cannot understand any file system structure, so -@command{grub-setup} hardcodes the location of the first sector of the core -image into @file{boot.img} when installing GRUB. +@command{grub-install} hardcodes the location of the first sector of the +core image into @file{boot.img} when installing GRUB. @item diskboot.img This image is used as the first sector of the core image when booting from a @@ -2319,6 +2659,44 @@ In GRUB 2, images for PXE network booting are now constructed using contains the @samp{pxe} and @samp{pxecmd} modules. @xref{Network}. @end table +@node Core image size limitation +@chapter Core image size limitation + +Heavily limited platforms: +@itemize +@item i386-pc (normal and PXE): the core image size (compressed) is limited by 458240 bytes. + kernel.img (.text + .data + .bss, uncompressed) is limited by 392704 bytes. + module size (uncompressed) + kernel.img (.text + .data, uncompressed) is limited by the size of contiguous chunk at 1M address. +@item sparc64-ieee1275: kernel.img (.text + .data + .bss) + modules + 256K (stack) + 2M (heap) is limited by space available at 0x4400. On most platforms it's just 3 or 4M since ieee1275 maps only so much. +@item i386-ieee1275: kernel.img (.text + .data + .bss) + modules is limited by memory available at 0x10000, at most 596K +@end itemize + +Lightly limited platforms: + +@itemize +@item *-xen: limited only by adress space and RAM size. +@item i386-qemu: kernel.img (.text + .data + .bss) is limited by 392704 bytes. + (core.img would be limited by ROM size but it's unlimited on qemu +@item All EFI platforms: limited by contiguous RAM size and possibly firmware bugs +@item Coreboot and multiboot. kernel.img (.text + .data + .bss) is limited by 392704 bytes. + module size is limited by the size of contiguous chunk at 1M address. +@item mipsel-loongson (ELF), mips(el)-qemu_mips (ELF): if uncompressed: + kernel.img (.text + .data) + modules is limited by the space from 80200000 forward + if compressed: + kernel.img (.text + .data, uncompressed) + modules (uncompressed) + + (modules + kernel.img (.text + .data)) (compressed) + + decompressor is limited by the space from 80200000 forward +@item mipsel-loongson (Flash), mips(el)-qemu_mips (Flash): kernel.img (.text + .data) + modules is limited by the space from 80200000 forward + core.img (final) is limited by flash size (512K on yeeloong and fulooong) +@item mips-arc: if uncompressed: + kernel.img (.text + .data) is limited by the space from 8bd00000 forward + modules + dummy decompressor is limited by the space from 8bd00000 backward + if compressed: + kernel.img (.text + .data, uncompressed) is limited by the space from 8bd00000 forward + modules (uncompressed) + (modules + kernel.img (.text + .data)) (compressed, aligned to 1M) + + 1M (decompressor + scratch space) is limited by the space from 8bd00000 backward +@item powerpc-ieee1275: kernel.img (.text + .data + .bss) + modules is limited by space available at 0x200000 +@end itemize @node Filesystem @chapter Filesystem syntax and semantics @@ -2352,16 +2730,17 @@ by a digit, like @samp{fd0}, or @samp{cd}. AHCI, PATA (ata), crypto, USB use the name of driver followed by a number. Memdisk and host are limited to one disk and so it's refered just by driver name. -RAID (md), ofdisk (ieee1275 and nand), LVM (lv), LDM and arcdisk (arc) use -intrinsic name of disk prefixed by driver name. Additionally just ``nand'' -refers to the disk aliased as ``nand''. +RAID (md), ofdisk (ieee1275 and nand), LVM (lvm), LDM, virtio (vdsk) +and arcdisk (arc) use intrinsic name of disk prefixed by driver name. +Additionally just ``nand'' refers to the disk aliased as ``nand''. Conflicts are solved by suffixing a number if necessarry. Commas need to be escaped. Loopback uses whatever name specified to @command{loopback} command. Hostdisk uses names specified in device.map as long as it's of the form [fhc]d[0-9]* or hostdisk/. For crypto and RAID (md) additionally you can use the syntax -uuid/. +uuid/. For LVM additionally you can use the syntax +lvmid//. @example (fd0) @@ -2373,7 +2752,8 @@ For crypto and RAID (md) additionally you can use the syntax (usb0) (cryptouuid/123456789abcdef0123456789abcdef0) (mduuid/123456789abcdef0123456789abcdef0) -(lv/system-root) +(lvm/system-root) +(lvmid/F1ikgD-2RES-306G-il9M-7iwa-4NKW-EbV1NV/eLGuCQ-L4Ka-XUgR-sjtJ-ffch-bajr-fCNfz5) (md/myraid) (md/0) (ieee1275/disk2) @@ -2404,8 +2784,10 @@ of the partition when installing GRUB). (hd0,1,3) @end example -If you enabled the network support, the special drives @samp{(tftp)}, -@samp{(http)} and so on ars also available. +If you enabled the network support, the special drives +@code{(@var{protocol}[,@var{server}])} are also available. Supported protocols +are @samp{http} and @samp{tftp}. If @var{server} is omitted, value of +environment variable @samp{net_default_server} is used. Before using the network drive, you must initialize the network. @xref{Network}, for more information. @@ -2428,6 +2810,13 @@ GRUB's @dfn{root device} implicitly. So if you set the root device to, say, @samp{(hd1,1)} by the command @samp{set root=(hd1,1)} (@pxref{set}), then @code{/boot/kernel} is the same as @code{(hd1,1)/boot/kernel}. +On ZFS filesystem the first path component must be +@var{volume}@samp{@@}[@var{snapshot}]. +So @samp{/rootvol@@snap-129/boot/grub/grub.cfg} refers to file +@samp{/boot/grub/grub.cfg} in snapshot of volume @samp{rootvol} with name +@samp{snap-129}. Trailing @samp{@@} after volume name is mandatory even if +snapshot name is omitted. + @node Block list syntax @section How to specify block lists @@ -2607,6 +2996,7 @@ These variables have special meaning to GRUB. @menu * biosnum:: +* check_signatures:: * chosen:: * color_highlight:: * color_normal:: @@ -2616,19 +3006,25 @@ These variables have special meaning to GRUB. * gfxmode:: * gfxpayload:: * gfxterm_font:: +* grub_cpu:: +* grub_platform:: * icondir:: * lang:: * locale_dir:: * menu_color_highlight:: * menu_color_normal:: -* net_pxe_boot_file:: -* net_pxe_dhcp_server_name:: -* net_pxe_domain:: -* net_pxe_extensionspath:: -* net_pxe_hostname:: -* net_pxe_ip:: -* net_pxe_mac:: -* net_pxe_rootpath:: +* net_@var{}_boot_file:: +* net_@var{}_dhcp_server_name:: +* net_@var{}_domain:: +* net_@var{}_extensionspath:: +* net_@var{}_hostname:: +* net_@var{}_ip:: +* net_@var{}_mac:: +* net_@var{}_rootpath:: +* net_default_interface:: +* net_default_ip:: +* net_default_mac:: +* net_default_server:: * pager:: * prefix:: * pxe_blksize:: @@ -2654,6 +3050,12 @@ For an alternative approach which also changes BIOS drive mappings for the chain-loaded system, @pxref{drivemap}. +@node check_signatures +@subsection check_signatures + +This variable controls whether GRUB enforces digital signature +validation on loaded files. @xref{Using digital signatures}. + @node chosen @subsection chosen @@ -2703,6 +3105,31 @@ those colors. Each color must be a name from the following list: The default is @samp{white/black}. +The color support support varies from terminal to terminal. + +@samp{morse} has no color support at all. + +@samp{mda_text} color support is limited to highlighting by +black/white reversal. + +@samp{console} on ARC, EMU and IEEE1275, @samp{serial_*} and +@samp{spkmodem} are governed by terminfo and support +only 8 colors if in modes @samp{vt100-color} (default for console on emu), +@samp{arc} (default for console on ARC), @samp{ieee1275} (default +for console on IEEE1275). When in mode @samp{vt100} +then the color support is limited to highlighting by black/white +reversal. When in mode @samp{dumb} there is no color support. + +When console supports no colors this setting is ignored. +When console supports 8 colors, then the colors from the +second half of the previous list are mapped to the +matching colors of first half. + +@samp{console} on EFI and BIOS and @samp{vga_text} support all 16 colors. + +@samp{gfxterm} supports all 16 colors and would be theoretically extendable +to support whole rgb24 palette but currently there is no compelling reason +to go beyond the current 16 colors. @node debug @subsection debug @@ -2710,7 +3137,8 @@ The default is @samp{white/black}. This variable may be set to enable debugging output from various components of GRUB. The value is a list of debug facility names separated by whitespace or @samp{,}, or @samp{all} to enable all available debugging -output. +output. The facility names are the first argument to grub_dprintf. Consult +source for more details. @node default @@ -2718,7 +3146,21 @@ output. If this variable is set, it identifies a menu entry that should be selected by default, possibly after a timeout (@pxref{timeout}). The entry may be -identified by number or by title. +identified by number or by id. + +For example, if you have: + +@verbatim +menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux { + ... +} +@end verbatim + +then you can make this the default using: + +@example +default=example-gnu-linux +@end example If the entry is in a submenu, then it must be identified using the titles of each of the submenus starting from the top level followed by the number or @@ -2758,7 +3200,8 @@ If this variable is set, it sets the resolution used on the @samp{gfxterm} graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be available. The default is @samp{auto}, which -selects a platform-specific default that should look reasonable. +selects a platform-specific default that should look reasonable. Supported +modes can be listed by @samp{videoinfo} command in GRUB. The resolution may be specified as a sequence of one or more modes, separated by commas (@samp{,}) or semicolons (@samp{;}); each will be tried @@ -2799,6 +3242,20 @@ If this variable is set, it names a font to use for text on the available font. +@node grub_cpu +@subsection grub_cpu + +In normal mode (@pxref{normal}), GRUB sets the @samp{grub_cpu} variable to +the CPU type for which GRUB was built (e.g. @samp{i386} or @samp{powerpc}). + + +@node grub_platform +@subsection grub_platform + +In normal mode (@pxref{normal}), GRUB sets the @samp{grub_platform} variable +to the platform for which GRUB was built (e.g. @samp{pc} or @samp{efi}). + + @node icondir @subsection icondir @@ -2854,50 +3311,74 @@ variable changes those colors. For the available color names, The default is the value of @samp{color_normal} (@pxref{color_normal}). -@node net_pxe_boot_file -@subsection net_pxe_boot_file +@node net_@var{}_boot_file +@subsection net_@var{}_boot_file @xref{Network}. -@node net_pxe_dhcp_server_name -@subsection net_pxe_dhcp_server_name +@node net_@var{}_dhcp_server_name +@subsection net_@var{}_dhcp_server_name @xref{Network}. -@node net_pxe_domain -@subsection net_pxe_domain +@node net_@var{}_domain +@subsection net_@var{}_domain @xref{Network}. -@node net_pxe_extensionspath -@subsection net_pxe_extensionspath +@node net_@var{}_extensionspath +@subsection net_@var{}_extensionspath @xref{Network}. -@node net_pxe_hostname -@subsection net_pxe_hostname +@node net_@var{}_hostname +@subsection net_@var{}_hostname @xref{Network}. -@node net_pxe_ip -@subsection net_pxe_ip +@node net_@var{}_ip +@subsection net_@var{}_ip @xref{Network}. -@node net_pxe_mac -@subsection net_pxe_mac +@node net_@var{}_mac +@subsection net_@var{}_mac @xref{Network}. -@node net_pxe_rootpath -@subsection net_pxe_rootpath +@node net_@var{}_rootpath +@subsection net_@var{}_rootpath + +@xref{Network}. + + +@node net_default_interface +@subsection net_default_interface + +@xref{Network}. + + +@node net_default_ip +@subsection net_default_ip + +@xref{Network}. + + +@node net_default_mac +@subsection net_default_mac + +@xref{Network}. + + +@node net_default_server +@subsection net_default_server @xref{Network}. @@ -3026,6 +3507,7 @@ shell}. * Menu-specific commands:: * General commands:: * Command-line and menu entry commands:: +* Networking commands:: @end menu @@ -3063,13 +3545,13 @@ These commands can only be used in the menu: @deffn Command menuentry @var{title} @ [@option{--class=class} @dots{}] [@option{--users=users}] @ - [@option{--unrestricted}] [@option{--hotkey=key}] @ - @{ @var{command}; @dots{} @} + [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @ + [@var{arg} @dots{}] @{ @var{command}; @dots{} @} This defines a GRUB menu entry named @var{title}. When this entry is selected from the menu, GRUB will set the @var{chosen} environment variable -to @var{title}, execute the list of commands given within braces, and if the -last command in the list returned successfully and a kernel was loaded it -will execute the @command{boot} command. +to value of @option{--id} if @option{--id} is given, execute the list of +commands given within braces, and if the last command in the list returned +successfully and a kernel was loaded it will execute the @command{boot} command. The @option{--class} option may be used any number of times to group menu entries into classes. Menu themes may display different classes using @@ -3084,6 +3566,13 @@ entries. @xref{Security}. The @option{--hotkey} option associates a hotkey with a menu entry. @var{key} may be a single letter, or one of the aliases @samp{backspace}, @samp{tab}, or @samp{delete}. + +The @option{--id} may be used to associate unique identifier with a menu entry. +@var{id} is string of ASCII aphanumeric characters, underscore and hyphen +and should not start with a digit. + +All other arguments including @var{title} are passed as positional parameters +when list of commands is executed with @var{title} always assigned to @code{$1}. @end deffn @@ -3092,7 +3581,7 @@ The @option{--hotkey} option associates a hotkey with a menu entry. @deffn Command submenu @var{title} @ [@option{--class=class} @dots{}] [@option{--users=users}] @ - [@option{--unrestricted}] [@option{--hotkey=key}] @ + [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @ @{ @var{menu entries} @dots{} @} This defines a submenu. An entry called @var{title} will be added to the menu; when that entry is selected, a new menu will be displayed showing all @@ -3209,24 +3698,37 @@ you forget a command, you can run the command @command{help} (@pxref{help}). @menu +* [:: Check file types and compare values * acpi:: Load ACPI tables +* authenticate:: Check whether user is in user list +* background_color:: Set background color for active terminal +* background_image:: Load background image for active terminal * badram:: Filter out bad regions of RAM * blocklist:: Print a block list * boot:: Start up your operating system * cat:: Show the contents of a file * chainloader:: Chain-load another boot loader +* clear:: Clear the screen +* cmosclean:: Clear bit in CMOS +* cmosdump:: Dump CMOS contents +* cmostest:: Test bit in CMOS * cmp:: Compare two files * configfile:: Load a configuration file * cpuid:: Check for CPU features -* crc:: Calculate CRC32 checksums +* crc:: Compute or check CRC32 checksums +* cryptomount:: Mount a crypto device * date:: Display or set current date and time +* devicetree:: Load a device tree blob +* distrust:: Remove a pubkey from trusted keys * drivemap:: Map a drive to another * echo:: Display a line of text +* eval:: Evaluate agruments as GRUB commands * export:: Export an environment variable * false:: Do nothing, unsuccessfully * gettext:: Translate a string * gptsync:: Fill an MBR based on GPT entries * halt:: Shut down your computer +* hashsum:: Compute or check hash checksum * help:: Show help messages * initrd:: Load a Linux initrd * initrd16:: Load a Linux initrd (16-bit mode) @@ -3235,28 +3737,56 @@ you forget a command, you can run the command @command{help} * linux:: Load a Linux kernel * linux16:: Load a Linux kernel (16-bit mode) * list_env:: List variables in environment block +* list_trusted:: List trusted public keys * load_env:: Load variables from environment block +* loadfont:: Load font files * loopback:: Make a device from a filesystem image * ls:: List devices or files +* lsfonts:: List loaded fonts +* lsmod:: Show loaded modules +* md5sum:: Compute or check MD5 hash +* module:: Load module for multiboot kernel +* multiboot:: Load multiboot compliant kernel +* nativedisk:: Switch to native disk drivers * normal:: Enter normal mode * normal_exit:: Exit from normal mode * parttool:: Modify partition table entries * password:: Set a clear-text password * password_pbkdf2:: Set a hashed password * play:: Play a tune +* probe:: Retrieve device info * pxe_unload:: Unload the PXE environment * read:: Read user input * reboot:: Reboot your computer +* regexp:: Test if regular expression matches string +* rmmod:: Remove a module * save_env:: Save variables to environment block * search:: Search devices by file, label, or UUID * sendkey:: Emulate keystrokes * set:: Set an environment variable +* sha1sum:: Compute or check SHA1 hash +* sha256sum:: Compute or check SHA256 hash +* sha512sum:: Compute or check SHA512 hash +* sleep:: Wait for a specified number of seconds +* source:: Read a configuration file in same context +* test:: Check file types and compare values * true:: Do nothing, successfully +* trust:: Add public key to list of trusted keys * unset:: Unset an environment variable * uppermem:: Set the upper memory size +@comment * vbeinfo:: List available video modes +* verify_detached:: Verify detached digital signature +* videoinfo:: List available video modes @end menu +@node [ +@subsection [ +@deffn Command @code{[} expression @code{]} +Alias for @code{test @var{expression}} (@pxref{test}). +@end deffn + + @node acpi @subsection acpi @@ -3278,6 +3808,42 @@ Normally, this command will replace the Root System Description Pointer GRUB, but may be used by GRUB's EFI emulation. @end deffn + +@node authenticate +@subsection authenticate +@deffn Command authenticate [userlist] +Check whether user is in @var{userlist} or listed in the value of variable +@samp{superusers}. See @pxref{superusers} for valid user list format. +If @samp{superusers} is empty, this command returns true. @xref{Security}. +@end deffn + + +@node background_color +@subsection background_color + +@deffn Command background_color color +Set background color for active terminal. For valid color specifications see +@pxref{Theme file format, ,Colors}. Background color can be changed only when +using @samp{gfxterm} for terminal output. + +This command sets color of empty areas without text. Text background color +is controlled by environment variables @var{color_normal}, @var{color_highlight}, +@var{menu_color_normal}, @var{menu_color_highlight}. @xref{Special environment variables}. +@end deffn + + +@node background_image +@subsection background_image + +@deffn Command background_image [[@option{--mode} @samp{stretch}|@samp{normal}] file] +Load background image for active terminal from @var{file}. Image is stretched +to fill up entire screen unless option @option{--mode} @samp{normal} is given. +Without arguments remove currently loaded background image. Background image +can be changed only when using @samp{gfxterm} for terminal output. + +@end deffn + + @node badram @subsection badram @@ -3350,6 +3916,42 @@ load a defective boot loader, such as SCO UnixWare 7.1. @end deffn +@node clear +@subsection clear + +@deffn Command clear +Clear the screen. +@end deffn + + +@node cmosclean +@subsection cmosclean + +@deffn Command cmosclean byte:bit +Clear value of bit in CMOS at location @var{byte}:@var{bit}. This command +is available only on platforms that support CMOS. +@end deffn + + +@node cmosdump +@subsection cmosdump + +@deffn Dump CMOS contents +Dump full CMOS contents as hexadecimal values. This command is available only +on platforms that support CMOS. +@end deffn + + +@node cmostest +@subsection cmostest + +@deffn Command cmostest byte:bit +Test value of bit in CMOS at location @var{byte}:@var{bit}. Exit status +is zero if bit is set, non zero otherwise. This command is available only +on platforms that support CMOS. +@end deffn + + @node cmp @subsection cmp @@ -3377,7 +3979,9 @@ If they are completely identical, nothing will be printed. @deffn Command configfile file Load @var{file} as a configuration file. If @var{file} defines any menu -entries, then show a menu containing them immediately. +entries, then show a menu containing them immediately. Any environment +variable changes made by the commands in @var{file} will not be preserved +after @command{configfile} returns. @end deffn @@ -3398,8 +4002,24 @@ invoked with @option{-l}. This may change in the future. @node crc @subsection crc -@deffn Command crc file -Display the CRC32 checksum of @var{file}. +@deffn Command crc arg @dots{} +Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node cryptomount +@subsection cryptomount + +@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b} +Setup access to encrypted device. If necessary, passphrase +is requested interactively. Option @var{device} configures specific grub device +(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device +with specified @var{uuid}; option @option{-a} configures all detected encrypted +devices; option @option{-b} configures all geli containers that have boot flag set. + +GRUB suports devices encrypted using LUKS and geli. Note that necessary modules (@var{luks} and @var{geli}) have to be loaded manually before this command can +be used. @end deffn @@ -3416,6 +4036,32 @@ hour, minute, and second unchanged. @end deffn +@node devicetree +@subsection linux + +@deffn Command devicetree file +Load a device tree blob (.dtb) from a filesystem, for later use by a Linux +kernel. Does not perform merging with any device tree supplied by firmware, +but rather replaces it completely. +@ref{GNU/Linux}. +@end deffn + +@node distrust +@subsection distrust + +@deffn Command distrust pubkey_id +Remove public key @var{pubkey_id} from GRUB's keyring of trusted keys. +@var{pubkey_id} is the last four bytes (eight hexadecimal digits) of +the GPG v4 key id, which is also the output of @command{list_trusted} +(@pxref{list_trusted}). Outside of GRUB, the key id can be obtained +using @code{gpg --fingerprint}). +These keys are used to validate signatures when environment variable +@code{check_signatures} is set to @code{enforce} +(@pxref{check_signatures}), and by some invocations of +@command{verify_detached} (@pxref{verify_detached}). @xref{Using +digital signatures}, for more information. +@end deffn + @node drivemap @subsection drivemap @@ -3485,6 +4131,15 @@ character will print that character. @end deffn +@node eval +@subsection eval + +@deffn Command eval string ... +Concatenate arguments together using single space as separator and evaluate +result as sequence of GRUB commands. +@end deffn + + @node export @subsection export @@ -3545,6 +4200,30 @@ is shut down using APM. @end deffn +@node hashsum +@subsection hashsum + +@deffn Command hashsum @option{--hash} hash @option{--keep-going} @option{--uncompress} @option{--check} file [@option{--prefix} dir]|file @dots{} +Compute or verify file hashes. Hash type is selected with option @option{--hash}. +Supported hashes are: @samp{adler32}, @samp{crc64}, @samp{crc32}, +@samp{crc32rfc1510}, @samp{crc24rfc2440}, @samp{md4}, @samp{md5}, +@samp{ripemd160}, @samp{sha1}, @samp{sha224}, @samp{sha256}, @samp{sha512}, +@samp{sha384}, @samp{tiger192}, @samp{tiger}, @samp{tiger2}, @samp{whirlpool}. +Option @option{--uncompress} uncompresses files before computing hash. + +When list of files is given, hash of each file is computed and printed, +followed by file name, each file on a new line. + +When option @option{--check} is given, it points to a file that contains +list of @var{hash name} pairs in the same format as used by UNIX +@command{md5sum} command. Option @option{--prefix} +may be used to give directory where files are located. Hash verification +stops after the first mismatch was found unless option @option{--keep-going} +was given. The exit code @code{$?} is set to 0 if hash verification +is successful. If it fails, @code{$?} is set to a nonzero value. +@end deffn + + @node help @subsection help @@ -3643,23 +4322,69 @@ This command is only available on x86 systems. @node list_env @subsection list_env -@deffn Command list_env [@option{-f} file] +@deffn Command list_env [@option{--file} file] List all variables in the environment block file. @xref{Environment block}. -The @option{-f} option overrides the default location of the environment -block. +The @option{--file} option overrides the default location of the +environment block. @end deffn +@node list_trusted +@subsection list_trusted + +@deffn Command list_trusted +List all public keys trusted by GRUB for validating signatures. +The output is in GPG's v4 key fingerprint format (i.e., the output of +@code{gpg --fingerprint}). The least significant four bytes (last +eight hexadecimal digits) can be used as an argument to +@command{distrust} (@pxref{distrust}). +@xref{Using digital signatures}, for more information about uses for +these keys. +@end deffn @node load_env @subsection load_env -@deffn Command load_env [@option{-f} file] +@deffn Command load_env [@option{--file} file] [@option{--skip-sig}] [whitelisted_variable_name] @dots{} Load all variables from the environment block file into the environment. @xref{Environment block}. -The @option{-f} option overrides the default location of the environment +The @option{--file} option overrides the default location of the environment block. + +The @option{--skip-sig} option skips signature checking even when the +value of environment variable @code{check_signatures} is set to +@code{enforce} (@pxref{check_signatures}). + +If one or more variable names are provided as arguments, they are +interpreted as a whitelist of variables to load from the environment +block file. Variables set in the file but not present in the +whitelist are ignored. + +The @option{--skip-sig} option should be used with care, and should +always be used in concert with a whitelist of acceptable variables +whose values should be set. Failure to employ a carefully constructed +whitelist could result in reading a malicious value into critical +environment variables from the file, such as setting +@code{check_signatures=no}, modifying @code{prefix} to boot from an +unexpected location or not at all, etc. + +When used with care, @option{--skip-sig} and the whitelist enable an +administrator to configure a system to boot only signed +configurations, but to allow the user to select from among multiple +configurations, and to enable ``one-shot'' boot attempts and +``savedefault'' behavior. @xref{Using digital signatures}, for more +information. +@end deffn + + +@node loadfont +@subsection loadfont + +@deffn Command loadfont file @dots{} +Load specified font files. Unless absolute pathname is given, @var{file} +is assumed to be in directory @samp{$prefix/fonts} with +suffix @samp{.pf2} appended. @xref{Theme file format,,Fonts}. @end deffn @@ -3696,6 +4421,69 @@ name syntax}), then list the contents of that directory. @end deffn +@node lsfonts +@subsection lsfonts + +@deffn Command lsfonts +List loaded fonts. +@end deffn + + +@node lsmod +@subsection lsmod + +@deffn Command lsmod +Show list of loaded modules. +@end deffn + +@node md5sum +@subsection md5sum + +@deffn Command md5sum arg @dots{} +Alias for @code{hashsum --hash md5 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + +@node module +@subsection module + +@deffn Command module [--nounzip] file [arguments] +Load a module for multiboot kernel image. The rest of the +line is passed verbatim as the module command line. +@end deffn + +@node multiboot +@subsection multiboot + +@deffn Command multiboot [--quirk-bad-kludge] [--quirk-modules-after-kernel] file @dots{} +Load a multiboot kernel image from @var{file}. The rest of the +line is passed verbatim as the @dfn{kernel command-line}. Any module must +be reloaded after using this command (@pxref{module}). + +Some kernels have known problems. You need to specify --quirk-* for those. +--quirk-bad-kludge is a problem seen in several products that they include +loading kludge information with invalid data in ELF file. GRUB prior to 0.97 +and some custom builds prefered ELF information while 0.97 and GRUB 2 +use kludge. Use this option to ignore kludge. +Known affected systems: old Solaris, SkyOS. + +--quirk-modules-after-kernel is needed for kernels which load at relatively +high address e.g. 16MiB mark and can't cope with modules stuffed between +1MiB mark and beginning of the kernel. +Known afftected systems: VMWare. +@end deffn + +@node nativedisk +@subsection nativedisk + +@deffn Command nativedisk +Switch from firmware disk drivers to native ones. +Really useful only on platforms where both +firmware and native disk drives are available. +Currently i386-pc, i386-efi, i386-ieee1275 and +x86_64-efi. +@end deffn + @node normal @subsection normal @@ -3781,7 +4569,7 @@ to generate password hashes. @xref{Security}. @node play @subsection play -@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] ... +@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] @dots{} Plays a tune If the argument is a file name (@pxref{File name syntax}), play the tune @@ -3797,6 +4585,15 @@ a rest. @end deffn +@node probe +@subsection probe + +@deffn Command probe [@option{--set} var] @option{--driver}|@option{--partmap}|@option{--fs}|@option{--fs-uuid}|@option{--label} device +Retrieve device information. If option @option{--set} is given, assign result +to variable @var{var}, otherwise print information on the screen. +@end deffn + + @node pxe_unload @subsection pxe_unload @@ -3825,15 +4622,45 @@ Reboot the computer. @end deffn +@node regexp +@subsection regexp + +@deffn Command regexp [@option{--set} [number:]var] regexp string +Test if regular expression @var{regexp} matches @var{string}. Supported +regular expressions are POSIX.2 Extended Regular Expressions. If option +@option{--set} is given, store @var{number}th matched subexpression in +variable @var{var}. Subexpressions are numbered in order of their opening +parentheses starting from @samp{1}. @var{number} defaults to @samp{1}. +@end deffn + + +@node rmmod +@subsection rmmod + +@deffn Command rmmod module +Remove a loaded @var{module}. +@end deffn + + @node save_env @subsection save_env -@deffn Command save_env [@option{-f} file] var @dots{} +@deffn Command save_env [@option{--file} file] var @dots{} Save the named variables from the environment to the environment block file. @xref{Environment block}. -The @option{-f} option overrides the default location of the environment +The @option{--file} option overrides the default location of the environment block. + +This command will operate successfully even when environment variable +@code{check_signatures} is set to @code{enforce} +(@pxref{check_signatures}), since it writes to disk and does not alter +the behavior of GRUB based on any contents of disk that have been +read. It is possible to modify a digitally signed environment block +file from within GRUB using this command, such that its signature will +no longer be valid on subsequent boots. Care should be taken in such +advanced configurations to avoid rendering the system +unbootable. @xref{Using digital signatures}, for more information. @end deffn @@ -4017,6 +4844,124 @@ arguments, print all environment variables with their values. @end deffn +@node sha1sum +@subsection sha1sum + +@deffn Command sha1sum arg @dots{} +Alias for @code{hashsum --hash sha1 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node sha256sum +@subsection sha256sum + +@deffn Command sha256sum arg @dots{} +Alias for @code{hashsum --hash sha256 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node sha512sum +@subsection sha512sum + +@deffn Command sha512sum arg @dots{} +Alias for @code{hashsum --hash sha512 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node sleep +@subsection sleep + +@deffn Command sleep [@option{--verbose}] [@option{--interruptible}] count +Sleep for @var{count} seconds. If option @option{--interruptible} is given, +allow @key{ESC} to interrupt sleep. With @option{--verbose} show countdown +of remaining seconds. +@end deffn + + +@node source +@subsection source + +@deffn Command source file +Read @var{file} as a configuration file, as if its contents had been +incorporated directly into the sourcing file. Unlike @command{configfile} +(@pxref{configfile}), this executes the contents of @var{file} without +changing context: any environment variable changes made by the commands in +@var{file} will be preserved after @command{source} returns, and the menu +will not be shown immediately. +@end deffn + + +@node test +@subsection test + +@deffn Command test expression +Evaluate @var{expression} and return zero exit status if result is true, +non zero status otherwise. + +@var{expression} is one of: + +@table @asis +@item @var{string1} @code{==} @var{string2} +the strings are equal +@item @var{string1} @code{!=} @var{string2} +the strings are not equal +@item @var{string1} @code{<} @var{string2} +@var{string1} is lexicographically less than @var{string2} +@item @var{string1} @code{<=} @var{string2} +@var{string1} is lexicographically less or equal than @var{string2} +@item @var{string1} @code{>} @var{string2} +@var{string1} is lexicographically greater than @var{string2} +@item @var{string1} @code{>=} @var{string2} +@var{string1} is lexicographically greater or equal than @var{string2} +@item @var{integer1} @code{-eq} @var{integer2} +@var{integer1} is equal to @var{integer2} +@item @var{integer1} @code{-ge} @var{integer2} +@var{integer1} is greater than or equal to @var{integer2} +@item @var{integer1} @code{-gt} @var{integer2} +@var{integer1} is greater than @var{integer2} +@item @var{integer1} @code{-le} @var{integer2} +@var{integer1} is less than or equal to @var{integer2} +@item @var{integer1} @code{-lt} @var{integer2} +@var{integer1} is less than @var{integer2} +@item @var{integer1} @code{-ne} @var{integer2} +@var{integer1} is not equal to @var{integer2} +@item @var{prefix}@var{integer1} @code{-pgt} @var{prefix}@var{integer2} +@var{integer1} is greater than @var{integer2} after stripping off common non-numeric @var{prefix}. +@item @var{prefix}@var{integer1} @code{-plt} @var{prefix}@var{integer2} +@var{integer1} is less than @var{integer2} after stripping off common non-numeric @var{prefix}. +@item @var{file1} @code{-nt} @var{file2} +@var{file1} is newer than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-nt} in which case it is added to the first file modification time. +@item @var{file1} @code{-ot} @var{file2} +@var{file1} is older than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-ot} in which case it is added to the first file modification time. +@item @code{-d} @var{file} +@var{file} exists and is a directory +@item @code{-e} @var{file} +@var{file} exists +@item @code{-f} @var{file} +@var{file} exists and is not a directory +@item @code{-s} @var{file} +@var{file} exists and has a size greater than zero +@item @code{-n} @var{string} +the length of @var{string} is nonzero +@item @var{string} +@var{string} is equivalent to @code{-n @var{string}} +@item @code{-z} @var{string} +the length of @var{string} is zero +@item @code{(} @var{expression} @code{)} +@var{expression} is true +@item @code{!} @var{expression} +@var{expression} is false +@item @var{expression1} @code{-a} @var{expression2} +both @var{expression1} and @var{expression2} are true +@item @var{expression1} @code{-o} @var{expression2} +either @var{expression1} or @var{expression2} is true +@end table +@end deffn + + @node true @subsection true @@ -4025,6 +4970,22 @@ Do nothing, successfully. This is mainly useful in control constructs such as @code{if} and @code{while} (@pxref{Shell-like scripting}). @end deffn +@node trust +@subsection trust + +@deffn Command trust [@option{--skip-sig}] pubkey_file +Read public key from @var{pubkey_file} and add it to GRUB's internal +list of trusted public keys. These keys are used to validate digital +signatures when environment variable @code{check_signatures} is set to +@code{enforce}. Note that if @code{check_signatures} is set to +@code{enforce} when @command{trust} executes, then @var{pubkey_file} +must itself be properly signed. The @option{--skip-sig} option can be +used to disable signature-checking when reading @var{pubkey_file} +itself. It is expected that @option{--skip-sig} is useful for testing +and manual booting. @xref{Using digital signatures}, for more +information. +@end deffn + @node unset @subsection unset @@ -4039,13 +5000,228 @@ Unset the environment variable @var{envvar}. This command is not yet implemented for GRUB 2, although it is planned. + +@ignore +@node vbeinfo +@subsection vbeinfo + +@deffn Command vbeinfo [[WxH]xD] +Alias for command @command{videoinfo} (@pxref{videoinfo}). It is available +only on PC BIOS platforms. +@end deffn +@end ignore + + +@node verify_detached +@subsection verify_detached + +@deffn Command verify_detached [@option{--skip-sig}] file signature_file [pubkey_file] +Verifies a GPG-style detached signature, where the signed file is +@var{file}, and the signature itself is in file @var{signature_file}. +Optionally, a specific public key to use can be specified using +@var{pubkey_file}. When environment variable @code{check_signatures} +is set to @code{enforce}, then @var{pubkey_file} must itself be +properly signed by an already-trusted key. An unsigned +@var{pubkey_file} can be loaded by specifying @option{--skip-sig}. +If @var{pubkey_file} is omitted, then public keys from GRUB's trusted keys +(@pxref{list_trusted}, @pxref{trust}, and @pxref{distrust}) are +tried. + +Exit code @code{$?} is set to 0 if the signature validates +successfully. If validation fails, it is set to a non-zero value. +@xref{Using digital signatures}, for more information. +@end deffn + +@node videoinfo +@subsection videoinfo + +@deffn Command videoinfo [[WxH]xD] +List available video modes. If resolution is given, show only matching modes. +@end deffn + +@node Networking commands +@section The list of networking commands + +@menu +* net_add_addr:: Add a network address +* net_add_dns:: Add a DNS server +* net_add_route:: Add routing entry +* net_bootp:: Perform a bootp autoconfiguration +* net_del_addr:: Remove IP address from interface +* net_del_dns:: Remove a DNS server +* net_del_route:: Remove a route entry +* net_get_dhcp_option:: Retrieve DHCP options +* net_ipv6_autoconf:: Perform IPv6 autoconfiguration +* net_ls_addr:: List interfaces +* net_ls_cards:: List network cards +* net_ls_dns:: List DNS servers +* net_ls_routes:: List routing entries +* net_nslookup:: Perform a DNS lookup +@end menu + + +@node net_add_addr +@subsection net_add_addr + +@deffn Command net_add_addr @var{interface} @var{card} @var{address} +Configure additional network @var{interface} with @var{address} on a +network @var{card}. @var{address} can be either IP in dotted decimal notation, +or symbolic name which is resolved using DNS lookup. If successful, this command +also adds local link routing entry to the default subnet of @var{address} +with name @var{interface}@samp{:local} via @var{interface}. +@end deffn + + +@node net_add_dns +@subsection net_add_dns + +@deffn Command net_add_dns @var{server} +Resolve @var{server} IP address and add to the list of DNS servers used during +name lookup. +@end deffn + + +@node net_add_route +@subsection net_add_route + +@deffn Command net_add_route @var{shortname} @var{ip}[/@var{prefix}] [@var{interface} | @samp{gw} @var{gateway}] +Add route to network with address @var{ip} as modified by @var{prefix} via +either local @var{interface} or @var{gateway}. @var{prefix} is optional and +defaults to 32 for IPv4 address and 128 for IPv6 address. Route is identified +by @var{shortname} which can be used to remove it (@pxref{net_del_route}). +@end deffn + + +@node net_bootp +@subsection net_bootp + +@deffn Command net_bootp [@var{card}] +Perform configuration of @var{card} using DHCP protocol. If no card name +is specified, try to configure all existing cards. If configuration was +successful, interface with name @var{card}@samp{:dhcp} and configured +address is added to @var{card}. If server provided gateway information in +DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. Additionally the following DHCP options are recognized and processed: + +@table @samp +@item 1 (Subnet Mask) +Used to calculate network local routing entry for interface @var{card}@samp{:dhcp}. +@item 3 (Router) +Adds default route entry with the name @var{card}@samp{:dhcp:default} via gateway +from DHCP option. Note that only option with single route is accepted. +@item 6 (Domain Name Server) +Adds all servers from option value to the list of servers used during name resolution. +@item 12 (Host Name) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_hostname} +(@pxref{net_@var{}_hostname}) to the value of option. +@item 15 (Domain Name) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_domain} +(@pxref{net_@var{}_domain}) to the value of option. +@item 17 (Root Path) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_rootpath} +(@pxref{net_@var{}_rootpath}) to the value of option. +@item 18 (Extensions Path) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_extensionspath} +(@pxref{net_@var{}_extensionspath}) to the value of option. +@end table + +@end deffn + + +@node net_del_addr +@subsection net_del_addr + +@deffn Command net_del_addr @var{interface} +Remove configured @var{interface} with associated address. +@end deffn + + +@node net_del_dns +@subsection net_del_dns + +@deffn Command net_del_dns @var{address} +Remove @var{address} from list of servers used during name lookup. +@end deffn + + +@node net_del_route +@subsection net_del_route + +@deffn Command net_del_route @var{shortname} +Remove route entry identified by @var{shortname}. +@end deffn + + +@node net_get_dhcp_option +@subsection net_get_dhcp_option + +@deffn Command net_get_dhcp_option @var{var} @var{interface} @var{number} @var{type} +Request DHCP option @var{number} of @var{type} via @var{interface}. @var{type} +can be one of @samp{string}, @samp{number} or @samp{hex}. If option is found, +assign its value to variable @var{var}. Values of types @samp{number} and @samp{hex} +are converted to string representation. +@end deffn + + +@node net_ipv6_autoconf +@subsection net_ipv6_autoconf + +@deffn Command net_ipv6_autoconf [@var{card}] +Perform IPv6 autoconfiguration by adding to the @var{card} interface with name +@var{card}@samp{:link} and link local MAC-based address. If no card is specified, +perform autoconfiguration for all existing cards. +@end deffn + + +@node net_ls_addr +@subsection net_ls_addr + +@deffn Command net_ls_addr +List all configured interfaces with their MAC and IP addresses. +@end deffn + + +@node net_ls_cards +@subsection net_ls_cards + +@deffn Command net_ls_cards +List all detected network cards with their MAC address. +@end deffn + + +@node net_ls_dns +@subsection net_ls_dns + +@deffn Command net_ls_dns +List addresses of DNS servers used during name lookup. +@end deffn + + +@node net_ls_routes +@subsection net_ls_routes + +@deffn Command net_ls_routes +List routing entries. +@end deffn + + +@node net_nslookup +@subsection net_nslookup + +@deffn Command net_nslookup @var{name} [@var{server}] +Resolve address of @var{name} using DNS server @var{server}. If no server +is given, use default list of servers. +@end deffn + + @node Internationalisation -@chapter Charset +@chapter Internationalisation + +@section Charset GRUB uses UTF-8 internally other than in rendering where some GRUB-specific appropriate representation is used. All text files (including config) are assumed to be encoded in UTF-8. -@chapter Filesystems +@section Filesystems NTFS, JFS, UDF, HFS+, exFAT, long filenames in FAT, Joliet part of ISO9660 are treated as UTF-16 as per specification. AFS and BFS are read as UTF-8, again according to specification. BtrFS, cpio, tar, squash4, minix, @@ -4079,32 +5255,41 @@ treated as distinct from u+combining diaresis. This however means that in order to access file on HFS+ its name must be specified in normalisation form D. On normalized ZFS subvolumes filenames out of normalisation are inaccessible. -@chapter Output terminal +@section Output terminal Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII. + BIOS firmware console and VGA text are limited to ASCII and some pseudographics. + None of above mentioned is appropriate for displaying international and any unsupported character is replaced with question mark except pseudographics -which we attempt to approximate with ASCII. EFI console on the other hand -nominally supports UTF-16 but actual language coverage depends on firmware and -may be very limited. The encoding used on serial can be chosen with -@command{terminfo} as either ASCII, UTF-8 or ``visual UTF-8''. Last one is -against the specification but results in correct rendering of right-to-left -on some readers which don't have own bidi implementation. When using gfxterm -or gfxmenu GRUB itself is responsible for rendering the text. In this case -GRUB is limited by loaded fonts. If fonts contain all required characters -then bidirectional text, cursive variants and combining marks other than -enclosing, half (e.g. left half tilde or combining overline) and double ones. -Ligatures aren't supported though. This should cover European, Middle Eastern -(if you don't mind lack of lam-alif ligature in Arabic) and East Asian scripts. -Notable unsupported scripts are Brahmic family and derived as well as -Mongolian, Tifinagh, Korean Jamo (precomposed characters have no problem) -and tonal writing (2e5-2e9). GRUB also ignores deprecated (as specified -in Unicode) characters (e.g. tags). GRUB also doesn't handle so called -``annotation characters'' If you can complete either of -two lists or, better, propose a patch to improve rendering, please contact -developper team. +which we attempt to approximate with ASCII. -@chapter Input terminal +EFI console on the other hand nominally supports UTF-16 but actual language +coverage depends on firmware and may be very limited. + +The encoding used on serial can be chosen with @command{terminfo} as +either ASCII, UTF-8 or ``visual UTF-8''. Last one is against the specification +but results in correct rendering of right-to-left on some readers which don't +have own bidi implementation. + +On emu GRUB checks if charset is UTF-8 and uses it if so and uses ASCII +otherwise. + +When using gfxterm or gfxmenu GRUB itself is responsible for rendering the +text. In this case GRUB is limited by loaded fonts. If fonts contain all +required characters then bidirectional text, cursive variants and combining +marks other than enclosing, half (e.g. left half tilde or combining overline) +and double ones. Ligatures aren't supported though. This should cover European, +Middle Eastern (if you don't mind lack of lam-alif ligature in Arabic) and +East Asian scripts. Notable unsupported scripts are Brahmic family and +derived as well as Mongolian, Tifinagh, Korean Jamo (precomposed characters +have no problem) and tonal writing (2e5-2e9). GRUB also ignores deprecated +(as specified in Unicode) characters (e.g. tags). GRUB also doesn't handle so +called ``annotation characters'' If you can complete either of +two lists or, better, propose a patch to improve rendering, please contact +developer team. + +@section Input terminal Firmware console on BIOS, IEEE1275 and ARC doesn't allow you to enter non-ASCII characters. EFI specification allows for such but author is unaware of any actual implementations. Serial input is currently limited for latin1 (unlikely @@ -4114,15 +5299,15 @@ So no dead keys or advanced input method. Also there is no keymap change hotkey. In practice it makes difficult to enter any text using non-Latin alphabet. Moreover all current input consumers are limited to ASCII. -@chapter Gettext +@section Gettext GRUB supports being translated. For this you need to have language *.mo files in $prefix/locale, load gettext module and set ``lang'' variable. -@chapter Regexp +@section Regexp Regexps work on unicode characters, however no attempt at checking cannonical equivalence has been made. Moreover the classes like [:alpha:] match only ASCII subset. -@chapter Other +@section Other Currently GRUB always uses YEAR-MONTH-DAY HOUR:MINUTE:SECOND [WEEKDAY] 24-hour datetime format but weekdays are translated. GRUB always uses the decimal number format with [0-9] as digits and . as @@ -4139,13 +5324,21 @@ Identifiers containing non-ASCII may work but aren't supported. Only the ASCII space characters (space U+0020, tab U+000b, CR U+000d and LF U+000a) are recognised. Other unicode space characters aren't a valid field separator. -@command{test} tests <, >, <=, >=, -pgt and -plt compare the strings in the +@command{test} (@pxref{test}) tests <, >, <=, >=, -pgt and -plt compare the strings in the lexicographical order of unicode codepoints, replicating the behaviour of test from coreutils. environment variables and commands are listed in the same order. @node Security -@chapter Authentication and authorisation +@chapter Security + +@menu +* Authentication and authorisation:: Users and access control +* Using digital signatures:: Booting digitally signed code +@end menu + +@node Authentication and authorisation +@section Authentication and authorisation in GRUB By default, the boot loader interface is accessible to anyone with physical access to the console: anyone can select and edit any menu entry, and anyone @@ -4212,6 +5405,95 @@ generating configuration files with authentication. You can use adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} commands. +@node Using digital signatures +@section Using digital signatures in GRUB + +GRUB's @file{core.img} can optionally provide enforcement that all files +subsequently read from disk are covered by a valid digital signature. +This document does @strong{not} cover how to ensure that your +platform's firmware (e.g., Coreboot) validates @file{core.img}. + +If environment variable @code{check_signatures} +(@pxref{check_signatures}) is set to @code{enforce}, then every +attempt by the GRUB @file{core.img} to load another file @file{foo} +implicitly invokes @code{verify_detached foo foo.sig} +(@pxref{verify_detached}). @code{foo.sig} must contain a valid +digital signature over the contents of @code{foo}, which can be +verified with a public key currently trusted by GRUB +(@pxref{list_trusted}, @pxref{trust}, and @pxref{distrust}). If +validation fails, then file @file{foo} cannot be opened. This failure +may halt or otherwise impact the boot process. + +@comment Unfortunately --pubkey is not yet supported by grub-install, +@comment but we should not bring up internal detail grub-mkimage here +@comment in the user guide (as opposed to developer's manual). + +@comment An initial trusted public key can be embedded within the GRUB +@comment @file{core.img} using the @code{--pubkey} option to +@comment @command{grub-mkimage} (@pxref{Invoking grub-install}). Presently it +@comment is necessary to write a custom wrapper around @command{grub-mkimage} +@comment using the @code{--grub-mkimage} flag to @command{grub-install}. + +GRUB uses GPG-style detached signatures (meaning that a file +@file{foo.sig} will be produced when file @file{foo} is signed), and +currently supports the DSA and RSA signing algorithms. A signing key +can be generated as follows: + +@example +gpg --gen-key +@end example + +An individual file can be signed as follows: + +@example +gpg --detach-sign /path/to/file +@end example + +For successful validation of all of GRUB's subcomponents and the +loaded OS kernel, they must all be signed. One way to accomplish this +is the following (after having already produced the desired +@file{grub.cfg} file, e.g., by running @command{grub-mkconfig} +(@pxref{Invoking grub-mkconfig}): + +@example +@group +# Edit /dev/shm/passphrase.txt to contain your signing key's passphrase +for i in `find /boot -name "*.cfg" -or -name "*.lst" -or \ + -name "*.mod" -or -name "vmlinuz*" -or -name "initrd*" -or \ + -name "grubenv"`; +do + gpg --batch --detach-sign --passphrase-fd 0 $i < \ + /dev/shm/passphrase.txt +done +shred /dev/shm/passphrase.txt +@end group +@end example + +See also: @ref{check_signatures}, @ref{verify_detached}, @ref{trust}, +@ref{list_trusted}, @ref{distrust}, @ref{load_env}, @ref{save_env}. + +Note that internally signature enforcement is controlled by setting +the environment variable @code{check_signatures} equal to +@code{enforce}. Passing one or more @code{--pubkey} options to +@command{grub-mkimage} implicitly defines @code{check_signatures} +equal to @code{enforce} in @file{core.img} prior to processing any +configuration files. + +Note that signature checking does @strong{not} prevent an attacker +with (serial, physical, ...) console access from dropping manually to +the GRUB console and executing: + +@example +set check_signatures=no +@end example + +To prevent this, password-protection (@pxref{Authentication and +authorisation}) is essential. Note that even with GRUB password +protection, GRUB itself cannot prevent someone with physical access to +the machine from altering that machine's firmware (e.g., Coreboot +or BIOS) configuration to cause the machine to boot from a different +(attacker-controlled) device. GRUB is at best only one link in a +secure boot chain. @node Platform limitations @chapter Platform limitations @@ -4224,8 +5506,7 @@ ARC platform is unable to change datetime (firmware doesn't seem to provide a function for it). EMU has similar limitation. -ARC platform no serial port is available. -EMU has similar limitation. +On EMU platform no serial port is available. Console charset refers only to firmware-assisted console. gfxterm is always Unicode (see Internationalisation section for its limitations). Serial is @@ -4242,9 +5523,6 @@ the actual console may be much more limited depending on firmware On BIOS network is supported only if the image is loaded through network. On sparc64 GRUB is unable to determine which server it was booted from. -On platforms not having direct serial support (as indicated in the line serial) -you can still redirect firmware console to serial if it allows so. - Direct ATA/AHCI support allows to circumvent various firmware limitations but isn't needed for normal operation except on baremetal ports. @@ -4252,6 +5530,8 @@ AT keyboard support allows keyboard layout remapping and support for keys not available through firmware. It isn't needed for normal operation except baremetal ports. +Speaker allows morse and spkmodem communication. + USB support provides benefits similar to ATA (for USB disks) or AT (for USB keyboards). In addition it allows USBserial. @@ -4273,6 +5553,7 @@ and mips-qemu_mips can use only memory up to first hole. @item network @tab yes (*) @tab no @tab no @tab no @item ATA/AHCI @tab yes @tab yes @tab yes @tab yes @item AT keyboard @tab yes @tab yes @tab yes @tab yes +@item Speaker @tab yes @tab yes @tab yes @tab yes @item USB @tab yes @tab yes @tab yes @tab yes @item chainloader @tab local @tab yes @tab yes @tab no @item cpuid @tab partial @tab partial @tab partial @tab partial @@ -4290,6 +5571,7 @@ and mips-qemu_mips can use only memory up to first hole. @item network @tab yes @tab yes @tab yes @tab yes @item ATA/AHCI @tab yes @tab yes @tab yes @tab no @item AT keyboard @tab yes @tab yes @tab yes @tab no +@item Speaker @tab yes @tab yes @tab yes @tab no @item USB @tab yes @tab yes @tab yes @tab no @item chainloader @tab local @tab local @tab no @tab local @item cpuid @tab partial @tab partial @tab partial @tab no @@ -4307,6 +5589,7 @@ and mips-qemu_mips can use only memory up to first hole. @item network @tab no @tab yes (*) @tab yes @tab no @item ATA/AHCI @tab yes @tab no @tab no @tab no @item AT keyboard @tab yes @tab no @tab no @tab no +@item Speaker @tab no @tab no @tab no @tab no @item USB @tab yes @tab no @tab no @tab no @item chainloader @tab yes @tab no @tab no @tab no @item cpuid @tab no @tab no @tab no @tab no @@ -4320,10 +5603,11 @@ and mips-qemu_mips can use only memory up to first hole. @multitable @columnfractions .20 .20 .20 .20 .20 @item @tab MIPS qemu @tab emu @item video @tab no @tab yes -@item console charset @tab CP437 @tab ASCII +@item console charset @tab CP437 @tab Unicode (*) @item network @tab no @tab yes @item ATA/AHCI @tab yes @tab no @item AT keyboard @tab yes @tab no +@item Speaker @tab no @tab no @item USB @tab N/A @tab yes @item chainloader @tab yes @tab no @item cpuid @tab no @tab no @@ -4347,14 +5631,15 @@ Information retrieval: @itemize @item mipsel-loongson: lsspd @item mips-arc: lsdev -@item efi: lsefisystab, lssal, lsefimmap +@item efi: lsefisystab, lssal, lsefimmap, lsefi @item i386-pc: lsapm +@item i386-coreboot: lscoreboot, coreboot_boottime, cbmemc @item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): lsacpi @end itemize Workarounds for platform-specific issues: @itemize -@item i386-efi/x86_64-efi: loadbios, fixvideo +@item i386-efi/x86_64-efi: loadbios, fakebios, fix_video @item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): acpi (override ACPI tables) @item i386-pc: drivemap @@ -4369,7 +5654,7 @@ Advanced operations for power users: Miscelaneous: @itemize @item cmos (x86-*, ieee1275, mips-qemu_mips, mips-loongson): cmostest - (used on some laptops to check for special power-on key) + (used on some laptops to check for special power-on key), cmosclean @item i386-pc: play @end itemize @@ -4384,10 +5669,10 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Plan9 @tab yes @tab no (1) @item Freedos @tab yes @tab no (1) @item FreeBSD bootloader @tab yes @tab crashes (1) -@item 32-bit kFreeBSD @tab yes @tab crashes (2,6) -@item 64-bit kFreeBSD @tab yes @tab crashes (2,6) +@item 32-bit kFreeBSD @tab yes @tab crashes (5) +@item 64-bit kFreeBSD @tab yes @tab crashes (5) @item 32-bit kNetBSD @tab yes @tab crashes (1) -@item 64-bit kNetBSD @tab yes @tab crashes (2) +@item 64-bit kNetBSD @tab yes @tab crashes @item 32-bit kOpenBSD @tab yes @tab yes @item 64-bit kOpenBSD @tab yes @tab yes @item Multiboot @tab yes @tab yes @@ -4398,9 +5683,9 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 64-bit Linux (modern protocol) @tab yes @tab yes @item 32-bit XNU @tab yes @tab ? @item 64-bit XNU @tab yes @tab ? -@item 32-bit EFI chainloader @tab no (3) @tab no (3) -@item 64-bit EFI chainloader @tab no (3) @tab no (3) -@item Appleloader @tab no (3) @tab no (3) +@item 32-bit EFI chainloader @tab no (2) @tab no (2) +@item 64-bit EFI chainloader @tab no (2) @tab no (2) +@item Appleloader @tab no (2) @tab no (2) @end multitable @multitable @columnfractions .50 .22 .22 @@ -4410,8 +5695,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Plan9 @tab no (1) @tab no (1) @item FreeDOS @tab no (1) @tab no (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1) -@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) -@item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6) +@item 32-bit kFreeBSD @tab crashes (5) @tab crashes (5) +@item 64-bit kFreeBSD @tab crashes (5) @tab crashes (5) @item 32-bit kNetBSD @tab crashes (1) @tab crashes (1) @item 64-bit kNetBSD @tab yes @tab yes @item 32-bit kOpenBSD @tab yes @tab yes @@ -4424,9 +5709,9 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 64-bit Linux (modern protocol) @tab yes @tab yes @item 32-bit XNU @tab ? @tab ? @item 64-bit XNU @tab ? @tab ? -@item 32-bit EFI chainloader @tab no (3) @tab no (3) -@item 64-bit EFI chainloader @tab no (3) @tab no (3) -@item Appleloader @tab no (3) @tab no (3) +@item 32-bit EFI chainloader @tab no (2) @tab no (2) +@item 64-bit EFI chainloader @tab no (2) @tab no (2) +@item Appleloader @tab no (2) @tab no (2) @end multitable @multitable @columnfractions .50 .22 .22 @@ -4449,9 +5734,9 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 32-bit Linux (modern protocol) @tab yes @tab yes @item 64-bit Linux (modern protocol) @tab yes @tab yes @item 32-bit XNU @tab yes @tab yes -@item 64-bit XNU @tab yes (5) @tab yes -@item 32-bit EFI chainloader @tab yes @tab no (4) -@item 64-bit EFI chainloader @tab no (4) @tab yes +@item 64-bit XNU @tab yes (4) @tab yes +@item 32-bit EFI chainloader @tab yes @tab no (3) +@item 64-bit EFI chainloader @tab no (3) @tab yes @item Appleloader @tab yes @tab yes @end multitable @@ -4462,8 +5747,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Plan9 @tab no (1) @item FreeDOS @tab no (1) @item FreeBSD bootloader @tab crashes (1) -@item 32-bit kFreeBSD @tab crashes (6) -@item 64-bit kFreeBSD @tab crashes (6) +@item 32-bit kFreeBSD @tab crashes (5) +@item 64-bit kFreeBSD @tab crashes (5) @item 32-bit kNetBSD @tab crashes (1) @item 64-bit kNetBSD @tab ? @item 32-bit kOpenBSD @tab ? @@ -4476,14 +5761,13 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 64-bit Linux (modern protocol) @tab ? @item 32-bit XNU @tab ? @item 64-bit XNU @tab ? -@item 32-bit EFI chainloader @tab no (3) -@item 64-bit EFI chainloader @tab no (3) -@item Appleloader @tab no (3) +@item 32-bit EFI chainloader @tab no (2) +@item 64-bit EFI chainloader @tab no (2) +@item Appleloader @tab no (2) @end multitable @enumerate @item Requires BIOS -@item Crashes because the memory at 0x0-0x1000 isn't available @item EFI only @item 32-bit and 64-bit EFI have different structures and work in different CPU modes so it's not possible to chainload 32-bit bootloader on 64-bit platform and vice-versa @item Some modules may need to be disabled @@ -4493,7 +5777,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel PowerPC, IA64 and Sparc64 ports support only Linux. MIPS port supports Linux and multiboot2. -@chapter Boot tests +@section Boot tests As you have seen in previous chapter the support matrix is pretty big and some of the configurations are only rarely used. To ensure the quality bootchecks are available for all x86 targets except EFI chainloader, Appleloader and XNU. All x86 platforms have bootcheck facility except ieee1275. Multiboot, multiboot2, BIOS chainloader, ntldr and freebsd-bootloader boot targets are tested only with a fake kernel images. Only Linux is tested among the payloads using Linux protocols. @@ -4591,17 +5875,17 @@ Installing to the whole disk device is normally more robust. @item Check that GRUB actually knows how to read from the device and file system containing @file{/boot/grub}. It will not be able to read from encrypted -devices, nor from file systems for which support has not yet been added to -GRUB. +devices with unsupported encryption scheme, nor from file systems for which +support has not yet been added to GRUB. @end itemize @node Invoking grub-install @chapter Invoking grub-install -The program @command{grub-install} installs GRUB on your drive using -@command{grub-mkimage} and (on some platforms) @command{grub-setup}. You -must specify the device name on which you want to install GRUB, like this: +The program @command{grub-install} generates a GRUB core image using +@command{grub-mkimage} and installs it on your system. You must specify the +device name on which you want to install GRUB, like this: @example grub-install @var{install_device} @@ -4704,6 +5988,33 @@ Length of the salt. Defaults to 64. @end table +@node Invoking grub-mkrelpath +@chapter Invoking grub-mkrelpath + +The program @command{grub-mkrelpath} makes a file system path relative to +the root of its containing file system. For instance, if @file{/usr} is a +mount point, then: + +@example +$ @kbd{grub-mkrelpath /usr/share/grub/unicode.pf2} +@samp{/share/grub/unicode.pf2} +@end example + +This is mainly used internally by other GRUB utilities such as +@command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}), but may +occasionally also be useful for debugging. + +@command{grub-mkrelpath} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. +@end table + + @node Invoking grub-mkrescue @chapter Invoking grub-mkrescue @@ -4762,6 +6073,93 @@ built-in default. @end table +@node Invoking grub-mount +@chapter Invoking grub-mount + +The program @command{grub-mount} performs a read-only mount of any file +system or file system image that GRUB understands, using GRUB's file system +drivers via FUSE. (It is only available if FUSE development files were +present when GRUB was built.) This has a number of uses: + +@itemize @bullet +@item +It provides a convenient way to check how GRUB will view a file system at +boot time. You can use normal command-line tools to compare that view with +that of your operating system, making it easy to find bugs. + +@item +It offers true read-only mounts. Linux does not have these for journalling +file systems, because it will always attempt to replay the journal at mount +time; while you can temporarily mark the block device read-only to avoid +this, that causes the mount to fail. Since GRUB intentionally contains no +code for writing to file systems, it can easily provide a guaranteed +read-only mount mechanism. + +@item +It allows you to examine any file system that GRUB understands without +needing to load additional modules into your running kernel, which may be +useful in constrained environments such as installers. + +@item +Since it can examine file system images (contained in regular files) just as +easily as file systems on block devices, you can use it to inspect any file +system image that GRUB understands with only enough privileges to use FUSE, +even if nobody has yet written a FUSE module specifically for that file +system type. +@end itemize + +Using @command{grub-mount} is normally as simple as: + +@example +grub-mount /dev/sda1 /mnt +@end example + +@command{grub-mount} must be given one or more images and a mount point as +non-option arguments (if it is given more than one image, it will treat them +as a RAID set), and also accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item -C +@itemx --crypto +Mount encrypted devices, prompting for a passphrase if necessary. + +@item -d @var{string} +@itemx --debug=@var{string} +Show debugging output for conditions matching @var{string}. + +@item -K prompt|@var{file} +@itemx --zfs-key=prompt|@var{file} +Load a ZFS encryption key. If you use @samp{prompt} as the argument, +@command{grub-mount} will read a passphrase from the terminal; otherwise, it +will read key material from the specified file. + +@item -r @var{device} +@itemx --root=@var{device} +Set the GRUB root device to @var{device}. You do not normally need to set +this; @command{grub-mount} will automatically set the root device to the +root of the supplied file system. + +If @var{device} is just a number, then it will be treated as a partition +number within the supplied image. This means that, if you have an image of +an entire disk in @file{disk.img}, then you can use this command to mount +its second partition: + +@example +grub-mount -r 2 disk.img mount-point +@end example + +@item -v +@itemx --verbose +Print verbose messages. +@end table + + @node Invoking grub-probe @chapter Invoking grub-probe @@ -4848,6 +6246,33 @@ Print verbose messages. @end table +@node Invoking grub-script-check +@chapter Invoking grub-script-check + +The program @command{grub-script-check} takes a GRUB script file +(@pxref{Shell-like scripting}) and checks it for syntax errors, similar to +commands such as @command{sh -n}. It may take a @var{path} as a non-option +argument; if none is supplied, it will read from standard input. + +@example +grub-script-check /boot/grub/grub.cfg +@end example + +@command{grub-script-check} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item -v +@itemx --verbose +Print each line of input after reading it. +@end table + + @node Obtaining and Building GRUB @appendix How to obtain and build GRUB @@ -4886,7 +6311,7 @@ just do: @end example Also, the latest version is available using Bazaar. See -@uref{http://www.gnu.org/software/grub/grub-download.en.html} for more +@uref{http://www.gnu.org/software/grub/grub-download.html} for more information. @node Reporting bugs diff --git a/docs/man/grub-bios-setup.h2m b/docs/man/grub-bios-setup.h2m index eebe3ef38..ac6ede362 100644 --- a/docs/man/grub-bios-setup.h2m +++ b/docs/man/grub-bios-setup.h2m @@ -1,5 +1,5 @@ [NAME] -grub-setup \- set up a device to boot using GRUB +grub-bios-setup \- set up a device to boot using GRUB [SEE ALSO] .BR grub-install (8), .BR grub-mkimage (1), diff --git a/docs/man/grub-glue-efi.h2m b/docs/man/grub-glue-efi.h2m new file mode 100644 index 000000000..c1c6ded49 --- /dev/null +++ b/docs/man/grub-glue-efi.h2m @@ -0,0 +1,4 @@ +[NAME] +grub-glue-efi \- generate a fat binary for EFI +[DESCRIPTION] +grub-glue-efi processes ia32 and amd64 EFI images and glues them according to Apple format. diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m index 2de371a3f..8cbbc87a0 100644 --- a/docs/man/grub-install.h2m +++ b/docs/man/grub-install.h2m @@ -3,5 +3,4 @@ grub-install \- install GRUB to a device [SEE ALSO] .BR grub-mkconfig (8), .BR grub-mkimage (1), -.BR grub-setup (8), .BR grub-mkrescue (1) diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m deleted file mode 100644 index 3ef8e9712..000000000 --- a/docs/man/grub-mkdevicemap.h2m +++ /dev/null @@ -1,4 +0,0 @@ -[NAME] -grub-mkdevicemap \- generate a GRUB device map file automatically -[SEE ALSO] -.BR grub-install (8) diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m index ca08b0c5c..f0fbc2bb1 100644 --- a/docs/man/grub-mkimage.h2m +++ b/docs/man/grub-mkimage.h2m @@ -2,6 +2,5 @@ grub-mkimage \- make a bootable image of GRUB [SEE ALSO] .BR grub-install (8), -.BR grub-setup (8), .BR grub-mkrescue (1), .BR grub-mknetdir (8) diff --git a/docs/man/grub-render-label.h2m b/docs/man/grub-render-label.h2m new file mode 100644 index 000000000..50ae5247c --- /dev/null +++ b/docs/man/grub-render-label.h2m @@ -0,0 +1,3 @@ +[NAME] +grub-render-label \- generate a .disk_label for Apple Macs. + diff --git a/docs/man/grub-sparc64-setup.h2m b/docs/man/grub-sparc64-setup.h2m index eebe3ef38..18f803a50 100644 --- a/docs/man/grub-sparc64-setup.h2m +++ b/docs/man/grub-sparc64-setup.h2m @@ -1,5 +1,5 @@ [NAME] -grub-setup \- set up a device to boot using GRUB +grub-sparc64-setup \- set up a device to boot using GRUB [SEE ALSO] .BR grub-install (8), .BR grub-mkimage (1), diff --git a/docs/osdetect.cfg b/docs/osdetect.cfg new file mode 100644 index 000000000..b759c71fd --- /dev/null +++ b/docs/osdetect.cfg @@ -0,0 +1,325 @@ +# Sample GRUB script to autodetect operating systems +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +set saved_root=$root + +function freebsd_ufs_variants { + set device=$1 + set fstype=$2 + set uuid=$3 + + menuentry "FreeBSD (on $fstype $device)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (single)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --single + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (verbose)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --verbose + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (without ACPI)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (safe mode)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + set FreeBSD.hint.apic.0.disabled=1 + set FreeBSD.hw.ata.ata_dma=0 + set FreeBSD.hw.ata.atapi_dma=0 + set FreeBSD.hw.ata.wc=0 + set FreeBSD.hw.eisa_slots=0 + set FreeBSD.hint.kbdmux.0.disabled=1 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } +} + +function freebsd_zfs_variants { + set device=$1 + set fstype=zfs + + menuentry "FreeBSD (on $fstype $device)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (single)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --single + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (verbose)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --verbose + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (without ACPI)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (safe mode)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + set FreeBSD.hint.apic.0.disabled=1 + set FreeBSD.hw.ata.ata_dma=0 + set FreeBSD.hw.ata.atapi_dma=0 + set FreeBSD.hw.ata.wc=0 + set FreeBSD.hw.eisa_slots=0 + set FreeBSD.hint.kbdmux.0.disabled=1 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } +} + +insmod regexp +for dev in (*); do + # $device: parenthesis removed from $dev + regexp -s device '\((.*)\)' $dev + # $fstype: filesystem type identified + probe -s fstype -f $dev + # uuid: filesystem UUID + probe -s uuid -u $dev + + if test -f ($device)/bootmgr -a -f ($device)/boot/bcd; then + menuentry "Windows Vista bootmgr (on $device)" $device { + set root=$2 + chainloader +1 + } + elif test -f ($device)/ntldr -a \ + -e ($device)/ntdetect.com -a -f ($device)/boot.ini; then + menuentry "Windows NT/2000/XP loader (on $device)" $device { + set root=$2 + regexp -s devnum 'hd([0-9]+)' $root + if test "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test -f ($device)/windows/win.com; then + menuentry "Windows 98/ME (on $device)" $device { + set root=$2 + regexp -s devnum 'hd([0-9]+)' $root + if test "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test -f ($device)/io.sys -a -f ($device)/command.com; then + menuentry "MS-DOS (on $device)" $device { + set root=$2 + regexp -s devnum 'hd([0-9]+)' $root + if test "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test -f ($device)/kernel.sys; then + menuentry "FreeDOS (on $device)" $device { + set root=$2 + regexp -s type '([fh])d[0-9]+' $root + regexp -s devnum '[fh]d([0-9]+)' $root + if test $type = 'h' -a "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test "$fstype" = ufs1 -o "$fstype" = ufs2 -a \ + -e ($device)/boot/kernel/kernel -a \ + -e ($device)/boot/device.hints; then + + freebsd_ufs_variants $device $fstype $uuid + + elif test "$fstype" = zfs -a \ + -e ($device)/@/boot/kernel/kernel -a \ + -e ($device)/@/boot/device.hints; then + + freebsd_zfs_variants $device + + elif test "$fstype" = hfsplus -a -f ($device)/mach_kernel; then + menuentry "Mac OS X/Darwin" $device $uuid { + set root=$2 + set uuid=$3 + + insmod vbe + do_resume=0 + if [ /var/vm/sleepimage -nt10 / ]; then + if xnu_resume /var/vm/sleepimage; then + do_resume=1 + fi + fi + if [ $do_resume = 1 ]; then + xnu_uuid $uuid uuid + if [ -f /Extra/DSDT.aml ]; then + acpi -e /Extra/DSDT.aml + fi + xnu_kernel /mach_kernel boot-uuid=${uuid} rd=*uuid + if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then + xnu_mkext /System/Library/Extensions.mkext + else + xnu_mkext /System/Library/Extensions + fi + if [ -f /Extra/Extensions.mkext ]; then + xnu_mkext /Extra/Extensions.mkext + fi + if [ -d /Extra/Extensions ]; then + xnu_kextdir /Extra/Extensions + fi + if [ -f /Extra/devtree.txt ]; then + xnu_devtree /Extra/devtree.txt + fi + if [ -f /Extra/splash.jpg ]; then + insmod jpeg + xnu_splash /Extra/splash.jpg + fi + if [ -f /Extra/splash.png ]; then + insmod png + xnu_splash /Extra/splash.png + fi + if [ -f /Extra/splash.tga ]; then + insmod tga + xnu_splash /Extra/splash.tga + fi + fi + } + else + set root=$device + for file in /boot/vmlinuz-* /boot/linux-*; do + if test -f $file; then + regexp -s version '/boot/vmlinuz-(.*)' $file + regexp -s version '/boot/linux-(.*)' $file + + menuentry "Linux $file" $device $uuid $file $version { + set root=$2 + set uuid=$3 + set kernel=$4 + set version=$5 + + linux $kernel root=UUID=$uuid ro + if test -f /boot/initrd-$version.img; then + initrd /boot/initrd-$version.img + elif test -f /boot/initrd.img-$version; then + initrd /boot/initrd.img-$version + elif test -f /boot/initrd-$version; then + initrd /boot/initrd-$version + fi + } + + menuentry "Linux $file (single)" $device $uuid $file $version { + set root=$2 + set uuid=$3 + set kernel=$4 + set version=$5 + + linux $kernel root=UUID=$uuid ro single + if test -f /boot/initrd-$version.img; then + initrd /boot/initrd-$version.img + elif test -f /boot/initrd.img-$version; then + initrd /boot/initrd.img-$version + elif test -f /boot/initrd-$version; then + initrd /boot/initrd-$version + fi + } + fi + done + fi +done + +set root=$saved_root diff --git a/gentpl.py b/gentpl.py index 13a60816f..825739dd3 100644 --- a/gentpl.py +++ b/gentpl.py @@ -21,9 +21,10 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275", "x86_64_efi", + "i386_xen", "x86_64_xen", "mips_loongson", "sparc64_ieee1275", "powerpc_ieee1275", "mips_arc", "ia64_efi", - "mips_qemu_mips" ] + "mips_qemu_mips", "arm_uboot", "arm_efi" ] GROUPS = {} @@ -36,10 +37,13 @@ GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ] +GROUPS["arm"] = [ "arm_uboot", "arm_efi" ] # Groups based on firmware -GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi" ] +GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi" ] GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] +GROUPS["uboot"] = [ "arm_uboot" ] +GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] # emu is a special case so many core functionality isn't needed on this platform GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") @@ -47,20 +51,23 @@ GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips", "sparc64_ieee1275", "powerpc_ieee1275"] -GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi"); GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel -GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"] +GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ] GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) # Similar for terminfo -GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"]; +GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["xen"] + GROUPS["ieee1275"] + GROUPS["uboot"]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) +# Flattened Device Trees (FDT) +GROUPS["fdt"] = [ "arm_uboot", "arm_efi" ] + # Miscelaneous groups schedulded to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") @@ -302,13 +309,8 @@ def define_macro_for_platform_nodist_sources(p): return define_autogen_macro( "get_" + p + "_nodist_sources", platform_values(p, "_nodist")) -def define_macro_for_platform_dependencies(p): - return define_autogen_macro( - "get_" + p + "_dependencies", - platform_values(p, "dependencies", "_dependencies")) def platform_sources(p): return "[+ get_" + p + "_sources +]" def platform_nodist_sources(p): return "[+ get_" + p + "_nodist_sources +]" -def platform_dependencies(p): return "[+ get_" + p + "_dependencies +]" # # Returns Autogen code which defines the autogen macros that collect @@ -326,6 +328,10 @@ def define_macro_for_platform_ldadd(p): return define_autogen_macro( "get_" + p + "_ldadd", platform_specific_values(p, "_ldadd", "ldadd")) +def define_macro_for_platform_dependencies(p): + return define_autogen_macro( + "get_" + p + "_dependencies", + platform_specific_values(p, "_dependencies", "dependencies")) def define_macro_for_platform_ldflags(p): return define_autogen_macro( "get_" + p + "_ldflags", @@ -351,6 +357,7 @@ def define_macro_for_platform_objcopyflags(p): # def platform_startup(p): return "[+ get_" + p + "_startup +]" def platform_ldadd(p): return "[+ get_" + p + "_ldadd +]" +def platform_dependencies(p): return "[+ get_" + p + "_dependencies +]" def platform_cflags(p): return "[+ get_" + p + "_cflags +]" def platform_ldflags(p): return "[+ get_" + p + "_ldflags +]" def platform_cppflags(p): return "[+ get_" + p + "_cppflags +]" @@ -380,9 +387,9 @@ def module(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 += var_set(cname() + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(platform)) - r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("dist_noinst_DATA", extra_dist()) r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") @@ -408,9 +415,9 @@ def kernel(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 += var_set(cname() + "_DEPENDENCIES", "$(TARGET_OBJ2ELF)") - r += gvar_add("EXTRA_DIST", extra_dist()) + r += gvar_add("dist_noinst_DATA", extra_dist()) r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") @@ -419,14 +426,14 @@ def kernel(platform): r += rule("[+ name +].img", "[+ name +].exec$(EXEEXT)", if_platform_tagged(platform, "nostrip", """if test x$(USE_APPLE_CC_FIXES) = xyes; then \ - $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \ + $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \ elif test ! -z '$(TARGET_OBJ2ELF)'; then \ cp $< $@.bin; $(TARGET_OBJ2ELF) $@.bin && cp $@.bin $@ || (rm -f $@.bin; exit 1); \ else cp $< $@; fi""", """if test x$(USE_APPLE_CC_FIXES) = xyes; then \ - $(STRIP) $(""" + cname() + """) -o $@.bin $<; \ - $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $@.bin $@; \ -else """ + "$(STRIP) $(" + cname() + "_STRIPFLAGS) -o $@ $<; \ + $(TARGET_STRIP) $(""" + cname() + """) -o $@.bin $<; \ + $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $@.bin $@; \ +else """ + "$(TARGET_STRIP) $(" + cname() + "_STRIPFLAGS) -o $@ $<; \ fi""")) return r @@ -443,7 +450,7 @@ def image(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("dist_noinst_DATA", extra_dist()) r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") @@ -453,7 +460,7 @@ def image(platform): 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 -R .note.gnu.gold-version $< $@; \ + $(TARGET_OBJCOPY) $(""" + cname() + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ fi """) return r @@ -476,7 +483,7 @@ def library(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 += gvar_add("dist_noinst_DATA", extra_dist()) r += first_time(gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)")) r += first_time(gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)")) return r @@ -484,10 +491,10 @@ def library(platform): def installdir(default="bin"): return "[+ IF installdir +][+ installdir +][+ ELSE +]" + default + "[+ ENDIF +]" -def manpage(): +def manpage(adddeps): r = "if COND_MAN_PAGES\n" r += gvar_add("man_MANS", "[+ name +].[+ mansection +]\n") - r += rule("[+ name +].[+ mansection +]", "[+ name +]", """ + r += rule("[+ name +].[+ mansection +]", "[+ name +] " + adddeps, """ chmod a+x [+ name +] PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +] """) @@ -503,7 +510,7 @@ def program(platform, test=False): r += gvar_add("TESTS", "[+ name +]") r += "[+ ELSE +]" r += var_add(installdir() + "_PROGRAMS", "[+ name +]") - r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" + r += "[+ IF mansection +]" + manpage("") + "[+ ENDIF +]" r += "[+ ENDIF +]" r += var_set(cname() + "_SOURCES", platform_sources(platform)) @@ -515,15 +522,14 @@ def program(platform, test=False): 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("dist_noinst_DATA", 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)) + r = var_add("dist_" + installdir() + "_DATA", platform_sources(platform)) + r += gvar_add("dist_noinst_DATA", extra_dist()) return r def script(platform): @@ -532,15 +538,16 @@ def script(platform): r += gvar_add ("TESTS", "[+ name +]") r += "[+ ELSE +]" r += var_add(installdir() + "_SCRIPTS", "[+ name +]") - r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" + r += "[+ IF mansection +]" + manpage("grub-mkconfig_lib") + "[+ ENDIF +]" r += "[+ ENDIF +]" - r += rule("[+ name +]", platform_sources(platform) + " $(top_builddir)/config.status", """ -$(top_builddir)/config.status --file=$@:$< + r += rule("[+ name +]", "$(top_builddir)/config.status " + platform_sources(platform), """ +(skip=1; for x in $^; do if [ $$skip = 1 ]; then skip=0; else cat "$$x"; fi; done) | $(top_builddir)/config.status --file=$@:- chmod a+x [+ name +] """) r += gvar_add("CLEANFILES", "[+ name +]") + r += gvar_add("EXTRA_DIST", extra_dist()) r += gvar_add("dist_noinst_DATA", platform_sources(platform)) return r @@ -595,11 +602,11 @@ print ("[+ AutoGen5 template +]\n") for p in GRUB_PLATFORMS: print (define_macro_for_platform_sources(p)) print (define_macro_for_platform_nodist_sources(p)) - # print define_macro_for_platform_dependencies(p) print (define_macro_for_platform_startup(p)) print (define_macro_for_platform_cflags(p)) print (define_macro_for_platform_ldadd(p)) + print (define_macro_for_platform_dependencies(p)) print (define_macro_for_platform_ldflags(p)) print (define_macro_for_platform_cppflags(p)) print (define_macro_for_platform_ccasflags(p)) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 7dc25197c..e081559f8 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -7,11 +7,11 @@ include $(top_srcdir)/conf/Makefile.common CC=$(TARGET_CC) CPP=$(TARGET_CC) CCAS=$(TARGET_CC) +RANLIB=$(TARGET_RANLIB) +STRIP=$(TARGET_STRIP) -if COND_GRUB_MKFONT if COND_HAVE_FONT_SOURCE -TARGET_CFLAGS += -DUSE_ASCII_FAILBACK=1 -DHAVE_UNIFONT_WIDTHSPEC=1 -endif +TARGET_CFLAGS += -DUSE_ASCII_FALLBACK=1 -DHAVE_UNIFONT_WIDTHSPEC=1 endif MACHO2IMG=$(top_builddir)/grub-macho2img @@ -30,25 +30,19 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM) CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM) +build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^ + # gentrigtables gentrigtables: gentrigtables.c - $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) $< -lm + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< $(BUILD_LIBM) CLEANFILES += gentrigtables # trigtables.c trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac - $(builddir)/gentrigtables > $@ + ./gentrigtables > $@ CLEANFILES += trigtables.c -gensm712: video/sm712.c - $(BUILD_CC) -DGENINIT -o $@ -I$(top_builddir) -I$(top_builddir)/include -I$(top_srcdir)/include $(CPPFLAGS) $< -CLEANFILES += gensm712 - -# trigtables.c -sm712_start.S: gensm712 video/sm712.c $(top_srcdir)/configure.ac - $(builddir)/gensm712 > $@ -CLEANFILES += sm712_start.S - # XXX Use Automake's LEX & YACC support grub_script.tab.h: script/parser.y $(YACC) -d -p grub_script_yy -b grub_script $< @@ -60,12 +54,9 @@ grub_script.yy.h: script/yylex.l $(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $< grub_script.yy.c: grub_script.yy.h -rs_decoder.S: $(srcdir)/lib/reed_solomon.c +rs_decoder.h: $(srcdir)/lib/reed_solomon.c $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding -kern/i386/pc/startup.S: $(builddir)/rs_decoder.S -boot/mips/loongson/fwstart.S: $(builddir)/sm712_start.S - CLEANFILES += grub_script.yy.c grub_script.yy.h include $(srcdir)/Makefile.core.am @@ -91,36 +82,44 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h +if !COND_clang KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h +endif KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h endif if COND_i386_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h endif if COND_i386_coreboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/coreboot/lbio.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h endif if COND_i386_multiboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_qemu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h endif if COND_i386_ieee1275 @@ -128,13 +127,31 @@ 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 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +endif + +if COND_i386_xen +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +endif + +if COND_x86_64_xen +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/x86_64/xen/hypercall.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h endif if COND_x86_64_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h endif @@ -150,18 +167,13 @@ endif if COND_mips_arc KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h endif if COND_mips_qemu_mips KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h @@ -174,11 +186,10 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/time.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h @@ -210,10 +221,26 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h endif +if COND_arm_uboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +endif + +if COND_arm_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +endif + if COND_emu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h if COND_GRUB_EMU_SDL KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h endif @@ -264,11 +291,11 @@ 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) > $@ + rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@ CLEANFILES += grub_emu_init.h grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES) - rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(NM) > $@ + rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@ CLEANFILES += grub_emu_init.c endif @@ -349,7 +376,7 @@ syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES) # generate global module dependencies list moddep.lst: syminfo.lst genmoddep.awk video.lst - cat $< | sort | awk -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) + cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) platform_DATA += moddep.lst CLEANFILES += config.log syminfo.lst moddep.lst @@ -363,27 +390,27 @@ 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; \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -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; \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -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; \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -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; \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -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; \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -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; \ + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -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) @@ -394,7 +421,7 @@ efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF) $(OBJCONV) -felf64 -nu -nd $@.bin $@ || exit 1; \ rm -f $@.bin; \ else \ - $(TARGET_CC) -m64 -nostdlib -Wl,-r -o $@ $^ || exit 1; \ + $(TARGET_CC) -m64 -Wl,-melf_x86_64 -nostdlib -Wl,-r -o $@ $^ || exit 1; \ if test ! -z "$(TARGET_OBJ2ELF)"; then $(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi; \ fi diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 74930a341..164c19b18 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -30,6 +30,20 @@ script = { common = gdb_grub.in; }; +script = { + installdir = platform; + name = grub.chrp; + common = boot/powerpc/grub.chrp.in; + enable = powerpc_ieee1275; +}; + +script = { + installdir = platform; + name = bootinfo.txt; + common = boot/powerpc/bootinfo.txt.in; + enable = powerpc_ieee1275; +}; + kernel = { name = kernel; @@ -45,6 +59,14 @@ kernel = { ia64_efi_ldflags = '-Wl,-r,-d'; ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + x86_64_xen_ldflags = '-Wl,-Ttext=0'; + x86_64_xen_cppflags = '$(CPPFLAGS_XEN)'; + i386_xen_ldflags = '-Wl,-Ttext=0'; + i386_xen_cppflags = '$(CPPFLAGS_XEN)'; + + arm_efi_ldflags = '-Wl,-r,-d'; + arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; @@ -59,17 +81,22 @@ kernel = { mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; - mips_arc_ldflags = '-Wl,-Ttext,0x8bd00000'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; - mips_loongson_cppflags = '-DUSE_ASCII_FAILBACK'; + mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + mips_loongson_cppflags = '-DUSE_ASCII_FALLBACK'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; + arm_uboot_ldflags = '-Wl,-Ttext=0x08000000'; + arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; i386_pc_startup = kern/i386/pc/startup.S; i386_efi_startup = kern/i386/efi/startup.S; x86_64_efi_startup = kern/x86_64/efi/startup.S; + i386_xen_startup = kern/i386/xen/startup.S; + x86_64_xen_startup = kern/x86_64/xen/startup.S; i386_qemu_startup = kern/i386/qemu/startup.S; i386_ieee1275_startup = kern/i386/ieee1275/startup.S; i386_coreboot_startup = kern/i386/coreboot/startup.S; @@ -77,6 +104,8 @@ kernel = { mips_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; + arm_uboot_startup = kern/arm/uboot/startup.S; + arm_efi_startup = kern/arm/efi/startup.S; common = kern/command.c; common = kern/corecmd.c; @@ -102,7 +131,6 @@ kernel = { noemu_nodist = symlist.c; - i386_pc = kern/generic/rtc_get_time_ms.c; mips = kern/generic/rtc_get_time_ms.c; ieee1275 = disk/ieee1275/ofdisk.c; @@ -113,20 +141,25 @@ kernel = { ieee1275 = term/ieee1275/console.c; ieee1275 = kern/ieee1275/init.c; + uboot = disk/uboot/ubootdisk.c; + uboot = kern/uboot/uboot.c; + uboot = kern/uboot/init.c; + uboot = kern/uboot/hw.c; + uboot = term/uboot/console.c; + terminfoinkernel = term/terminfo.c; terminfoinkernel = term/tparm.c; terminfoinkernel = commands/extcmd.c; terminfoinkernel = lib/arg.c; i386 = kern/i386/dl.c; + i386_xen = kern/i386/dl.c; - i386_coreboot_multiboot_qemu = kern/i386/coreboot/init.c; + i386_coreboot = kern/i386/coreboot/init.c; + i386_multiboot = kern/i386/coreboot/init.c; + i386_qemu = kern/i386/qemu/init.c; i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; - - i386_coreboot_multiboot_qemu = term/i386/vga_common.c; - i386_pc = term/i386/vga_common.c; - - x86 = kern/i386/pit.c; + i386_coreboot = video/i386/coreboot/cbfb.c; efi = disk/efi/efidisk.c; efi = kern/efi/efi.c; @@ -134,36 +167,45 @@ kernel = { efi = kern/efi/mm.c; efi = term/efi/console.c; - i386_efi = kern/i386/tsc.c; + x86 = kern/i386/tsc.c; + i386_efi = kern/i386/efi/init.c; i386_efi = bus/pci.c; - x86_64_efi = kern/i386/tsc.c; - x86_64_efi = kern/x86_64/dl.c; + x86_64 = kern/x86_64/dl.c; + x86_64_xen = kern/x86_64/dl.c; x86_64_efi = kern/x86_64/efi/callwrap.S; x86_64_efi = kern/i386/efi/init.c; x86_64_efi = bus/pci.c; + xen = kern/i386/tsc.c; + x86_64_xen = kern/x86_64/xen/hypercall.S; + i386_xen = kern/i386/xen/hypercall.S; + xen = kern/xen/init.c; + xen = term/xen/console.c; + xen = disk/xen/xendisk.c; + xen = commands/boot.c; + ia64_efi = kern/ia64/efi/startup.S; ia64_efi = kern/ia64/efi/init.c; ia64_efi = kern/ia64/dl.c; ia64_efi = kern/ia64/dl_helper.c; + arm_efi = kern/arm/efi/init.c; + arm_efi = kern/arm/efi/misc.c; + i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/mmap.c; - i386_pc = kern/i386/tsc.c; i386_pc = term/i386/pc/console.c; i386_qemu = bus/pci.c; i386_qemu = kern/vga_init.c; i386_qemu = kern/i386/qemu/mmap.c; - i386_qemu = kern/i386/tsc.c; i386_coreboot = kern/i386/coreboot/mmap.c; - i386_coreboot = kern/i386/tsc.c; + i386_coreboot = kern/i386/coreboot/cbtable.c; i386_multiboot = kern/i386/multiboot_mmap.c; - i386_multiboot = kern/i386/tsc.c; mips = kern/mips/cache.S; mips = kern/mips/dl.c; @@ -173,9 +215,9 @@ kernel = { mips_qemu_mips = term/ns8250.c; mips_qemu_mips = term/serial.c; mips_qemu_mips = term/at_keyboard.c; + mips_qemu_mips = commands/boot.c; mips_qemu_mips = commands/keylayouts.c; mips_qemu_mips = term/i386/pc/vga_text.c; - mips_qemu_mips = term/i386/vga_common.c; mips_qemu_mips = kern/vga_init.c; mips_arc = kern/mips/arc/init.c; @@ -188,6 +230,7 @@ kernel = { mips_loongson = bus/pci.c; mips_loongson = kern/mips/loongson/init.c; mips_loongson = term/at_keyboard.c; + mips_loongson = commands/boot.c; mips_loongson = term/serial.c; mips_loongson = video/sm712.c; mips_loongson = video/sis315pro.c; @@ -203,11 +246,22 @@ kernel = { sparc64_ieee1275 = kern/sparc64/dl.c; sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; + arm = kern/arm/dl.c; + arm = kern/arm/dl_helper.c; + arm = kern/arm/cache_armv6.S; + arm = kern/arm/cache_armv7.S; + extra_dist = kern/arm/cache.S; + arm = kern/arm/cache.c; + arm = kern/arm/misc.S; + emu = disk/host.c; - emu = gnulib/progname.c; - emu = gnulib/error.c; emu = kern/emu/cache_s.S; emu = kern/emu/hostdisk.c; + emu = osdep/unix/hostdisk.c; + emu = osdep/exec.c; + extra_dist = osdep/unix/exec.c; + emu = osdep/devmapper/hostdisk.c; + emu = osdep/hostdisk.c; emu = kern/emu/hostfs.c; emu = kern/emu/main.c; emu = kern/emu/argp_common.c; @@ -215,23 +269,28 @@ kernel = { emu = kern/emu/mm.c; emu = kern/emu/time.c; emu = kern/emu/cache.c; - emu = term/emu/console.c; + emu = osdep/emuconsole.c; + extra_dist = osdep/unix/emuconsole.c; + extra_dist = osdep/windows/emuconsole.c; + emu = osdep/sleep.c; + emu = osdep/init.c; + emu = osdep/emunet.c; + extra_dist = osdep/linux/emunet.c; + extra_dist = osdep/basic/emunet.c; + emu = osdep/cputime.c; + extra_dist = osdep/unix/cputime.c; + extra_dist = osdep/windows/cputime.c; videoinkernel = term/gfxterm.c; videoinkernel = font/font.c; videoinkernel = font/font_cmd.c; videoinkernel = io/bufio.c; - videoinkernel = video/bitmap.c; - videoinkernel = video/bitmap_scale.c; - videoinkernel = video/colors.c; videoinkernel = video/fb/fbblit.c; videoinkernel = video/fb/fbfill.c; videoinkernel = video/fb/fbutil.c; videoinkernel = video/fb/video_fb.c; videoinkernel = video/video.c; - videoinkernel = commands/boot.c; - extra_dist = kern/i386/int.S; extra_dist = kern/i386/realmode.S; extra_dist = boot/i386/pc/lzma_decode.S; @@ -245,9 +304,9 @@ program = { emu = kern/emu/full.c; emu_nodist = grub_emu_init.c; - ldadd = 'kernel.img$(EXEEXT)'; + ldadd = 'kernel.exec$(EXEEXT)'; ldadd = '$(MODULE_FILES)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = 'gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; enable = emu; }; @@ -258,8 +317,8 @@ program = { emu = kern/emu/lite.c; emu_nodist = symlist.c; - ldadd = 'kernel.img$(EXEEXT)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = 'kernel.exec$(EXEEXT)'; + ldadd = 'gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; enable = emu; }; @@ -286,12 +345,34 @@ image = { enable = sparc64_ieee1275; }; +image = { + name = boot_hybrid; + i386_pc = boot/i386/pc/boot.S; + + cppflags = '-DHYBRID_BOOT=1'; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + image = { name = cdboot; + i386_pc = boot/i386/pc/cdboot.S; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S; + sparc64_ieee1275_objcopyflags = '-O a.out-sunos-big'; + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x4000'; + sparc64_ieee1275_cppflags = '-DCDBOOT=1'; + objcopyflags = '-O binary'; + + enable = sparc64_ieee1275; enable = i386_pc; }; @@ -345,11 +426,9 @@ image = { cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1'; objcopyflags = '-O binary'; - mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; - ldadd = '-lgcc'; - cflags = '-Wno-unreachable-code -static-libgcc'; + mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + ldadd = '$(TARGET_LIBGCC)'; + cflags = '-Wno-unreachable-code $(TARGET_LDFLAGS_STATIC_LIBGCC)'; enable = mips; }; @@ -361,17 +440,16 @@ image = { cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1'; objcopyflags = '-O binary'; - mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; - ldadd = '-lgcc'; - cflags = '-static-libgcc'; + mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + ldadd = '$(TARGET_LIBGCC)'; + cflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC)'; enable = mips; }; image = { name = lzma_decompress; i386_pc = boot/i386/pc/startup_raw.S; + i386_pc_nodist = rs_decoder.h; objcopyflags = '-O binary'; ldflags = '$(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x8200'; @@ -382,7 +460,7 @@ image = { name = fwstart; mips_loongson = boot/mips/loongson/fwstart.S; objcopyflags = '-O binary'; - ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; enable = mips_loongson; }; @@ -390,10 +468,16 @@ image = { name = fwstart_fuloong2f; mips_loongson = boot/mips/loongson/fuloong2f.S; objcopyflags = '-O binary'; - ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; enable = mips_loongson; }; +module = { + name = disk; + common = lib/disk.c; + extra_dist = kern/disk_common.c; +}; + module = { name = trig; common_nodist = trigtables.c; @@ -430,6 +514,7 @@ module = { module = { name = emuusb; common = bus/usb/usb.c; + enable = emu; condition = COND_GRUB_EMU_USB; }; @@ -451,10 +536,16 @@ module = { enable = usb; }; +module = { + name = usbserial_usbdebug; + common = bus/usb/serial/usbdebug_late.c; + enable = usb; +}; + module = { name = uhci; common = bus/usb/uhci.c; - enable = x86; + enable = pci; }; module = { @@ -479,11 +570,21 @@ module = { enable = i386_multiboot; }; +module = { + name = nativedisk; + common = commands/nativedisk.c; + + enable = x86; + enable = mips_loongson; + enable = mips_qemu_mips; +}; + module = { name = emupci; common = bus/emu/pci.c; common = commands/lspci.c; + enable = emu; condition = COND_GRUB_EMU_PCI; }; @@ -494,6 +595,19 @@ module = { enable = mips_arc; }; +module = { + name = lsxen; + common = commands/xen/lsxen.c; + cppflags = '$(CPPFLAGS_XEN)'; + + enable = xen; +}; + +module = { + name = check_nt_hiberfil; + common = commands/i386/nthibr.c; +}; + library = { name = libgnulib.a; common = gnulib/regex.c; @@ -507,17 +621,53 @@ module = { enable = cmos; }; +module = { + name = cmosdump; + common = commands/i386/cmosdump.c; + enable = cmos; +}; + module = { name = iorw; common = commands/iorw.c; enable = x86; }; +module = { + name = cbtable; + common = kern/i386/coreboot/cbtable.c; + enable = i386_pc; + enable = i386_efi; + enable = i386_qemu; + enable = i386_multiboot; + enable = i386_ieee1275; + enable = x86_64_efi; +}; + +module = { + name = cbtime; + common = commands/i386/coreboot/cb_timestamps.c; + enable = x86; +}; + +module = { + name = cbls; + common = commands/i386/coreboot/cbls.c; + enable = x86; +}; + +module = { + name = cbmemc; + common = term/i386/coreboot/cbmemc.c; + enable = x86; +}; + module = { name = regexp; common = commands/regexp.c; common = commands/wildcard.c; ldadd = libgnulib.a; + dependencies = libgnulib.a; cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; }; @@ -572,6 +722,12 @@ module = { enable = efi; }; +module = { + name = lsefi; + common = commands/efi/lsefi.c; + enable = efi; +}; + module = { name = efifwsetup; efi = commands/efi/efifwsetup.c; @@ -587,7 +743,14 @@ module = { name = boot; common = commands/boot.c; i386_pc = lib/i386/pc/biosnum.c; - enable = videomodules; + enable = x86; + enable = emu; + enable = sparc64_ieee1275; + enable = powerpc_ieee1275; + enable = mips_arc; + enable = ia64_efi; + enable = arm_efi; + enable = arm_uboot; }; module = { @@ -607,8 +770,10 @@ module = { module = { name = cpuid; - x86 = commands/i386/cpuid.c; + common = commands/i386/cpuid.c; enable = x86; + enable = i386_xen; + enable = x86_64_xen; }; module = { @@ -629,6 +794,11 @@ module = { common = commands/echo.c; }; +module = { + name = eval; + common = commands/eval.c; +}; + module = { name = extcmd; common = commands/extcmd.c; @@ -660,9 +830,12 @@ module = { i386_multiboot = lib/i386/halt.c; i386_coreboot = lib/i386/halt.c; i386_qemu = lib/i386/halt.c; + xen = lib/xen/halt.c; + xen_cppflags = '$(CPPFLAGS_XEN)'; efi = lib/efi/halt.c; ieee1275 = lib/ieee1275/halt.c; emu = lib/emu/halt.c; + uboot = lib/uboot/halt.c; }; module = { @@ -671,11 +844,15 @@ module = { i386 = lib/i386/reboot_trampoline.S; ia64_efi = lib/efi/reboot.c; x86_64_efi = lib/efi/reboot.c; + arm_efi = lib/efi/reboot.c; powerpc_ieee1275 = lib/ieee1275/reboot.c; sparc64_ieee1275 = lib/ieee1275/reboot.c; mips_arc = lib/mips/arc/reboot.c; mips_loongson = lib/mips/loongson/reboot.c; mips_qemu_mips = lib/mips/qemu_mips/reboot.c; + xen = lib/xen/reboot.c; + xen_cppflags = '$(CPPFLAGS_XEN)'; + uboot = lib/uboot/reboot.c; common = commands/reboot.c; }; @@ -684,6 +861,13 @@ module = { common = commands/hashsum.c; }; +module = { + name = verify; + common = commands/verify.c; + cflags = '$(CFLAGS_POSIX)'; + cppflags = '-I$(srcdir)/lib/posix_wrap'; +}; + module = { name = hdparm; common = commands/hdparm.c; @@ -778,6 +962,18 @@ module = { enable = x86; }; +module = { + name = spkmodem; + x86 = term/spkmodem.c; + enable = x86; +}; + +module = { + name = morse; + x86 = term/morse.c; + enable = x86; +}; + module = { name = probe; common = commands/probe.c; @@ -815,6 +1011,12 @@ module = { enable = pci; }; +module = { + name = pcidump; + common = commands/pcidump.c; + enable = pci; +}; + module = { name = sleep; common = commands/sleep.c; @@ -1022,6 +1224,11 @@ module = { enable = videomodules; }; +module = { + name = procfs; + common = fs/proc.c; +}; + module = { name = affs; common = fs/affs.c; @@ -1045,6 +1252,16 @@ module = { cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; }; +module = { + name = archelp; + common = fs/archelp.c; +}; + +module = { + name = cbfs; + common = fs/cbfs.c; +}; + module = { name = cpio; common = fs/cpio.c; @@ -1095,6 +1312,11 @@ module = { common = fs/hfsplus.c; }; +module = { + name = hfspluscomp; + common = fs/hfspluscomp.c; +}; + module = { name = iso9660; common = fs/iso9660.c; @@ -1187,6 +1409,11 @@ module = { common = fs/ufs.c; }; +module = { + name = ufs1_be; + common = fs/ufs_be.c; +}; + module = { name = ufs2; common = fs/ufs2.c; @@ -1201,6 +1428,7 @@ module = { name = zfs; common = fs/zfs/zfs.c; common = fs/zfs/zfs_lzjb.c; + common = fs/zfs/zfs_lz4.c; common = fs/zfs/zfs_sha256.c; common = fs/zfs/zfs_fletcher.c; }; @@ -1256,6 +1484,11 @@ module = { common = io/gzio.c; }; +module = { + name = offsetio; + common = io/offset.c; +}; + module = { name = bufio; common = io/bufio.c; @@ -1265,6 +1498,8 @@ module = { module = { name = elf; common = kern/elf.c; + + extra_dist = kern/elfXX.c; }; module = { @@ -1287,13 +1522,21 @@ module = { x86 = lib/i386/relocator64.S; i386 = lib/i386/relocator_asm.S; x86_64 = lib/x86_64/relocator_asm.S; + i386_xen = lib/i386/relocator_asm.S; + x86_64_xen = lib/x86_64/relocator_asm.S; x86 = lib/i386/relocator.c; + x86 = lib/i386/relocator_common_c.c; ieee1275 = lib/ieee1275/relocator.c; efi = lib/efi/relocator.c; mips = lib/mips/relocator_asm.S; mips = lib/mips/relocator.c; powerpc = lib/powerpc/relocator_asm.S; powerpc = lib/powerpc/relocator.c; + xen = lib/xen/relocator.c; + i386_xen = lib/i386/xen/relocator.S; + x86_64_xen = lib/x86_64/xen/relocator.S; + xen = lib/i386/relocator_common_c.c; + xen_cppflags = '$(CPPFLAGS_XEN)'; extra_dist = lib/i386/relocator_common.S; extra_dist = kern/powerpc/cache_flush.S; @@ -1301,16 +1544,20 @@ module = { enable = mips; enable = powerpc; enable = x86; + enable = xen; }; module = { name = datetime; cmos = lib/cmos_datetime.c; efi = lib/efi/datetime.c; + uboot = lib/uboot/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c; sparc64_ieee1275 = lib/ieee1275/cmos.c; powerpc_ieee1275 = lib/ieee1275/cmos.c; + xen = lib/xen/datetime.c; + xen_cppflags = '$(CPPFLAGS_XEN)'; mips_arc = lib/arc/datetime.c; enable = noemu; @@ -1326,6 +1573,7 @@ module = { extra_dist = lib/powerpc/setjmp.S; extra_dist = lib/ia64/setjmp.S; extra_dist = lib/ia64/longjmp.S; + extra_dist = lib/arm/setjmp.S; }; module = { @@ -1355,9 +1603,10 @@ module = { module = { name = linux16; - i386_pc = loader/i386/pc/linux.c; - i386_pc = lib/cmdline.c; - enable = i386_pc; + common = loader/i386/pc/linux.c; + common = loader/linux.c; + common = lib/cmdline.c; + enable = x86; }; module = { @@ -1383,6 +1632,7 @@ module = { cppflags = "-DGRUB_USE_MULTIBOOT2"; common = loader/multiboot.c; + common = lib/cmdline.c; common = loader/multiboot_mbi2.c; enable = x86; enable = mips; @@ -1391,6 +1641,7 @@ module = { module = { name = multiboot; common = loader/multiboot.c; + common = lib/cmdline.c; x86 = loader/i386/multiboot_mbi.c; extra_dist = loader/multiboot_elfxx.c; enable = x86; @@ -1399,11 +1650,20 @@ module = { module = { name = linux; x86 = loader/i386/linux.c; + xen = loader/i386/xen.c; + xen = loader/i386/xen_file.c; + xen = loader/i386/xen_file32.c; + xen = loader/i386/xen_file64.c; + extra_dist = loader/i386/xen_fileXX.c; + xen_cppflags = '$(CPPFLAGS_XEN)'; 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; ia64_efi = loader/ia64/efi/linux.c; + arm = loader/arm/linux.c; + arm = lib/fdt.c; + common = loader/linux.c; common = lib/cmdline.c; enable = noemu; }; @@ -1441,6 +1701,7 @@ module = { efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; i386_coreboot = loader/i386/coreboot/chainloader.c; + i386_coreboot = lib/LzmaDec.c; enable = i386_pc; enable = i386_coreboot; enable = efi; @@ -1461,6 +1722,7 @@ module = { enable = x86; enable = ia64_efi; + enable = arm_efi; enable = mips; }; @@ -1555,6 +1817,11 @@ module = { common = partmap/sunpc.c; }; +module = { + name = part_dfly; + common = partmap/dfly.c; +}; + module = { name = msdospart; common = parttool/msdospart.c; @@ -1572,15 +1839,22 @@ module = { enable = videomodules; }; +module = { + name = gfxterm_background; + common = term/gfxterm_background.c; +}; + module = { name = serial; common = term/serial.c; x86 = term/ns8250.c; ieee1275 = term/ieee1275/serial.c; + mips_arc = term/arc/serial.c; efi = term/efi/serial.c; enable = terminfomodule; enable = ieee1275; + enable = mips_arc; }; module = { @@ -1606,17 +1880,21 @@ module = { name = vga; common = video/i386/pc/vga.c; enable = i386_pc; - enable = i386_coreboot; - enable = i386_multiboot; }; module = { name = vga_text; common = term/i386/pc/vga_text.c; - common = term/i386/vga_common.c; enable = i386_pc; }; +module = { + name = mda_text; + common = term/i386/pc/mda_text.c; + enable = i386_pc; + enable = i386_coreboot_multiboot_qemu; +}; + module = { name = video_cirrus; x86 = video/cirrus.c; @@ -1633,6 +1911,10 @@ module = { name = functional_test; common = tests/lib/functional_test.c; common = tests/lib/test.c; + common = tests/checksums.h; + common = tests/video_checksum.c; + common = tests/fake_input.c; + common = video/capture.c; }; module = { @@ -1640,16 +1922,64 @@ module = { common = tests/example_functional_test.c; }; +module = { + name = setjmp_test; + common = tests/setjmp_test.c; +}; + +module = { + name = signature_test; + common = tests/signature_test.c; +}; + +module = { + name = xnu_uuid_test; + common = tests/xnu_uuid_test.c; +}; + +module = { + name = pbkdf2_test; + common = tests/pbkdf2_test.c; +}; + +module = { + name = legacy_password_test; + common = tests/legacy_password_test.c; + enable = i386_pc; + enable = i386_efi; + enable = x86_64_efi; + enable = emu; + enable = xen; +}; + +module = { + name = div_test; + common = tests/div_test.c; +}; + +module = { + name = videotest_checksum; + common = tests/videotest_checksum.c; +}; + +module = { + name = gfxterm_menu; + common = tests/gfxterm_menu.c; +}; + +module = { + name = cmdline_cat_test; + common = tests/cmdline_cat_test.c; +}; + module = { name = bitmap; common = video/bitmap.c; - enable = videomodules; }; module = { name = bitmap_scale; common = video/bitmap_scale.c; - enable = videomodules; }; module = { @@ -1684,8 +2014,6 @@ module = { name = vbe; common = video/i386/pc/vbe.c; enable = i386_pc; - enable = i386_coreboot; - enable = i386_multiboot; }; module = { @@ -1700,10 +2028,14 @@ module = { module = { name = video; common = video/video.c; - common = video/colors.c; enable = videomodules; }; +module = { + name = video_colors; + common = video/colors.c; +}; + module = { name = ieee1275_fb; ieee1275 = video/ieee1275.c; @@ -1753,6 +2085,12 @@ module = { enable = ieee1275; }; +module = { + name = ubootnet; + common = net/drivers/uboot/ubootnet.c; + enable = uboot; +}; + module = { name = efinet; common = net/drivers/efi/efinet.c; @@ -1770,8 +2108,15 @@ module = { common = commands/legacycfg.c; common = lib/legacy_parse.c; emu = lib/i386/pc/vesa_modes_table.c; + i386_efi = lib/i386/pc/vesa_modes_table.c; + x86_64_efi = lib/i386/pc/vesa_modes_table.c; + xen = lib/i386/pc/vesa_modes_table.c; + enable = i386_pc; + enable = i386_efi; + enable = x86_64_efi; enable = emu; + enable = xen; }; module = { @@ -1805,8 +2150,12 @@ module = { module = { name = backtrace; x86 = lib/i386/backtrace.c; + i386_xen = lib/i386/backtrace.c; + x86_64_xen = lib/i386/backtrace.c; common = lib/backtrace.c; enable = x86; + enable = i386_xen; + enable = x86_64_xen; }; module = { @@ -1818,7 +2167,7 @@ module = { module = { name = keylayouts; common = commands/keylayouts.c; - enable = videomodules; + enable = x86; }; module = { @@ -1837,6 +2186,12 @@ module = { condition = COND_ENABLE_CACHE_STATS; }; +module = { + name = boottime; + common = commands/boottime.c; + condition = COND_ENABLE_BOOT_TIME_STATS; +}; + module = { name = adler32; common = lib/adler32.c; @@ -1847,6 +2202,36 @@ module = { common = lib/crc64.c; }; +module = { + name = mpi; + common = lib/libgcrypt-grub/mpi/mpiutil.c; + common = lib/libgcrypt-grub/mpi/mpi-bit.c; + common = lib/libgcrypt-grub/mpi/mpi-add.c; + common = lib/libgcrypt-grub/mpi/mpi-mul.c; + common = lib/libgcrypt-grub/mpi/mpi-mod.c; + common = lib/libgcrypt-grub/mpi/mpi-gcd.c; + common = lib/libgcrypt-grub/mpi/mpi-div.c; + common = lib/libgcrypt-grub/mpi/mpi-cmp.c; + common = lib/libgcrypt-grub/mpi/mpi-inv.c; + common = lib/libgcrypt-grub/mpi/mpi-pow.c; + common = lib/libgcrypt-grub/mpi/mpi-mpow.c; + common = lib/libgcrypt-grub/mpi/mpih-lshift.c; + common = lib/libgcrypt-grub/mpi/mpih-mul.c; + common = lib/libgcrypt-grub/mpi/mpih-mul1.c; + common = lib/libgcrypt-grub/mpi/mpih-mul2.c; + common = lib/libgcrypt-grub/mpi/mpih-mul3.c; + common = lib/libgcrypt-grub/mpi/mpih-add1.c; + common = lib/libgcrypt-grub/mpi/mpih-sub1.c; + common = lib/libgcrypt-grub/mpi/mpih-div.c; + common = lib/libgcrypt-grub/mpi/mpicoder.c; + common = lib/libgcrypt-grub/mpi/mpih-rshift.c; + common = lib/libgcrypt-grub/mpi/mpi-inline.c; + common = lib/libgcrypt_wrap/mem.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + module = { name = all_video; common = lib/fake_module.c; @@ -1862,3 +2247,17 @@ module = { enable = i386; }; +module = { + name = testspeed; + common = commands/testspeed.c; +}; + +module = { + name = tr; + common = commands/tr.c; +}; + +module = { + name = progress; + common = lib/progress.c; +}; diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S index 05fea2000..e074b07e5 100644 --- a/grub-core/boot/i386/pc/boot.S +++ b/grub-core/boot/i386/pc/boot.S @@ -31,6 +31,81 @@ #define MSG(x) movw $x, %si; call LOCAL(message) #define ERR(x) movw $x, %si; jmp LOCAL(error_message) + .macro floppy +part_start: + +probe_values: + .byte 36, 18, 15, 9, 0 + +LOCAL(floppy_probe): +/* + * Perform floppy probe. + */ + + movw $probe_values - 1, %si + +LOCAL(probe_loop): + /* reset floppy controller INT 13h AH=0 */ + xorw %ax, %ax + int $0x13 + + incw %si + movb (%si), %cl + + /* if number of sectors is 0, display error and die */ + cmpb $0, %cl + jne 1f + +/* + * Floppy disk probe failure. + */ + MSG(fd_probe_error_string) + jmp LOCAL(general_error) + +/* "Floppy" */ +fd_probe_error_string: .asciz "Floppy" + +1: + /* perform read */ + movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx + movw %bx, %es + xorw %bx, %bx + movw $0x201, %ax + movb $0, %ch + movb $0, %dh + int $0x13 + + /* if error, jump to "LOCAL(probe_loop)" */ + jc LOCAL(probe_loop) + + /* %cl is already the correct value! */ + movb $1, %dh + movb $79, %ch + + jmp LOCAL(final_init) + .endm + + .macro scratch + + /* scratch space */ +mode: + .byte 0 +disk_address_packet: +sectors: + .long 0 +heads: + .long 0 +cylinders: + .word 0 +sector_start: + .byte 0 +head_start: + .byte 0 +cylinder_start: + .word 0 + /* more space... */ + .endm + .file "boot.S" .text @@ -54,6 +129,34 @@ start: jmp LOCAL(after_BPB) nop /* do I care about this ??? */ +#ifdef HYBRID_BOOT + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + nop + nop + nop + + nop + nop + jmp LOCAL(after_BPB) +#else /* * This space is for the BIOS parameter block!!!! Don't change * the first jump, nor start the code anywhere but right after @@ -62,27 +165,14 @@ start: . = _start + GRUB_BOOT_MACHINE_BPB_START . = _start + 4 - - /* scratch space */ -mode: - .byte 0 -disk_address_packet: -sectors: - .long 0 -heads: - .long 0 -cylinders: - .word 0 -sector_start: - .byte 0 -head_start: - .byte 0 -cylinder_start: - .word 0 - /* more space... */ +#endif +#ifdef HYBRID_BOOT + floppy +#else + scratch +#endif . = _start + GRUB_BOOT_MACHINE_BPB_END - /* * End of BIOS parameter block. */ @@ -90,9 +180,11 @@ cylinder_start: kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR +#ifndef HYBRID_BOOT . = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR kernel_sector: .long 1, 0 +#endif . = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE boot_drive: @@ -421,6 +513,11 @@ LOCAL(message): * number here. */ +#ifdef HYBRID_BOOT + . = _start + 0x1b0 +kernel_sector: + .long 1, 0 +#endif . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC nt_magic: .long 0 @@ -430,62 +527,17 @@ nt_magic: * This is where an MBR would go if on a hard disk. The code * here isn't even referenced unless we're on a floppy. Kinda * sneaky, huh? - */ + */ . = _start + GRUB_BOOT_MACHINE_PART_START -part_start: -probe_values: - .byte 36, 18, 15, 9, 0 - -LOCAL(floppy_probe): -/* - * Perform floppy probe. - */ - - movw $probe_values - 1, %si - -LOCAL(probe_loop): - /* reset floppy controller INT 13h AH=0 */ - xorw %ax, %ax - int $0x13 - - incw %si - movb (%si), %cl - - /* if number of sectors is 0, display error and die */ - cmpb $0, %cl - jne 1f - -/* - * Floppy disk probe failure. - */ - MSG(fd_probe_error_string) - jmp LOCAL(general_error) - -/* "Floppy" */ -fd_probe_error_string: .asciz "Floppy" - -1: - /* perform read */ - movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx - movw %bx, %es - xorw %bx, %bx - movw $0x201, %ax - movb $0, %ch - movb $0, %dh - int $0x13 - - /* if error, jump to "LOCAL(probe_loop)" */ - jc LOCAL(probe_loop) - - /* %cl is already the correct value! */ - movb $1, %dh - movb $79, %ch - - jmp LOCAL(final_init) +#ifndef HYBRID_BOOT + floppy +#else + scratch +#endif . = _start + GRUB_BOOT_MACHINE_PART_END - + /* the last 2 bytes in the sector 0 contain the signature */ .word GRUB_BOOT_MACHINE_SIGNATURE diff --git a/grub-core/boot/i386/pc/cdboot.S b/grub-core/boot/i386/pc/cdboot.S index d939835a9..92df7c76f 100644 --- a/grub-core/boot/i386/pc/cdboot.S +++ b/grub-core/boot/i386/pc/cdboot.S @@ -93,11 +93,12 @@ LOCAL(read_cdrom): pushw $CDBLK_LENG /* Block number. */ + incl %esi pushl %eax pushl %esi /* Buffer address. */ - pushw $((DATA_ADDR - 0x400)>> 4) + pushw $((DATA_ADDR - 0x200)>> 4) pushl %eax pushw $0x10 @@ -167,6 +168,6 @@ err_noboot_msg: err_cdfail_msg: .ascii "cdrom read fails\0" - . = start + 0x1FF + . = start + 0x7FF .byte 0 diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index e4bc8b425..87e56a2fd 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -207,6 +207,10 @@ real_code_2: 2: call LOCAL(move_memory) + movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2) + movb (reg_edx + 2 - start), %dh + movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1) + movb $0xFF, %dh ljmp $(DATA_ADDR >> 4), $0 diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 81c0bc457..279674030 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -100,7 +100,6 @@ LOCAL (codestart): /* The ".code32" directive takes GAS out of 16-bit mode. */ .code32 - incl %eax cld call grub_gate_a20 @@ -119,12 +118,12 @@ LOCAL (codestart): #include "../../../kern/i386/realmode.S" -#include +#include .text /* - * grub_gate_a20(int on) + * grub_gate_a20(void) * * Gate address-line 20 for high memory. * @@ -134,12 +133,10 @@ LOCAL (codestart): */ grub_gate_a20: - movl %eax, %edx - gate_a20_test_current_state: /* first of all, test if already in a good state */ call gate_a20_check_state - cmpb %al, %dl + testb %al, %al jnz gate_a20_try_bios ret @@ -149,18 +146,15 @@ gate_a20_try_bios: call prot_to_real .code16 - movw $0x2400, %ax - testb %dl, %dl - jz 1f - incw %ax -1: int $0x15 + movw $0x2401, %ax + int $0x15 DATA32 call real_to_prot .code32 popl %ebp call gate_a20_check_state - cmpb %al, %dl + testb %al, %al jnz gate_a20_try_system_control_port_a ret @@ -172,20 +166,13 @@ gate_a20_try_system_control_port_a: /* fourth, try the system control port A */ inb $0x92 andb $(~0x03), %al - testb %dl, %dl - jz 6f orb $0x02, %al -6: outb $0x92 + outb $0x92 - /* When turning off Gate A20, do not check the state strictly, - because a failure is not fatal usually, and Gate A20 is always - on some modern machines. */ - testb %dl, %dl - jz 7f call gate_a20_check_state - cmpb %al, %dl + testb %al, %al jnz gate_a20_try_keyboard_controller -7: ret + ret gate_a20_flush_keyboard_buffer: inb $0x64 @@ -211,11 +198,8 @@ gate_a20_try_keyboard_controller: andb $0x02, %al jnz 4b - movb $0xdd, %al - testb %dl, %dl - jz 5f - orb $0x02, %al -5: outb $0x60 + movb $0xdf, %al + outb $0x60 call gate_a20_flush_keyboard_buffer /* output a dummy command (USB keyboard hack) */ @@ -224,7 +208,7 @@ gate_a20_try_keyboard_controller: call gate_a20_flush_keyboard_buffer call gate_a20_check_state - cmpb %al, %dl + testb %al, %al /* everything failed, so restart from the beginning */ jnz gate_a20_try_bios ret @@ -234,7 +218,7 @@ gate_a20_check_state: movl $100, %ecx 1: call 3f - cmpb %al, %dl + testb %al, %al jz 2f loop 1b 2: @@ -263,9 +247,8 @@ gate_a20_check_state: pushl %ebx addl $0x100000, %ebx movb (%ebx), %ch - /* this result is 1 if A20 is on or 0 if it is off */ + /* this result is 0 if A20 is on or 1 if it is off */ subb %ch, %al - xorb $1, %al /* restore the original */ popl %ebx movb %cl, (%ebx) diff --git a/grub-core/boot/i386/qemu/boot.S b/grub-core/boot/i386/qemu/boot.S index 97aeab9e6..ebbfe8828 100644 --- a/grub-core/boot/i386/qemu/boot.S +++ b/grub-core/boot/i386/qemu/boot.S @@ -51,6 +51,13 @@ VARIABLE(grub_core_entry_addr) pushl $1f DATA32 jmp real_to_prot .code32 + /* Ensure A20 is enabled. We're in qemu, so control port A works + and there is no need to wait since there is no real logic, it's + all emulated. */ + inb $0x92 + andb $(~0x03), %al + orb $0x02, %al + outb $0x92 1: movl grub_core_entry_addr, %edx jmp *%edx diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index ec57be6a1..c62b28fe9 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -754,140 +754,3 @@ continue: #endif cached_continue: -#ifndef FULOONG2F - /* We have to init video early enough or watchdog will reboot us. */ - - /* Setup PCI controller. */ - - lui $t0, %hi (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) - lui $t1, %hi(0x8000000c) - addiu $t1, $t1, %lo(0x8000000c) - - sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) ($t0) - li $t1, 0xffffffff - sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) ($t0) - - li $t0, GRUB_MACHINE_PCI_CONTROLLER_HEADER - li $t1, (GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER \ - | GRUB_PCI_COMMAND_MEM_ENABLED) - sh $t0, GRUB_PCI_REG_COMMAND ($t1) - li $t1, ((1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) \ - | GRUB_PCI_STATUS_FAST_B2B_CAPABLE \ - | GRUB_PCI_STATUS_66MHZ_CAPABLE \ - | GRUB_PCI_STATUS_CAPABILITIES) - sh $t0, GRUB_PCI_REG_STATUS ($t1) - li $t0, 0xff - sw $t0, GRUB_PCI_REG_CACHELINE ($t1) - lui $t1, %hi(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \ - | GRUB_PCI_ADDR_MEM_PREFETCH) - addiu $t1, $t1, %lo(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \ - | GRUB_PCI_ADDR_MEM_PREFETCH) - sw $t0, GRUB_PCI_REG_ADDRESS_REG0 ($t1) - sw $zero, GRUB_PCI_REG_ADDRESS_REG1 ($t1) - - /* Find video. */ - /* $t4 chooses device in priority encoding. */ - /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. - This way we don't need to sacrifice a register for it. */ -retry_sm712: - /* We have only one bus (0). Function is 0. */ - lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) - lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) - lui $t3, %hi(GRUB_SM712_PCIID) - addiu $t3, $t3, %lo(GRUB_SM712_PCIID) - ori $t4, $zero, 1 -1: - andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) - /* In case of failure try again. SM712 may be slow to come up. */ - beql $t4, $zero, retry_sm712 - nop - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) - bnel $t2, $t3, 1b - sll $t4, $t4, 1 - - /* FIXME: choose address dynamically if needed. */ -#define SM712_MAP 0x04000000 - - lui $t2, %hi(SM712_MAP) - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_ADDRESS_REG0) ($t1) - - /* Set latency. */ - li $t2, 0x8 - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_CACHELINE) ($t1) - - /* Enable address spaces. */ - li $t2, 0x7 - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_COMMAND) ($t1) - - lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX) - li $t2, 0x18 - sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)($t3) - - lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA) - li $t2, 0x11 - sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)($t3) - - li $t2, ((((SM712_MAP & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK) \ - >> GRUB_MACHINE_PCI_WIN_SHIFT) \ - & GRUB_MACHINE_PCI_WIN_MASK)) - lui $t3, %hi(0xbfe00110) - addiu $t3, $t3, %lo(0xbfe00110) - sw $t2, 0 ($t3) - li $t2, (GRUB_MACHINE_PCI_WIN1_ADDR \ - | (SM712_MAP & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)) - - lui $t3, %hi(GRUB_SM712_REG_BASE) - addiu $t3, $t3, %lo(GRUB_SM712_REG_BASE) - addu $t2, $t2, $t3 - lui $t0, %hi(init_table - 0x20000000) - addiu $t0, $t0, %lo(init_table - 0x20000000) - lui $t1, %hi(init_table_end - 0x20000000) - addiu $t1, $t1, %lo(init_table_end - 0x20000000) - li $t5, 0x80 - addiu $t6, $t2, 0x3c0 - -table_cont: - lb $t3, 0($t0) - andi $t5, $t3, 0x80 - andi $t3, $t3, 0x7f - addu $t3, $t3, $t6 - lb $t4, 1($t0) - - bne $zero, $t5, 1f - addiu $t0, $t0, 2 - b 2f - sb $t4, 0($t3) -1: - lb $t4, 0($t3) -2: - bne $t0, $t1, table_cont - nop - - lui $t3, %hi(0x40c000 - GRUB_SM712_REG_BASE) - addiu $t3, $t3, %lo(0x40c000 - GRUB_SM712_REG_BASE) - addu $t1, $t2, $t3 - sw $zero, 0xc ($t1) - sw $zero, 0x40 ($t1) - li $t3, 0x20000 - sw $t3, 0x0 ($t1) - lui $t3, %hi(0x1020100) - addiu $t3, $t3, %lo(0x1020100) - sw $t3, 0x10 ($t1) - - li $t4, 0x16 - sb $t4, GRUB_VGA_IO_SR_INDEX($t2) - - lb $t4, GRUB_VGA_IO_SR_DATA($t2) - - b init_end - nop -init_table: -#include "sm712_start.S" -init_table_end: - .align 4 -init_end: -#endif diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index bbbc1dbec..606197624 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -196,6 +196,21 @@ do_check: argfw: not $s7, $a2 cmdlinedone: +#endif +#ifdef GRUB_MACHINE_ARC + lui $t0, %hi(_start - 256) + addiu $t0, $t0, %lo(_start - 256) + addiu $t3, $t0, 255 + lw $t1, 0($a1) +1: + bne $t0, $t3, 2f + lb $t2, 0($t1) + move $t2, $zero +2: + sb $t2, 0($t0) + addiu $t0, $t0, 1 + bnez $t2, 1b + addiu $t1, $t1, 1 #endif /* Copy the decompressor. */ lui $t1, %hi(base) @@ -253,10 +268,15 @@ cmdlinedone: lui $t0, %hi(EXT_C(grub_decompress_core)) addiu $t0, $t0, %lo(EXT_C(grub_decompress_core)) +#ifdef GRUB_MACHINE_ARC + lui $sp, %hi(_start - 512) + jalr $t0 + addiu $sp, $sp, %lo(_start - 512) +#else lui $sp, %hi(_start - 256) jalr $t0 addiu $sp, $sp, %lo(_start - 256) - +#endif move $a0, $s1 move $a1, $s6 diff --git a/grub-core/boot/powerpc/bootinfo.txt.in b/grub-core/boot/powerpc/bootinfo.txt.in new file mode 100644 index 000000000..bc831daa9 --- /dev/null +++ b/grub-core/boot/powerpc/bootinfo.txt.in @@ -0,0 +1,73 @@ + +@PACKAGE@ @VERSION@ +@PACKAGE@ @VERSION@ +boot &device;:\boot\grub\powerpc.elf + + +FF FF FF FF FF FF FF FF FF FF 92 6D 6D 6D 6D 6D 6D 6D 6D 6D DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 92 6D 92 92 92 DB FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF DB 6D 92 DB FF FF FF FF FF DB B6 FF FF 92 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 DB FF FF FF FF FF B6 6D 92 DB FF FF FF FF FF FF FF +FF FF FF FF FF FF 49 92 FF FF B6 B6 24 00 24 00 00 00 00 49 6D DB 6D 92 DB B6 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 6D DB 92 6D 24 49 92 6D 6D FF FF FF 92 6D FF FF FF FF FF FF +FF FF FF FF B6 49 DB FF FF 24 00 00 00 92 92 B6 FF DB DB FF DB B6 FF DB 92 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 6D B6 FF 6D B6 6D 6D 92 24 24 00 00 24 6D FF FF 49 DB FF FF FF FF +FF FF FF B6 49 FF DB 49 24 00 49 6D B6 FF B6 92 6D 6D 6D 92 DB DB DB B6 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB FF FF FF FF DB B6 B6 B6 FF DB 24 00 00 92 B6 FF 49 FF FF FF FF +FF FF DB 49 FF FF 49 00 00 24 FF FF 6D 49 92 DB FF FF FF DB 92 92 92 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 92 6D 6D B6 DB DB B6 6D 6D FF FF 24 00 00 DB FF 49 FF FF FF +FF FF 49 FF FF 49 00 00 6D DB DB 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 B6 24 00 24 DB DB 6D FF FF +FF B6 92 FF B6 00 00 24 FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF 00 00 49 FF 92 B6 FF +FF 6D FF FF 92 00 00 49 FF 6D FF FF FF FF FF FF FF FF FF FF FF FF FF B6 92 92 6D 6D 6D 6D DB FF FF FF FF FF FF B6 92 92 92 92 92 FF FF FF FF FF FF FF FF FF FF FF FF 6D FF 24 00 24 FF FF 6D FF +DB 92 FF DB 00 00 49 FF 92 DB FF FF FF FF FF FF FF FF FF FF FF DB 6D B6 FF FF FF FF FF FF 92 6D FF FF FF FF 6D B6 FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF 92 DB 00 00 92 FF 92 DB +92 FF FF B6 00 00 6D FF 6D FF FF FF FF FF FF FF FF FF FF FF DB 6D FF FF FF 92 49 49 49 92 FF FF 49 DB DB 24 DB FF B6 49 49 92 FF FF DB 92 FF FF FF FF FF FF FF FF FF FF 92 FF 00 00 6D FF DB 92 +6D FF FF FF 00 00 49 92 DB FF FF FF FF FF FF FF FF FF FF DB 6D FF FF 6D 00 00 00 00 00 00 00 B6 FF 49 00 24 24 49 24 00 00 00 00 6D FF DB 92 FF FF FF FF FF FF FF FF FF DB B6 00 00 92 FF FF 6D +6D FF FF 24 00 00 DB 6D FF FF FF FF FF FF FF FF FF FF DB 6D FF DB 00 00 00 00 00 00 00 00 00 00 B6 FF DB B6 49 92 24 24 00 00 00 00 24 FF DB 92 FF FF FF FF FF FF FF FF FF 92 6D 00 00 DB FF 6D +6D FF FF 24 00 00 FF 6D FF FF FF FF FF FF FF FF FF FF 49 FF B6 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF 92 DB DB 24 24 00 00 00 00 24 FF 92 DB FF FF FF FF FF FF FF FF 92 92 00 00 FF FF 6D +6D FF FF B6 00 00 92 6D FF FF FF FF FF FF FF FF FF 49 FF DB 00 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF B6 B6 FF 92 24 00 00 00 00 00 49 FF 6D FF FF FF FF FF FF FF FF 92 24 00 49 FF FF 6D +6D FF FF 00 00 00 DB 6D FF FF FF FF FF FF FF FF 6D DB DB 00 00 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF DB B6 FF B6 49 00 00 00 00 00 00 6D FF 6D FF FF FF FF FF FF FF 92 92 00 00 DB FF 6D +6D FF FF DB 00 00 B6 6D FF FF FF FF FF FF FF 6D B6 FF 24 00 00 00 00 00 00 00 00 00 00 00 24 B6 DB 6D FF FF FF FF FF 6D 49 24 00 00 00 00 00 00 B6 DB B6 FF FF FF FF FF B6 DB 24 00 92 FF FF 6D +6D FF FF 6D 00 00 24 DB 92 FF FF FF FF FF 92 92 FF 49 00 00 00 00 00 49 B6 FF FF DB B6 DB FF FF FF B6 92 FF FF DB 92 FF FF FF 49 6D 92 24 00 00 00 DB B6 DB FF FF FF FF 6D FF 00 00 00 DB FF 6D +6D FF FF 92 24 00 49 FF 6D B6 FF FF FF 6D 92 FF 49 00 00 49 DB FF FF FF FF FF FF B6 FF FF FF FF FF FF B6 6D 92 92 FF FF FF FF 6D FF FF FF DB 24 00 24 FF 92 B6 FF FF 92 B6 FF 00 00 B6 FF FF 6D +92 FF FF FF 00 00 24 92 FF 92 6D 92 49 B6 DB 24 00 24 DB FF FF FF FF FF DB 92 24 00 FF FF FF FF 6D 6D FF FF FF 6D 6D FF FF B6 DB 6D FF FF FF FF 00 00 24 DB B6 6D 6D B6 DB 00 00 00 6D FF FF 6D +DB 92 FF DB 49 00 00 00 B6 FF FF DB FF 6D 00 00 6D FF FF FF FF FF FF FF 24 92 00 49 FF FF FF FF FF 6D B6 FF FF 6D 6D FF 6D 00 DB DB 92 FF FF FF DB 00 00 00 6D FF FF DB 6D 00 00 24 FF FF 92 DB +FF 49 FF FF 6D 00 00 00 24 49 B6 FF 24 00 00 6D FF FF FF FF FF FF FF 49 92 B6 00 DB FF FF DB DB FF FF B6 FF FF FF FF FF 00 49 DB FF 92 FF FF FF FF 92 00 00 00 24 6D 00 00 00 00 24 DB FF 49 FF +FF 92 B6 FF 92 49 00 00 00 00 00 24 00 00 00 FF FF FF FF FF FF FF 92 6D FF B6 DB FF DB B6 DB B6 B6 FF FF B6 FF FF FF DB 00 B6 DB FF 92 FF FF FF FF FF 24 00 00 00 00 00 00 00 00 B6 FF 92 B6 FF +FF FF 49 FF FF 49 24 00 00 00 00 00 00 00 B6 FF FF FF FF FF FF FF B6 FF FF FF FF FF FF FF FF FF 6D FF FF 6D FF FF FF DB 24 FF FF FF 92 FF FF FF FF FF 6D 00 00 00 00 00 00 00 DB FF FF 6D FF FF +FF FF DB 6D FF FF 6D 49 00 00 00 00 00 24 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 6D 49 24 24 24 FF FF DB FF FF FF FF 24 24 00 00 92 FF FF FF FF FF DB 00 00 00 00 00 00 FF DB FF 6D FF FF FF +FF FF FF 92 B6 FF FF DB 49 24 00 00 00 92 FF FF FF FF FF FF FF FF FF DB FF FF FF 49 49 24 00 24 FF FF FF FF FF FF FF FF 49 6D 00 24 49 FF FF FF FF FF FF 49 00 24 6D 6D B6 FF FF 6D B6 FF FF FF +FF FF FF FF 6D B6 FF FF DB 92 B6 49 00 FF FF FF FF FF FF FF FF FF FF B6 FF FF FF 92 DB 92 00 24 FF FF FF FF FF FF FF FF FF 00 00 6D FF FF FF FF FF FF FF DB 00 6D DB FF FF FF 6D B6 FF FF FF FF +FF FF FF FF FF 92 6D FF FF FF FF B6 49 FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF B6 92 92 B6 B6 DB FF FF FF FF FF FF FF B6 6D 49 6D FF FF FF FF FF FF FF 92 24 FF FF B6 6D DB FF FF FF FF FF +FF FF FF FF FF FF DB 49 6D B6 FF 6D 92 FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF FF 92 FF FF FF FF FF FF FF FF 6D DB 92 FF FF FF FF FF FF FF FF 6D 49 6D DB FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF DB 92 49 00 FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 6D FF FF FF FF FF FF FF DB 92 FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF DB 00 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 92 6D B6 FF FF FF FF FF FF 49 DB FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF 49 DB 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 6D FF 92 49 92 FF FF FF FF DB 49 DB FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF FF FF 6D 92 FF 92 FF FF FF FF FF FF FF FF FF FF B6 6D 49 6D DB FF FF FF FF FF 6D 49 FF FF FF DB 6D 6D 92 92 6D 49 FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF 6D 92 FF FF FF DB FF FF FF FF FF FF FF FF 6D 6D FF FF FF 92 6D FF FF FF FF FF 49 92 B6 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF DB 24 92 FF FF FF FF FF FF FF FF FF FF FF FF FF 49 49 6D DB FF FF DB 6D B6 FF FF FF FF B6 B6 DB 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF 24 B6 FF FF FF FF B6 49 49 24 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF 00 49 FF DB DB FF FF FF B6 92 FF FF FF FF FF FF 92 DB FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF 24 B6 FF FF B6 24 00 6D DB FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB DB 00 00 24 FF FF FF FF B6 FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF B6 B6 DB B6 6D 49 49 92 FF FF FF B6 6D FF FF FF FF FF FF FF 92 92 FF FF FF FF FF FF FF 49 92 DB 49 FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF 92 24 49 49 6D FF 6D 92 FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF DB FF FF FF FF FF FF FF FF B6 FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF B6 DB DB FF FF FF FF FF FF FF DB FF FF FF FF FF FF FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF 24 92 FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF B6 92 FF FF FF FF FF FF FF FF FF FF FF DB 6D 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF DB 49 FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 92 6D FF FF FF FF FF 00 24 DB FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF 92 6D FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 FF FF FF FF FF FF FF 49 00 DB FF FF FF FF FF FF FF FF FF 6D 6D B6 DB DB DB 92 49 00 00 00 00 00 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 DB FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF FF FF DB 6D 49 49 6D B6 DB FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 FF FF FF FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF DB 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF DB 6D 00 49 FF FF FF FF FF FF FF FF FF FF FF FF DB B6 92 6D 6D 6D 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF 49 00 92 FF FF FF FF FF FF FF FF 49 00 00 00 00 00 49 B6 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF 6D 6D FF B6 B6 FF FF FF FF FF FF 92 92 FF FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF DB 00 DB 6D 00 B6 FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 DB FF FF FF FF FF 92 00 FF 24 00 00 49 FF FF FF FF FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF FF FF FF 49 24 24 00 00 6D FF FF FF FF FF FF FF DB FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF FF FF FF FF 6D 00 24 24 24 FF FF FF FF FF FF DB B6 DB 49 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 00 B6 00 49 DB FF FF FF DB 24 6D 24 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 B6 6D 00 00 DB FF 6D 00 00 00 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 00 6D FF FF 00 00 DB 49 00 00 00 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 DB FF FF 6D 00 00 92 24 00 00 00 00 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF 00 6D 00 00 24 00 00 00 00 00 00 24 92 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB 00 00 00 00 00 00 00 00 00 00 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 00 24 00 00 6D 00 00 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 92 6D 6D DB B6 92 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF + + + diff --git a/grub-core/boot/powerpc/grub.chrp.in b/grub-core/boot/powerpc/grub.chrp.in new file mode 100644 index 000000000..9b2218352 --- /dev/null +++ b/grub-core/boot/powerpc/grub.chrp.in @@ -0,0 +1,172 @@ + + +MacRISC MacRISC3 MacRISC4 + + +@PACKAGE@ @VERSION@ + + +3434 +00000000000000F781FB8181818181FBFAF500000000000000000000000000000000000000F6FAFAFAFA81F9F600000000000000 +0000000000F8FBF9F500F95656FCFB5656FBF800000000000000000000000000000000F5FAF9F5F7F600F6F6F9FAF70000000000 +000000F5FBFA0056FDFEFEFDFDFAAC81FB56568181560000000000000000000000F9F9F9F7FCFDFEFEFEFFFC81F656FA00000000 +0000F5AC2BF7FBFEFEFD2BF6568181F9F7F6F6F8FBF50000000000000000000000FAF700F600F5F7F7F6F7FEFFACF82BFB000000 +0000FC2BF5FEFFFFF5F7FC81F70000F7F9FAFAF8000000000000000000000000000056F9F9FAF9F7F7FA812BF7FFFF56F7FA0000 +005656F5FEFFAC2BF9FA000000000000000000000000000000000000000000000000000000000000000000FA56FAFEFEF8F9F700 +00FB00F7FFFF56F9F800000000000000000000F656FAFA56F50000000000F5F8F9F8F5000000000000000000F9F7FCFFFB00FB00 +F8F800ACFFACF6FA000000000000000000F6FA562BF5F5F781FA000000F9FA2B00F556F9F5000000000000000081F8FFFEF6562B +810000FFFFF9FAF500000000000000002B8100F5F9FCACFBF82BFBF6FCFAF6FAFC81F600FA2B000000000000002BF8FEFFF8F5FA +FA00F5FEFFFA8100000000000000002B8100F9FEFFFFFFFFFFFBF6FDFEACFDFEFFFFFFFBF581F600000000000000F9FEFFF700FA +FA00FBFFFEF6F900000000000000F6FB00FCFFFFFFFFFFFFFFFFFCF600FCF7ACFEFFFFFFFDF6810000000000000056F9FFAC00FA +FA00F6FFFFF856000000000000F5FBF5ACFFFFFFFFFFFFFFFFFFFF2B002BF8F5ACFFFFFFFFFDF6FA000000000000F9FCFF560081 +FA0081FFFFF8F9000000000000FBF6FBFFFFFFFFFFFFFFFFFFFFFFF800F55600FCFFFFFFFFFF81F8F80000000000F981FFAC0081 +FA0000FEFEF8FB0000000000812BFAFFFFFFFFFFFFFEFFFFFDF92BFA0000F6F981ACFEFFFFFFFF56F9F600000000F9FDFF2B0081 +FA00FAFFFF81812B000000FAF8F9FFFFFEACFBF80000F500000000F9F900562B0000FCF7F9ACFFFF2BF9F50000F9F6FEFFFB0081 +810000FCFFFBF6FB56F7FBF8F9FFFE5600000000F5FAAC000000F82BF6FAFBF800F556F80000F9FFFE2BFAFAFAF8FAFFFEF60081 +FAF6F5ACFFFFAC00F856F7ACFFFCF500000000FAFCFFFC00000056AC00F581F92BFEF9FAF6000081FFFFFBF6F62BFFFFACF6F6FA +F6FA00FAFFFFFFACFA56FFFFAC0000000000F6FD2BFEF6F5565600F5F800F60081FEF7F656000000FDFFFFFDFDFFFFFFAC0081F5 +0081F52BFDFFFFFFFFFFFFFFF60000000000FBF6F6F5F656F52BF900FA000000FCFAF5F656000000F7FFFFFFFFFFFFFDF7F68100 +00F6FB00F8FDFFFFFFFFFF810000000000F6F5000000F52B56F9FC00F7F70000FCF881FCF500000000FEFFFFFFFFAC5600FBF500 +000056F900F8ACFDFFFFFFF5000000000000002B0000FDFEFFFE560000F60000F9ACFFFE810000000081FFFEFDFAF800FAF70000 +000000FAF9002B56FAFDFC0000000000000000F80000FBF5FEFEF5000000000000ACFFFA2B0000000000FEFB2BF5008156000000 +00000000F9FBF600F6FBF800000000000000F7F8000000F9F9F9F82B0000000000F6ACACF70000000000F7FD2BFA812B00000000 +0000000000F681FCFBFD0000000000000000FBF6000000000000F52B000000000000F92B810000000000008181F6000000000000 +0000000000000000F6FC00000000000000F6FF0000000000000000000000000000000081FBFB2B00000000F7F900000000000000 +000000000000000000FC00000000000000FCFAF600000000000000000000000000000056ACF581FBF700000081FB000000000000 +0000000000000000FAF90000000000008156F5F8000000000000002BFBFCFBF800000000FD2B000056FB8181FBF8000000000000 +0000000000000000AC0000000000F5FBF90000F6000000000000F5AC56F6005681F50000F6ACFCFBF70000000000000000000000 +00000000000000F881000000F5FAFDFD00000000000000000000F7FEFA2B0000F581F70000000000810000000000000000000000 +000000000000F9FCF500FAFDACFAF5FD00000000000000000000F5ACF5FDFEFA0000F82B00000000810000000000000000000000 +000000000000FCF8F9AC81FD000000FD000000000000FAF7000000F50081F9FAF800000000000000FB0000000000000000000000 +000000000000FC81F956F5FD000000FD0000000000000000F800F5000000000056000000000000F7FB0000000000000000000000 +00000000000000000000F5AC000000ACF800000000000000F5FAF80000000000F50000000000F8ACF50000000000000000000000 +00000000000000000000F5AC000000F5AC000000000000000056F9000000000000000000F7ACFCF5000000000000000000000000 +00000000000000000000F5FD00000000AC000000000000000000FB0000000000000000F5F6F5FCF6000000000000000000000000 +0000000000000000000000FD00000000FBFDF600000000000000F8F900000000000000000000F5FB000000000000000000000000 +0000000000000000000000FDF500000000F9ACF800000000000000815600000000F656818181AC56000000000000000000000000 +000000000000000000000081F80000000000F9FC0000000000000000F9ACACACFCFBFAFA81FD2B00000000000000000000000000 +0000000000000000000000F7FB0000000000FBF70000000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000ACF500000000F9FD56F5000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000F8FA0000000000F6FEFEF5000000000000F55681FCACFDACFC560000000000000000000000000000 +00000000000000000000000000FBF600000000002BFCFA00F700000000F9FDFDFAFEF90000000000000000000000000000000000 +00000000000000000000000000F5FB0000000000F5FEF7ACAC0000000000000000FCF50000000000000000000000000000000000 +0000000000000000000000000000F6FA000000002BFF2BFFFFAC00000000000000F7FA0000000000000000000000000000000000 +000000000000000000000000000000F65600000000FAFEFFFFAC0000000000F800F6810000000000000000000000000000000000 +00000000000000000000000000000000F52B00000000F8FEFBFF5600000000FCFAACF60000000000000000000000000000000000 +0000000000000000000000000000000000000000000000F9FCFCFFFB00F8FEFFFDF5000000000000000000000000000000000000 +00000000000000000000000000000000000000000000F9FDF7F5FFFD56FFFFFFFD00000000000000000000000000000000000000 +00000000000000000000000000000000000000000000810000FBFFFFFBFFFFFFFFACF9F5F5000000000000000000000000000000 +0000000000000000000000000000000000000000000000F600FC81FFFEFFFFFFFFFFFE8100000000000000000000000000000000 +00000000000000000000000000000000000000000000000000F7F6FDFFFFFFFEFFFFACF500000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000F5FC81FC81FAFBF9F500000000000000000000000000000000 + +00000000000000F781FB8181818181FBFAF500000000000000000000000000000000000000F6FAFAFAFA81F9F600000000000000 +0000000000F8FBF9F500F95656FCFB5656FBF800000000000000000000000000000000F5FAF9F5F7F600F6F6F9FAF70000000000 +000000F5FBFA0056FDFEFEFDFDFAAC81FB56568181560000000000000000000000F9F9F9F7FCFDFEFEFEFFFC81F656FA00000000 +0000F5AC2BF7FBFEFEFD2BF6568181F9F7F6F6F8FBF50000000000000000000000FAF700F600F5F7F7F6F7FEFFACF82BFB000000 +0000FC2BF5FEFFFFF5F7FC81F70000F7F9FAFAF8000000000000000000000000000056F9F9FAF9F7F7FA812BF7FFFF56F7FA0000 +005656F5FEFFAC2BF9FA000000000000000000000000000000000000000000000000000000000000000000FA56FAFEFEF8F9F700 +00FB00F7FFFF56F9F800000000000000000000F656FAFA56F50000000000F5F8F9F8F5000000000000000000F9F7FCFFFB00FB00 +F8F800ACFFACF6FA000000000000000000F6FA562BF5F5F781FA000000F9FA2B00F556F9F5000000000000000081F8FFFEF6562B +810000FFFFF9FAF500000000000000002B8100F5F9FCACFBF82BFBF6FCFAF6FAFC81F600FA2B000000000000002BF8FEFFF8F5FA +FA00F5FEFFFA8100000000000000002B8100F9FEFFFFFFFFFFFBF6FDFEACFDFEFFFFFFFBF581F600000000000000F9FEFFF700FA +FA00FBFFFEF6F900000000000000F6FB00FCFFFFFFFFFFFFFFFFFCF600FCF7ACFEFFFFFFFDF6810000000000000056F9FFAC00FA +FA00F6FFFFF856000000000000F5FBF5ACFFFFFFFFFFFFFFFFFFFF2B002BF8F5ACFFFFFFFFFDF6FA000000000000F9FCFF560081 +FA0081FFFFF8F9000000000000FBF6FBFFFFFFFFFFFFFFFFFFFFFFF800F55600FCFFFFFFFFFF81F8F80000000000F981FFAC0081 +FA0000FEFEF8FB0000000000812BFAFFFFFFFFFFFFFEFFFFFDF92BFA0000F6F981ACFEFFFFFFFF56F9F600000000F9FDFF2B0081 +FA00FAFFFF81812B000000FAF8F9FFFFFEACFBF80000F500000000F9F900562B0000FCF7F9ACFFFF2BF9F50000F9F6FEFFFB0081 +810000FCFFFBF6FB56F7FBF8F9FFFE5600000000F5FAAC000000F82BF6FAFBF800F556F80000F9FFFE2BFAFAFAF8FAFFFEF60081 +FAF6F5ACFFFFAC00F856F7ACFFFCF500000000FAFCFFFC00000056AC00F581F92BFEF9FAF6000081FFFFFBF6F62BFFFFACF6F6FA +F6FA00FAFFFFFFACFA56FFFFAC0000000000F6FD2BFEF6F5565600F5F800F60081FEF7F656000000FDFFFFFDFDFFFFFFAC0081F5 +0081F52BFDFFFFFFFFFFFFFFF60000000000FBF6F6F5F656F52BF900FA000000FCFAF5F656000000F7FFFFFFFFFFFFFDF7F68100 +00F6FB00F8FDFFFFFFFFFF810000000000F6F5000000F52B56F9FC00F7F70000FCF881FCF500000000FEFFFFFFFFAC5600FBF500 +000056F900F8ACFDFFFFFFF5000000000000002B0000FDFEFFFE560000F60000F9ACFFFE810000000081FFFEFDFAF800FAF70000 +000000FAF9002B56FAFDFC0000000000000000F80000FBF5FEFEF5000000000000ACFFFA2B0000000000FEFB2BF5008156000000 +00000000F9FBF600F6FBF800000000000000F7F8000000F9F9F9F82B0000000000F6ACACF70000000000F7FD2BFA812B00000000 +0000000000F681FCFBFD0000000000000000FBF6000000000000F52B000000000000F92B810000000000008181F6000000000000 +0000000000000000F6FC00000000000000F6FF0000000000000000000000000000000081FBFB2B00000000F7F900000000000000 +000000000000000000FC00000000000000FCFAF600000000000000000000000000000056ACF581FBF700000081FB000000000000 +0000000000000000FAF90000000000008156F5F8000000000000002BFBFCFBF800000000FD2B000056FB8181FBF8000000000000 +0000000000000000AC0000000000F5FBF90000F6000000000000F5AC56F6005681F50000F6ACFCFBF70000000000000000000000 +00000000000000F881000000F5FAFDFD00000000000000000000F7FEFA2B0000F581F70000000000810000000000000000000000 +000000000000F9FCF500FAFDACFAF5FD00000000000000000000F5ACF5FDFEFA0000F82B00000000810000000000000000000000 +000000000000FCF8F9AC81FD000000FD000000000000FAF7000000F50081F9FAF800000000000000FB0000000000000000000000 +000000000000FC81F956F5FD000000FD0000000000000000F800F5000000000056000000000000F7FB0000000000000000000000 +00000000000000000000F5AC000000ACF800000000000000F5FAF80000000000F50000000000F8ACF50000000000000000000000 +00000000000000000000F5AC000000F5AC000000000000000056F9000000000000000000F7ACFCF5000000000000000000000000 +00000000000000000000F5FD00000000AC000000000000000000FB0000000000000000F5F6F5FCF6000000000000000000000000 +0000000000000000000000FD00000000FBFDF600000000000000F8F900000000000000000000F5FB000000000000000000000000 +0000000000000000000000FDF500000000F9ACF800000000000000815600000000F656818181AC56000000000000000000000000 +000000000000000000000081F80000000000F9FC0000000000000000F9ACACACFCFBFAFA81FD2B00000000000000000000000000 +0000000000000000000000F7FB0000000000FBF70000000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000ACF500000000F9FD56F5000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000F8FA0000000000F6FEFEF5000000000000F55681FCACFDACFC560000000000000000000000000000 +00000000000000000000000000FBF600000000002BFCFA00F700000000F9FDFDFAFEF90000000000000000000000000000000000 +00000000000000000000000000F5FB0000000000F5FEF7ACAC0000000000000000FCF50000000000000000000000000000000000 +0000000000000000000000000000F6FA000000002BFF2BFFFFAC00000000000000F7FA0000000000000000000000000000000000 +000000000000000000000000000000F65600000000FAFEFFFFAC0000000000F800F6810000000000000000000000000000000000 +00000000000000000000000000000000F52B00000000F8FEFBFF5600000000FCFAACF60000000000000000000000000000000000 +0000000000000000000000000000000000000000000000F9FCFCFFFB00F8FEFFFDF5000000000000000000000000000000000000 +00000000000000000000000000000000000000000000F9FDF7F5FFFD56FFFFFFFD00000000000000000000000000000000000000 +00000000000000000000000000000000000000000000810000FBFFFFFBFFFFFFFFACF9F5F5000000000000000000000000000000 +0000000000000000000000000000000000000000000000F600FC81FFFEFFFFFFFFFFFE8100000000000000000000000000000000 +00000000000000000000000000000000000000000000000000F7F6FDFFFFFFFEFFFFACF500000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000F5FC81FC81FAFBF9F500000000000000000000000000000000 + +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + + +boot &device;:&partition;,\System\Library\CoreServices\grub.elf + + diff --git a/grub-core/boot/sparc64/ieee1275/boot.S b/grub-core/boot/sparc64/ieee1275/boot.S index f79699502..0ab9a4af3 100644 --- a/grub-core/boot/sparc64/ieee1275/boot.S +++ b/grub-core/boot/sparc64/ieee1275/boot.S @@ -28,6 +28,7 @@ pic_base: call boot_continue mov %o4, CIF_REG +#ifndef CDBOOT /* The offsets to these locations are defined by the * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h, * and grub-setup uses this to patch these next three values as needed. @@ -43,9 +44,19 @@ pic_base: . = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH boot_path: . = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE -boot_path_end: kernel_byte: .xword (2 << 9) +boot_path_end: kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR +#else +#define boot_path (_start + 512) +#define boot_path_end (_start + 1024) +#include + + . = _start + 8 +kernel_byte: .xword (2 << 9) +kernel_size: .word 512 +kernel_address: .word GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS +#endif prom_finddev_name: .asciz "finddevice" prom_chosen_path: .asciz "/chosen" @@ -158,8 +169,10 @@ boot_continue: mov GRUB_NAME_LEN, %o3 GET_ABS(boot_path, %o3) +#ifndef CDBOOT ldub [%o3], %o1 brnz,pn %o1, bootpath_known +#endif /* getprop(chosen_node, "bootpath", &buffer, buffer_size) */ GET_ABS(prom_bootpath_name, %o2) @@ -194,12 +207,19 @@ bootpath_known: GET_ABS(prom_read_name, %o0) LDUW_ABS(kernel_address, 0x00, %o2) call prom_call_3_1_o1 +#ifdef CDBOOT + LDUW_ABS(kernel_size, 0x00, %o3) +#else mov 512, %o3 +#endif LDUW_ABS(kernel_address, 0x00, %o2) jmpl %o2, %o7 +#ifdef CDBOOT + mov CIF_REG, %o4 +#else nop - +#endif . = _start + GRUB_BOOT_MACHINE_CODE_END /* the last 4 bytes in the sector 0 contain the signature */ diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 9e7796ea1..bb9aa27e5 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -29,28 +29,39 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Context for grub_cs5536_find. */ +struct grub_cs5536_find_ctx +{ + grub_pci_device_t *devp; + int found; +}; + +/* Helper for grub_cs5536_find. */ +static int +grub_cs5536_find_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + struct grub_cs5536_find_ctx *ctx = data; + + if (pciid == GRUB_CS5536_PCIID) + { + *ctx->devp = dev; + ctx->found = 1; + return 1; + } + return 0; +} + int grub_cs5536_find (grub_pci_device_t *devp) { - int found = 0; - auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, - grub_pci_id_t pciid); + struct grub_cs5536_find_ctx ctx = { + .devp = devp, + .found = 0 + }; - int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - if (pciid == GRUB_CS5536_PCIID) - { - *devp = dev; - found = 1; - return 1; - } - return 0; - } + grub_pci_iterate (grub_cs5536_find_iter, &ctx); - grub_pci_iterate (hook); - - return found; + return ctx.found; } grub_uint64_t diff --git a/grub-core/bus/emu/pci.c b/grub-core/bus/emu/pci.c index d1beb561d..9d3296395 100644 --- a/grub-core/bus/emu/pci.c +++ b/grub-core/bus/emu/pci.c @@ -32,7 +32,7 @@ grub_pci_make_address (grub_pci_device_t dev, int reg) } void -grub_pci_iterate (grub_pci_iteratefunc_t hook) +grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) { struct pci_device_iterator *iter; struct pci_slot_match slot; @@ -43,7 +43,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) slot.func = PCI_MATCH_ANY; iter = pci_slot_match_iterator_create (&slot); while ((dev = pci_device_next (iter))) - hook (dev, dev->vendor_id | (dev->device_id << 16)); + hook (dev, dev->vendor_id | (dev->device_id << 16), hook_data); pci_iterator_destroy (iter); } diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 17dea30a1..b388ce5c8 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -98,7 +98,7 @@ grub_pci_make_address (grub_pci_device_t dev, int reg) } void -grub_pci_iterate (grub_pci_iteratefunc_t hook) +grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) { grub_pci_device_t dev; grub_pci_address_t addr; @@ -125,7 +125,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) continue; } - if (hook (dev, id)) + if (hook (dev, id, hook_data)) return; /* Probe only func = 0 if the device if not multifunction */ diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c index b7005192b..b592f088c 100644 --- a/grub-core/bus/usb/ehci.c +++ b/grub-core/bus/usb/ehci.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -454,9 +455,9 @@ grub_ehci_reset (struct grub_ehci *e) } /* PCI iteration function... */ -static int NESTED_FUNC_ATTR -grub_ehci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) +static int +grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint8_t release; grub_uint32_t class_code; @@ -533,6 +534,11 @@ grub_ehci_pci_iter (grub_pci_device_t dev, "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n"); return 0; } + + /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word(addr, + GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr)); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n"); } @@ -664,7 +670,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); e->tdfree_virt = e->td_virt; /* Set Terminate in first QH, which is used in framelist */ - e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH); e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); e->qh_virt[0].td_overlay.alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); @@ -710,6 +716,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, usblegsup = grub_pci_read (pciaddr_eecp); if (usblegsup & GRUB_EHCI_BIOS_OWNED) { + grub_boot_time ("Taking ownership of EHCI controller"); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n"); /* Ownership change - set OS_OWNED bit */ @@ -730,11 +737,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); /* Ensure PCI register is written */ grub_pci_read (pciaddr_eecp); - /* Disable SMI. */ - pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); - grub_pci_write (pciaddr_eecp, 0); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); } } else if (usblegsup & GRUB_EHCI_OS_OWNED) @@ -750,12 +752,14 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); /* Ensure PCI register is written */ grub_pci_read (pciaddr_eecp); - /* Disable SMI, just to be sure. */ - pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); - grub_pci_write (pciaddr_eecp, 0); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); } + + /* Disable SMI, just to be sure. */ + pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); + grub_pci_write (pciaddr_eecp, 0); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + } grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n"); @@ -791,7 +795,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, /* Set ownership of root hub ports to EHCI */ grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG, GRUB_EHCI_CF_EHCI_OWNER); - /* Enable asynchronous list */ + /* Enable both lists */ grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, GRUB_EHCI_CMD_AS_ENABL | GRUB_EHCI_CMD_PS_ENABL @@ -865,7 +869,7 @@ fail: } static int -grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev)) +grub_ehci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { struct grub_ehci *e; struct grub_usb_controller dev; @@ -873,7 +877,7 @@ grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev)) for (e = ehci; e; e = e->next) { dev.data = e; - if (hook (&dev)) + if (hook (&dev, hook_data)) return 1; } @@ -935,9 +939,9 @@ grub_ehci_setup_qh (grub_ehci_qh_t qh, grub_usb_transfer_t transfer) * SplitCompletionMask - AFAIK it is ignored in asynchronous list, * InterruptScheduleMask - AFAIK it should be zero in async. list */ ep_cap |= GRUB_EHCI_MULT_THREE; - ep_cap |= (transfer->dev->port << GRUB_EHCI_DEVPORT_OFF) + ep_cap |= (transfer->dev->split_hubport << GRUB_EHCI_DEVPORT_OFF) & GRUB_EHCI_DEVPORT_MASK; - ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF) + ep_cap |= (transfer->dev->split_hubaddr << GRUB_EHCI_HUBADDR_OFF) & GRUB_EHCI_HUBADDR_MASK; if (transfer->dev->speed == GRUB_USB_SPEED_LOW && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) @@ -969,6 +973,10 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) int i; grub_ehci_qh_t qh = e->qh_virt; grub_ehci_qh_t head; + grub_uint32_t qh_phys; + grub_uint32_t qh_terminate = + GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH; + grub_ehci_qh_t qh_iter; /* Prepare part of EP Characteristic to find existing QH */ target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) | @@ -976,21 +984,58 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) target = grub_cpu_to_le32 (target); mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK); - /* First try to find existing QH with proper target */ - for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */ + /* low speed interrupt transfers are linked to the periodic */ + /* schedule, everything else to the asynchronous schedule */ + if (transfer->dev->speed == GRUB_USB_SPEED_LOW + && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) + head = &qh[0]; + else + head = &qh[1]; + + /* First try to find existing QH with proper target in proper list */ + qh_phys = grub_le_to_cpu32( head->qh_hptr ); + if (qh_phys != qh_terminate) + qh_iter = grub_dma_phys2virt ( qh_phys & GRUB_EHCI_QHTDPTR_MASK, + e->qh_chunk ); + else + qh_iter = NULL; + + for ( + i = 0; + (qh_phys != qh_terminate) && (qh_iter != NULL) && + (qh_iter != head) && (i < GRUB_EHCI_N_QH); + i++ ) { - if (!qh[i].ep_char) - break; /* Found first not-allocated QH, finish */ - if (target == (qh[i].ep_char & mask)) + if (target == (qh_iter->ep_char & mask)) { /* Found proper existing (and linked) QH, do setup of QH */ - grub_dprintf ("ehci", "find_qh: found, i=%d, QH=%p\n", - i, &qh[i]); - grub_ehci_setup_qh (&qh[i], transfer); - return &qh[i]; + grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter); + grub_ehci_setup_qh (qh_iter, transfer); + return qh_iter; } + + qh_phys = grub_le_to_cpu32( qh_iter->qh_hptr ); + if (qh_phys != qh_terminate) + qh_iter = grub_dma_phys2virt ( qh_phys & GRUB_EHCI_QHTDPTR_MASK, + e->qh_chunk ); + else + qh_iter = NULL; } - /* QH with target_addr does not exist, we have to add it */ + + /* variable "i" should be never equal to GRUB_EHCI_N_QH here */ + if (i >= GRUB_EHCI_N_QH) + { /* Something very bad happened in QH list(s) ! */ + grub_dprintf ("ehci", "find_qh: Mismatch in QH list! head=%p\n", + head); + } + + /* QH with target_addr does not exist, we have to find and add it */ + for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */ + { + if (!qh[i].ep_char) + break; /* Found first not-allocated QH, finish */ + } + /* Have we any free QH in array ? */ if (i >= GRUB_EHCI_N_QH) /* No. */ { @@ -1005,14 +1050,6 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) /* We should preset new QH and link it into AL */ grub_ehci_setup_qh (&qh[i], transfer); - /* low speed interrupt transfers are linked to the periodic - * scheudle, everything else to the asynchronous schedule */ - if (transfer->dev->speed == GRUB_USB_SPEED_LOW - && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) - head = &qh[0]; - else - head = &qh[1]; - /* Linking - this new (last) QH will copy the QH from the head QH */ qh[i].qh_hptr = head->qh_hptr; /* Linking - the head QH will point to this new QH */ @@ -1254,16 +1291,6 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, /* XXX: Fix it: Currently we don't do anything to restart EHCI */ return GRUB_USB_ERR_INTERNAL; - /* Check if transfer is not high speed and connected to root hub. - * It should not happened but... */ - if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH) - && !transfer->dev->hubaddr) - { - grub_error (GRUB_USB_ERR_BADDEVICE, - "FULL/LOW speed device on EHCI port!?!"); - return GRUB_USB_ERR_BADDEVICE; - } - /* Allocate memory for controller transfer data. */ cdata = grub_malloc (sizeof (*cdata)); if (!cdata) @@ -1540,17 +1567,20 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev, int i; grub_uint64_t maxtime; grub_uint32_t qh_phys; + grub_uint32_t interrupt = + cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK; /* QH can be active and should be de-activated and halted */ grub_dprintf ("ehci", "cancel_transfer: begin\n"); - /* First check if EHCI is running and AL is enabled and if not, - * there is no problem... */ - if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) - & GRUB_EHCI_ST_HC_HALTED) != 0) || - ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) - & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)) + /* First check if EHCI is running - if not, there is no problem */ + /* to cancel any transfer. Or, if transfer is asynchronous, check */ + /* if AL is enabled - if not, transfer can be canceled also. */ + if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & + GRUB_EHCI_ST_HC_HALTED) != 0) || + (!interrupt && ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & + (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0))) { grub_ehci_pre_finish_transfer (transfer); grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); @@ -1560,13 +1590,14 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev, return GRUB_USB_ERR_NONE; } - /* EHCI and AL are running. What to do? - * Try to Halt QH via de-scheduling QH. */ + /* EHCI and (AL or SL) are running. What to do? */ + /* Try to Halt QH via de-scheduling QH. */ /* Find index of previous QH */ qh_phys = grub_dma_virt2phys(cdata->qh_virt, e->qh_chunk); for (i = 0; i < GRUB_EHCI_N_QH; i++) { - if ((e->qh_virt[i].qh_hptr & GRUB_EHCI_QHTDPTR_MASK) == qh_phys) + if ((grub_le_to_cpu32(e->qh_virt[i].qh_hptr) + & GRUB_EHCI_QHTDPTR_MASK) == qh_phys) break; } if (i == GRUB_EHCI_N_QH) @@ -1620,24 +1651,12 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev, grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); grub_ehci_free_td (e, cdata->td_alt_virt); - /* FIXME Putting the QH back on the list should work, but for some - * strange reason doing that will affect other QHs on the periodic - * list. So free the QH instead of putting it back on the list - * which does seem to work, but I would like to know why. */ - -#if 0 - /* Finaly we should return QH back to the AL... */ - e->qh_virt[i].qh_hptr = - grub_cpu_to_le32 (grub_dma_virt2phys - (cdata->qh_virt, e->qh_chunk)); -#else - /* Free the QH */ + /* "Free" the QH - link it to itself */ cdata->qh_virt->ep_char = 0; cdata->qh_virt->qh_hptr = grub_cpu_to_le32 ((grub_dma_virt2phys (cdata->qh_virt, e->qh_chunk) & GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH); -#endif grub_free (cdata); @@ -1658,7 +1677,7 @@ grub_ehci_hubports (grub_usb_controller_t dev) return portinfo; } -static grub_err_t +static grub_usb_err_t grub_ehci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -1680,18 +1699,20 @@ grub_ehci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "portstatus: EHCI Timed out - disable"); + return GRUB_USB_ERR_TIMEOUT; if (!enable) /* We don't need reset port */ { grub_dprintf ("ehci", "portstatus: Disabled.\n"); grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n", grub_ehci_port_read (e, port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } grub_dprintf ("ehci", "portstatus: enable\n"); + grub_boot_time ("Resetting port %d", port); + /* Now we will do reset - if HIGH speed device connected, it will * result in Enabled state, otherwise port remains disabled. */ /* Set RESET bit for 50ms */ @@ -1703,8 +1724,8 @@ grub_ehci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_RESET) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, - "portstatus: EHCI Timed out - reset port"); + return GRUB_USB_ERR_TIMEOUT; + grub_boot_time ("Port %d reset", port); /* Remember "we did the reset" - needed by detect_dev */ e->reset |= (1 << port); /* Test if port enabled, i.e. HIGH speed device connected */ @@ -1731,7 +1752,7 @@ grub_ehci_portstatus (grub_usb_controller_t dev, grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n", grub_ehci_port_read (e, port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static grub_usb_speed_t @@ -1810,7 +1831,7 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed) static void grub_ehci_inithw (void) { - grub_pci_iterate (grub_ehci_pci_iter); + grub_pci_iterate (grub_ehci_pci_iter, NULL); } static grub_err_t @@ -1866,7 +1887,7 @@ grub_ehci_restore_hw (void) } } - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static grub_err_t @@ -1877,16 +1898,19 @@ grub_ehci_fini_hw (int noreturn __attribute__ ((unused))) /* We should disable all EHCI HW to prevent any DMA access etc. */ for (e = ehci; e; e = e->next) { + /* Disable both lists */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + ~(GRUB_EHCI_CMD_AS_ENABL | GRUB_EHCI_CMD_PS_ENABL) + & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + /* Check if EHCI is halted and halt it if not */ - if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE) - grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout"); + grub_ehci_halt (e); /* Reset EHCI */ - if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE) - grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout"); + grub_ehci_reset (e); } - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static struct grub_usb_controller_dev usb_controller = { @@ -1897,15 +1921,23 @@ static struct grub_usb_controller_dev usb_controller = { .cancel_transfer = grub_ehci_cancel_transfer, .hubports = grub_ehci_hubports, .portstatus = grub_ehci_portstatus, - .detect_dev = grub_ehci_detect_dev + .detect_dev = grub_ehci_detect_dev, + /* estimated max. count of TDs for one bulk transfer */ + .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4 }; GRUB_MOD_INIT (ehci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64); COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96); + + grub_stop_disk_firmware (); + + grub_boot_time ("Initing EHCI hardware"); grub_ehci_inithw (); + grub_boot_time ("Registering EHCI driver"); grub_usb_controller_dev_register (&usb_controller); + grub_boot_time ("EHCI driver registered"); grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } diff --git a/grub-core/bus/usb/emu/usb.c b/grub-core/bus/usb/emu/usb.c index 38c5f01f1..3ad2fc312 100644 --- a/grub-core/bus/usb/emu/usb.c +++ b/grub-core/bus/usb/emu/usb.c @@ -88,7 +88,7 @@ grub_usb_poll_devices (void) int -grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) +grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) { int i; @@ -96,7 +96,7 @@ grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) { if (grub_usb_devs[i]) { - if (hook (grub_usb_devs[i])) + if (hook (grub_usb_devs[i], hook_data)) return 1; } } diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 23cf63187..a173e4056 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -213,9 +214,9 @@ grub_ohci_writereg32 (struct grub_ohci *o, /* Iterate over all PCI devices. Determine if a device is an OHCI controller. If this is the case, initialize it. */ -static int NESTED_FUNC_ATTR -grub_ohci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid) +static int +grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t interf; grub_uint32_t base; @@ -270,6 +271,11 @@ grub_ohci_pci_iter (grub_pci_device_t dev, return 0; #endif + /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word(addr, + GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr)); + grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n", class, subclass, interf); } @@ -472,13 +478,13 @@ grub_ohci_pci_iter (grub_pci_device_t dev, static void grub_ohci_inithw (void) { - grub_pci_iterate (grub_ohci_pci_iter); + grub_pci_iterate (grub_ohci_pci_iter, NULL); } static int -grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) +grub_ohci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { struct grub_ohci *o; struct grub_usb_controller dev; @@ -486,7 +492,7 @@ grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) for (o = ohci; o; o = o->next) { dev.data = o; - if (hook (&dev)) + if (hook (&dev, hook_data)) return 1; } @@ -1210,7 +1216,7 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev, return GRUB_USB_ERR_NONE; } -static grub_err_t +static grub_usb_err_t grub_ohci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -1230,11 +1236,11 @@ grub_ohci_portstatus (grub_usb_controller_t dev, while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "OHCI Timed out - disable"); + return GRUB_USB_ERR_TIMEOUT; grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } /* OHCI does one reset signal 10ms long but USB spec. @@ -1251,7 +1257,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE)) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset"); + return GRUB_USB_ERR_TIMEOUT; /* End the reset signaling - reset the reset status change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, @@ -1269,7 +1275,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable"); + return GRUB_USB_ERR_TIMEOUT; /* Reset bit Connect Status Change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, @@ -1281,7 +1287,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static grub_usb_speed_t @@ -1426,7 +1432,9 @@ static struct grub_usb_controller_dev usb_controller = .cancel_transfer = grub_ohci_cancel_transfer, .hubports = grub_ohci_hubports, .portstatus = grub_ohci_portstatus, - .detect_dev = grub_ohci_detect_dev + .detect_dev = grub_ohci_detect_dev, + /* estimated max. count of TDs for one bulk transfer */ + .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4 }; static struct grub_preboot *fini_hnd; @@ -1435,6 +1443,9 @@ GRUB_MOD_INIT(ohci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32); COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16); + + grub_stop_disk_firmware (); + grub_ohci_inithw (); grub_usb_controller_dev_register (&usb_controller); fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw, diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c index 55d1884cc..8e94c7dc0 100644 --- a/grub-core/bus/usb/serial/common.c +++ b/grub-core/bus/usb/serial/common.c @@ -42,7 +42,8 @@ static int usbnum = 0; int grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, - struct grub_serial_driver *driver) + struct grub_serial_driver *driver, int in_endp, + int out_endp) { struct grub_serial_port *port; int j; @@ -51,7 +52,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, interf = usbdev->config[configno].interf[interfno].descif; - port = grub_malloc (sizeof (*port)); + port = grub_zalloc (sizeof (*port)); if (!port) { grub_print_error (); @@ -73,12 +74,16 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, struct grub_usb_desc_endp *endp; endp = &usbdev->config[0].interf[interfno].descendp[j]; - if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) + if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2 + && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING + || in_endp == endp->endp_addr)) { /* Bulk IN endpoint. */ port->in_endp = endp; } - else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) + else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2 + && (out_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING + || out_endp == endp->endp_addr)) { /* Bulk OUT endpoint. */ port->out_endp = endp; @@ -119,7 +124,7 @@ grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size) if (port->bufstart < port->bufend) return port->buf[port->bufstart++]; - err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp->endp_addr, + err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp, sizeof (port->buf), port->buf, 10, &actual); if (err != GRUB_USB_ERR_NONE) diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c index 15ea8fb89..1a99cba17 100644 --- a/grub-core/bus/usb/serial/ftdi.c +++ b/grub-core/bus/usb/serial/ftdi.c @@ -91,11 +91,13 @@ real_config (struct grub_serial_port *port) grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, GRUB_FTDI_MODEM_CTRL, - GRUB_FTDI_MODEM_CTRL_DTRRTS, 0, 0, 0); + port->config.rtscts ? GRUB_FTDI_MODEM_CTRL_DTRRTS : 0, + 0, 0, 0); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, GRUB_FTDI_FLOW_CTRL, - GRUB_FTDI_FLOW_CTRL_DTRRTS, 0, 0, 0); + port->config.rtscts ? GRUB_FTDI_FLOW_CTRL_DTRRTS : 0, + 0, 0, 0); divisor = get_divisor (port->config.speed); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, @@ -128,7 +130,7 @@ ftdi_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); } static grub_err_t @@ -193,7 +195,9 @@ grub_ftdi_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; return grub_usbserial_attach (usbdev, configno, interfno, - &grub_ftdi_driver); + &grub_ftdi_driver, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); } static struct grub_usb_attach_desc attach_hook = diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c index 5433763e5..08095622a 100644 --- a/grub-core/bus/usb/serial/pl2303.c +++ b/grub-core/bus/usb/serial/pl2303.c @@ -125,7 +125,7 @@ real_config (struct grub_serial_port *port) 0x22, 3, 0, 0, 0); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, - 1, 0, 0x61, 0, 0); + 1, 0, port->config.rtscts ? 0x61 : 0, 0, 0); port->configured = 1; } @@ -146,7 +146,7 @@ pl2303_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); } static grub_err_t @@ -208,7 +208,9 @@ grub_pl2303_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; return grub_usbserial_attach (usbdev, configno, interfno, - &grub_pl2303_driver); + &grub_pl2303_driver, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); } static struct grub_usb_attach_desc attach_hook = diff --git a/grub-core/bus/usb/serial/usbdebug_late.c b/grub-core/bus/usb/serial/usbdebug_late.c new file mode 100644 index 000000000..e88ba130e --- /dev/null +++ b/grub-core/bus/usb/serial/usbdebug_late.c @@ -0,0 +1,93 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +/* Fetch a key. */ +static int +usbdebug_late_hw_fetch (struct grub_serial_port *port) +{ + return grub_usbserial_fetch (port, 0); +} + +/* Put a character. */ +static void +usbdebug_late_hw_put (struct grub_serial_port *port, const int c) +{ + char cc = c; + + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); +} + +static grub_err_t +usbdebug_late_hw_configure (struct grub_serial_port *port __attribute__ ((unused)), + struct grub_serial_config *config __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + +static struct grub_serial_driver grub_usbdebug_late_driver = + { + .configure = usbdebug_late_hw_configure, + .fetch = usbdebug_late_hw_fetch, + .put = usbdebug_late_hw_put, + .fini = grub_usbserial_fini + }; + +static int +grub_usbdebug_late_attach (grub_usb_device_t usbdev, int configno, int interfno) +{ + grub_usb_err_t err; + struct grub_usb_desc_debug debugdesc; + + err = grub_usb_get_descriptor (usbdev, GRUB_USB_DESCRIPTOR_DEBUG, configno, + sizeof (debugdesc), (char *) &debugdesc); + if (err) + return 0; + + return grub_usbserial_attach (usbdev, configno, interfno, + &grub_usbdebug_late_driver, + debugdesc.in_endp, debugdesc.out_endp); +} + +static struct grub_usb_attach_desc attach_hook = +{ + .class = 0xff, + .hook = grub_usbdebug_late_attach +}; + +GRUB_MOD_INIT(usbserial_usbdebug_late) +{ + grub_usb_register_attach_hook_class (&attach_hook); +} + +GRUB_MOD_FINI(usbserial_usbdebug_late) +{ + grub_serial_unregister_driver (&grub_usbdebug_late_driver); + grub_usb_unregister_attach_hook_class (&attach_hook); +} diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 8f60850de..0fb9365be 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -44,12 +45,22 @@ typedef enum GRUB_UHCI_REG_USBLEGSUP = 0xc0 } grub_uhci_reg_t; +enum + { + GRUB_UHCI_DETECT_CHANGED = (1 << 1), + GRUB_UHCI_DETECT_HAVE_DEVICE = 1, + GRUB_UHCI_DETECT_LOW_SPEED = (1 << 8) + }; + /* R/WC legacy support bits */ -#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15) -#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11) -#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10) -#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9) -#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8) +enum + { + GRUB_UHCI_LEGSUP_END_A20GATE = (1 << 15), + GRUB_UHCI_TRAP_BY_64H_WSTAT = (1 << 11), + GRUB_UHCI_TRAP_BY_64H_RSTAT = (1 << 10), + GRUB_UHCI_TRAP_BY_60H_WSTAT = (1 << 9), + GRUB_UHCI_TRAP_BY_60H_RSTAT = (1 << 8) + }; /* Reset all legacy support - clear all R/WC bits and all R/W bits */ #define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \ @@ -125,7 +136,7 @@ typedef volatile struct grub_uhci_qh *grub_uhci_qh_t; struct grub_uhci { - int iobase; + grub_port_t iobase; volatile grub_uint32_t *framelist_virt; grub_uint32_t framelist_phys; struct grub_pci_dma_chunk *framelist_chunk; @@ -178,16 +189,12 @@ grub_uhci_writereg32 (struct grub_uhci *u, grub_outl (val, u->iobase + reg); } -static grub_err_t -grub_uhci_portstatus (grub_usb_controller_t dev, - unsigned int port, unsigned int enable); - - /* Iterate over all PCI devices. Determine if a device is an UHCI controller. If this is the case, initialize it. */ -static int NESTED_FUNC_ATTR +static int grub_uhci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused))) + grub_pci_id_t pciid __attribute__((unused)), + void *data __attribute__ ((unused))) { grub_uint32_t class_code; grub_uint32_t class; @@ -212,22 +219,28 @@ grub_uhci_pci_iter (grub_pci_device_t dev, /* Set bus master - needed for coreboot or broken BIOSes */ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word(addr, - GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr)); + grub_pci_write_word(addr, GRUB_PCI_COMMAND_IO_ENABLED + | GRUB_PCI_COMMAND_BUS_MASTER + | grub_pci_read_word (addr)); /* Determine IO base address. */ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4); base = grub_pci_read (addr); /* Stop if there is no IO space base address defined. */ - if (! (base & 1)) + if ((base & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO) return 0; + if ((base & GRUB_UHCI_IOMASK) == 0) + return 0; + + grub_dprintf ("uhci", "base = %x\n", base); + /* Allocate memory for the controller and register it. */ u = grub_zalloc (sizeof (*u)); if (! u) return 1; - u->iobase = base & GRUB_UHCI_IOMASK; + u->iobase = (base & GRUB_UHCI_IOMASK) + GRUB_MACHINE_PCI_IO_BASE; /* Reset PIRQ and SMI */ addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP); @@ -351,7 +364,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, static void grub_uhci_inithw (void) { - grub_pci_iterate (grub_uhci_pci_iter); + grub_pci_iterate (grub_uhci_pci_iter, NULL); } static grub_uhci_td_t @@ -391,6 +404,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, { grub_uhci_td_t tdprev; + grub_dprintf ("uhci", "Freeing %p\n", td); /* Check state of TD and possibly set last_trans */ if (transfer && (td->linkptr & 1)) transfer->last_trans = i; @@ -399,7 +413,10 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, /* Unlink the queue. */ tdprev = td; - td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); + if (!td->linkptr2) + td = 0; + else + td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); /* Free the TD. */ grub_free_td (u, tdprev); @@ -582,10 +599,17 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, *actual = 0; - errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); + if (cdata->qh->elinkptr & ~0x0f) + errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); + else + errtd = 0; - grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", - errtd->ctrl_status, errtd->buffer & (~15), errtd); + if (errtd) + { + grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p, %x\n", + errtd->ctrl_status, errtd->buffer & (~15), errtd, + cdata->qh->elinkptr); + } /* Check if the transaction completed. */ if (cdata->qh->elinkptr & 1) @@ -671,7 +695,7 @@ grub_uhci_cancel_transfer (grub_usb_controller_t dev, } static int -grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev)) +grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { struct grub_uhci *u; struct grub_usb_controller dev; @@ -679,14 +703,14 @@ grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev)) for (u = uhci; u; u = u->next) { dev.data = u; - if (hook (&dev)) + if (hook (&dev, hook_data)) return 1; } return 0; } -static grub_err_t +static grub_usb_err_t grub_uhci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -704,8 +728,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, else if (port == 1) reg = GRUB_UHCI_REG_PORTSC2; else - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "UHCI Root Hub port does not exist"); + return GRUB_USB_ERR_INTERNAL; status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", "detect=0x%02x\n", status); @@ -718,11 +741,11 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while ((grub_uhci_readreg16 (u, reg) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable"); + return GRUB_USB_ERR_TIMEOUT; status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", ">3detect=0x%02x\n", status); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } /* Reset the port. */ @@ -753,7 +776,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable"); + return GRUB_USB_ERR_TIMEOUT; /* Reset recovery time */ grub_millisleep (10); @@ -763,7 +786,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, grub_dprintf ("uhci", ">3detect=0x%02x\n", status); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static grub_usb_speed_t @@ -787,7 +810,7 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port); /* Connect Status Change bit - it detects change of connection */ - if (status & (1 << 1)) + if (status & GRUB_UHCI_DETECT_CHANGED) { *changed = 1; /* Reset bit Connect Status Change */ @@ -797,9 +820,9 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) else *changed = 0; - if (! (status & 1)) + if (! (status & GRUB_UHCI_DETECT_HAVE_DEVICE)) return GRUB_USB_SPEED_NONE; - else if (status & (1 << 8)) + else if (status & GRUB_UHCI_DETECT_LOW_SPEED) return GRUB_USB_SPEED_LOW; else return GRUB_USB_SPEED_FULL; @@ -822,11 +845,15 @@ static struct grub_usb_controller_dev usb_controller = .cancel_transfer = grub_uhci_cancel_transfer, .hubports = grub_uhci_hubports, .portstatus = grub_uhci_portstatus, - .detect_dev = grub_uhci_detect_dev + .detect_dev = grub_uhci_detect_dev, + /* estimated max. count of TDs for one bulk transfer */ + .max_bulk_tds = N_TD * 3 / 4 }; GRUB_MOD_INIT(uhci) { + grub_stop_disk_firmware (); + grub_uhci_inithw (); grub_usb_controller_dev_register (&usb_controller); grub_dprintf ("uhci", "registered\n"); diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index fb04e6572..8da5e4c74 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -26,67 +26,44 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_usb_controller_dev_t grub_usb_list; static struct grub_usb_attach_desc *attach_hooks; -void -grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) -{ - auto int iterate_hook (grub_usb_controller_t dev); - - /* Iterate over all controllers found by the driver. */ - int iterate_hook (grub_usb_controller_t dev) - { - dev->dev = usb; - - /* Enable the ports of the USB Root Hub. */ - grub_usb_root_hub (dev); - - return 0; - } - - usb->next = grub_usb_list; - grub_usb_list = usb; - - if (usb->iterate) - usb->iterate (iterate_hook); -} - -void -grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) -{ - grub_usb_controller_dev_t *p, q; - - for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next) - if (q == usb) - { - *p = q->next; - break; - } -} - #if 0 -int -grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev)) +/* Context for grub_usb_controller_iterate. */ +struct grub_usb_controller_iterate_ctx { + grub_usb_controller_iterate_hook_t hook; + void *hook_data; grub_usb_controller_dev_t p; +}; - auto int iterate_hook (grub_usb_controller_t dev); +/* Helper for grub_usb_controller_iterate. */ +static int +grub_usb_controller_iterate_iter (grub_usb_controller_t dev, void *data) +{ + struct grub_usb_controller_iterate_ctx *ctx = data; - int iterate_hook (grub_usb_controller_t dev) - { - dev->dev = p; - if (hook (dev)) - return 1; - return 0; - } + dev->dev = ctx->p; + if (ctx->hook (dev, ctx->hook_data)) + return 1; + return 0; +} + +int +grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook, + void *hook_data) +{ + struct grub_usb_controller_iterate_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; /* Iterate over all controller drivers. */ - for (p = grub_usb_list; p; p = p->next) + for (ctx.p = grub_usb_list; ctx.p; ctx.p = ctx.p->next) { /* Iterate over the busses of the controllers. XXX: Actually, a hub driver should do this. */ - if (p->iterate (iterate_hook)) + if (ctx.p->iterate (grub_usb_controller_iterate_iter, &ctx)) return 1; } @@ -132,31 +109,6 @@ grub_usb_get_descriptor (grub_usb_device_t dev, 0, size, data); } -struct grub_usb_desc_endp * -grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr) -{ - int i; - - for (i = 0; i < usbdev->config[0].descconf->numif; i++) - { - struct grub_usb_desc_if *interf; - int j; - - interf = usbdev->config[0].interf[i].descif; - - for (j = 0; j < interf->endpointcnt; j++) - { - struct grub_usb_desc_endp *endp; - endp = &usbdev->config[0].interf[i].descendp[j]; - - if (endp->endp_addr == addr) - return endp; - } - } - - return NULL; -} - grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev) { @@ -196,6 +148,7 @@ grub_usb_device_initialize (grub_usb_device_t dev) int pos; int currif; char *data; + struct grub_usb_desc *desc; /* First just read the first 4 bytes of the configuration descriptor, after that it is known how many bytes really have @@ -222,18 +175,35 @@ grub_usb_device_initialize (grub_usb_device_t dev) /* Read all interfaces. */ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) { - while (pos < config.totallen - && ((struct grub_usb_desc *)&data[pos])->type - != GRUB_USB_DESCRIPTOR_INTERFACE) - pos += ((struct grub_usb_desc *)&data[pos])->length; + while (pos < config.totallen) + { + desc = (struct grub_usb_desc *)&data[pos]; + if (desc->type == GRUB_USB_DESCRIPTOR_INTERFACE) + break; + if (!desc->length) + { + err = GRUB_USB_ERR_BADDEVICE; + goto fail; + } + pos += desc->length; + } + dev->config[i].interf[currif].descif = (struct grub_usb_desc_if *) &data[pos]; pos += dev->config[i].interf[currif].descif->length; - while (pos < config.totallen - && ((struct grub_usb_desc *)&data[pos])->type - != GRUB_USB_DESCRIPTOR_ENDPOINT) - pos += ((struct grub_usb_desc *)&data[pos])->length; + while (pos < config.totallen) + { + desc = (struct grub_usb_desc *)&data[pos]; + if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT) + break; + if (!desc->length) + { + err = GRUB_USB_ERR_BADDEVICE; + goto fail; + } + pos += desc->length; + } /* Point to the first endpoint. */ dev->config[i].interf[currif].descendp @@ -272,8 +242,13 @@ void grub_usb_device_attach (grub_usb_device_t dev) continue; for (desc = attach_hooks; desc; desc = desc->next) - if (interf->class == desc->class && desc->hook (dev, 0, i)) - dev->config[0].interf[i].attached = 1; + if (interf->class == desc->class) + { + grub_boot_time ("Probing USB device driver class %x", desc->class); + if (desc->hook (dev, 0, i)) + dev->config[0].interf[i].attached = 1; + grub_boot_time ("Probed USB device driver class %x", desc->class); + } if (dev->config[0].interf[i].attached) continue; @@ -282,59 +257,66 @@ void grub_usb_device_attach (grub_usb_device_t dev) { case GRUB_USB_CLASS_MASS_STORAGE: grub_dl_load ("usbms"); + grub_print_error (); break; case GRUB_USB_CLASS_HID: grub_dl_load ("usb_keyboard"); + grub_print_error (); break; case 0xff: /* FIXME: don't load useless modules. */ grub_dl_load ("usbserial_ftdi"); + grub_print_error (); grub_dl_load ("usbserial_pl2303"); + grub_print_error (); + grub_dl_load ("usbserial_usbdebug"); + grub_print_error (); break; } } } +/* Helper for grub_usb_register_attach_hook_class. */ +static int +grub_usb_register_attach_hook_class_iter (grub_usb_device_t usbdev, void *data) +{ + struct grub_usb_attach_desc *desc = data; + struct grub_usb_desc_device *descdev = &usbdev->descdev; + int i; + + if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0 + || descdev->configcnt == 0) + return 0; + + /* XXX: Just check configuration 0 for now. */ + for (i = 0; i < usbdev->config[0].descconf->numif; i++) + { + struct grub_usb_desc_if *interf; + + interf = usbdev->config[0].interf[i].descif; + + grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n", + i, interf->class, interf->subclass, interf->protocol); + + if (usbdev->config[0].interf[i].attached) + continue; + + if (interf->class != desc->class) + continue; + if (desc->hook (usbdev, 0, i)) + usbdev->config[0].interf[i].attached = 1; + } + + return 0; +} + void grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc) { - auto int usb_iterate (grub_usb_device_t dev); - - int usb_iterate (grub_usb_device_t usbdev) - { - struct grub_usb_desc_device *descdev = &usbdev->descdev; - int i; - - if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0 - || descdev->configcnt == 0) - return 0; - - /* XXX: Just check configuration 0 for now. */ - for (i = 0; i < usbdev->config[0].descconf->numif; i++) - { - struct grub_usb_desc_if *interf; - - interf = usbdev->config[0].interf[i].descif; - - grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n", - i, interf->class, interf->subclass, interf->protocol); - - if (usbdev->config[0].interf[i].attached) - continue; - - if (interf->class != desc->class) - continue; - if (desc->hook (usbdev, 0, i)) - usbdev->config[0].interf[i].attached = 1; - } - - return 0; - } - desc->next = attach_hooks; attach_hooks = desc; - grub_usb_iterate (usb_iterate); + grub_usb_iterate (grub_usb_register_attach_hook_class_iter, desc); } void diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index 5fc5eba39..34a7ff1b5 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -29,6 +29,7 @@ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; static int rescan = 0; +static int npending = 0; struct grub_usb_hub { @@ -36,30 +37,34 @@ struct grub_usb_hub grub_usb_controller_t controller; int nports; struct grub_usb_device **devices; + struct grub_usb_hub_port *ports; grub_usb_device_t dev; }; static struct grub_usb_hub *hubs; +static grub_usb_controller_dev_t grub_usb_list; /* Add a device that currently has device number 0 and resides on CONTROLLER, the Hub reported that the device speed is SPEED. */ static grub_usb_device_t grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed, - int port, int hubaddr) + int split_hubport, int split_hubaddr) { grub_usb_device_t dev; int i; grub_usb_err_t err; + grub_boot_time ("Attaching USB device"); + dev = grub_zalloc (sizeof (struct grub_usb_device)); if (! dev) return NULL; dev->controller = *controller; dev->speed = speed; - dev->port = port; - dev->hubaddr = hubaddr; + dev->split_hubport = split_hubport; + dev->split_hubaddr = split_hubaddr; err = grub_usb_device_initialize (dev); if (err) @@ -103,13 +108,17 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_dprintf ("usb", "Added new usb device: %p, addr=%d\n", dev, i); - grub_dprintf ("usb", "speed=%d, port=%d, hubaddr=%d\n", - speed, port, hubaddr); + grub_dprintf ("usb", "speed=%d, split_hubport=%d, split_hubaddr=%d\n", + speed, split_hubport, split_hubaddr); /* Wait "recovery interval", spec. says 2ms */ grub_millisleep (2); + + grub_boot_time ("Probing USB device driver"); grub_usb_device_attach (dev); + + grub_boot_time ("Attached USB device"); return dev; } @@ -139,10 +148,15 @@ grub_usb_add_hub (grub_usb_device_t dev) grub_dprintf ("usb", "Hub set configuration\n"); grub_usb_set_configuration (dev, 1); - dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); - if (!dev->children) - return GRUB_USB_ERR_INTERNAL; dev->nports = hubdesc.portcnt; + dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); + dev->ports = grub_zalloc (dev->nports * sizeof (dev->ports[0])); + if (!dev->children || !dev->ports) + { + grub_free (dev->children); + grub_free (dev->ports); + return GRUB_USB_ERR_INTERNAL; + } /* Power on all Hub ports. */ for (i = 1; i <= hubdesc.portcnt; i++) @@ -173,7 +187,7 @@ grub_usb_add_hub (grub_usb_device_t dev) if (len > sizeof (dev->statuschange)) len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, endp->endp_addr, len, + = grub_usb_bulk_read_background (dev, endp, len, (char *) &dev->statuschange); break; } @@ -181,7 +195,7 @@ grub_usb_add_hub (grub_usb_device_t dev) rescan = 1; - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static void @@ -189,48 +203,30 @@ attach_root_port (struct grub_usb_hub *hub, int portno, grub_usb_speed_t speed) { grub_usb_device_t dev; - grub_err_t err; - int total, i; - grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; - int changed=0; + grub_usb_err_t err; -#if 0 -/* Specification does not say about disabling of port when device - * connected. If disabling is really necessary for some devices, - * delete this #if 0 and related #endif */ - /* Disable the port. XXX: Why? */ - err = hub->controller->dev->portstatus (hub->controller, portno, 0); - if (err) - return; -#endif - /* Wait for completion of insertion and stable power (USB spec.) - * Should be at least 100ms, some devices requires more... - * There is also another thing - some devices have worse contacts - * and connected signal is unstable for some time - we should handle - * it - but prevent deadlock in case when device is too faulty... */ - for (total = i = 0; (i < 250) && (total < 2000); i++, total++) - { - grub_millisleep (1); - current_speed = hub->controller->dev->detect_dev - (hub->controller, portno, &changed); - if (current_speed == GRUB_USB_SPEED_NONE) - i = 0; - } - grub_dprintf ("usb", "total=%d\n", total); - if (total >= 2000) - return; + grub_boot_time ("After detect_dev"); /* Enable the port. */ err = hub->controller->dev->portstatus (hub->controller, portno, 1); if (err) return; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; + npending++; grub_millisleep (10); + grub_boot_time ("Port enabled"); + /* Enable the port and create a device. */ - dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); + /* High speed device needs not transaction translation + and full/low speed device cannot be connected to EHCI root hub + and full/low speed device connected to OHCI/UHCI needs not + transaction translation - e.g. hubport and hubaddr should be + always none (zero) for any device connected to any root hub. */ + dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0); hub->controller->dev->pending_reset = 0; + npending--; if (! dev) return; @@ -239,14 +235,20 @@ attach_root_port (struct grub_usb_hub *hub, int portno, /* If the device is a Hub, scan it for more devices. */ if (dev->descdev.class == 0x09) grub_usb_add_hub (dev); + + grub_boot_time ("Attached root port"); } -grub_usb_err_t -grub_usb_root_hub (grub_usb_controller_t controller) +/* Iterate over all controllers found by the driver. */ +static int +grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *data) { - int i; + grub_usb_controller_dev_t usb = data; struct grub_usb_hub *hub; - int changed=0; + + controller->dev = usb; + + grub_boot_time ("Registering USB root hub"); hub = grub_malloc (sizeof (*hub)); if (!hub) @@ -267,27 +269,122 @@ grub_usb_root_hub (grub_usb_controller_t controller) /* Query the number of ports the root Hub has. */ hub->nports = controller->dev->hubports (controller); hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports); - if (!hub->devices) + hub->ports = grub_zalloc (sizeof (hub->ports[0]) * hub->nports); + if (!hub->devices || !hub->ports) { + grub_free (hub->devices); + grub_free (hub->ports); grub_free (hub->controller); grub_free (hub); - return GRUB_USB_ERR_INTERNAL; + grub_print_error (); + return 0; } - for (i = 0; i < hub->nports; i++) + return 0; +} + +void +grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) +{ + grub_usb_controller_dev_t *p, q; + + for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next) + if (q == usb) + { + *p = q->next; + break; + } +} + +void +grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) +{ + int portno; + int continue_waiting = 0; + struct grub_usb_hub *hub; + + usb->next = grub_usb_list; + grub_usb_list = usb; + + if (usb->iterate) + usb->iterate (grub_usb_controller_dev_register_iter, usb); + + grub_boot_time ("waiting for stable power on USB root\n"); + + while (1) { - grub_usb_speed_t speed; - if (!controller->dev->pending_reset) - { - speed = controller->dev->detect_dev (hub->controller, i, - &changed); + for (hub = hubs; hub; hub = hub->next) + if (hub->controller->dev == usb) + { + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (portno = 0; portno < hub->nports; portno++) + { + grub_usb_speed_t speed; + int changed = 0; - if (speed != GRUB_USB_SPEED_NONE) - attach_root_port (hub, i, speed); - } + speed = hub->controller->dev->detect_dev (hub->controller, portno, + &changed); + + if (hub->ports[portno].state == PORT_STATE_NORMAL + && speed != GRUB_USB_SPEED_NONE) + { + hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250; + hub->ports[portno].hard_limit_time = hub->ports[portno].soft_limit_time + 1750; + hub->ports[portno].state = PORT_STATE_WAITING_FOR_STABLE_POWER; + grub_boot_time ("Scheduling stable power wait for port %p:%d", + usb, portno); + continue_waiting++; + continue; + } + + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && speed == GRUB_USB_SPEED_NONE) + { + hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250; + continue; + } + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && grub_get_time_ms () > hub->ports[portno].soft_limit_time) + { + hub->ports[portno].state = PORT_STATE_STABLE_POWER; + grub_boot_time ("Got stable power wait for port %p:%d", + usb, portno); + continue_waiting--; + continue; + } + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && grub_get_time_ms () > hub->ports[portno].hard_limit_time) + { + hub->ports[portno].state = PORT_STATE_FAILED_DEVICE; + continue_waiting--; + continue; + } + } + } + if (!continue_waiting) + break; + grub_millisleep (1); } - return GRUB_USB_ERR_NONE; + grub_boot_time ("After the stable power wait on USB root"); + + for (hub = hubs; hub; hub = hub->next) + if (hub->controller->dev == usb) + for (portno = 0; portno < hub->nports; portno++) + if (hub->ports[portno].state == PORT_STATE_STABLE_POWER) + { + grub_usb_speed_t speed; + int changed = 0; + hub->ports[portno].state = PORT_STATE_NORMAL; + speed = hub->controller->dev->detect_dev (hub->controller, portno, &changed); + attach_root_port (hub, portno, speed); + } + + grub_boot_time ("USB root hub registered"); } static void detach_device (grub_usb_device_t dev); @@ -319,14 +416,78 @@ detach_device (grub_usb_device_t dev) grub_usb_devs[dev->addr] = 0; } +static int +wait_power_nonroot_hub (grub_usb_device_t dev) +{ + grub_usb_err_t err; + int continue_waiting = 0; + unsigned i; + + for (i = 1; i <= dev->nports; i++) + if (dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) + { + grub_uint64_t tm; + grub_uint32_t current_status = 0; + + /* Get the port status. */ + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_GET_STATUS, + 0, i, + sizeof (current_status), + (char *) ¤t_status); + if (err) + { + dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE; + continue; + } + tm = grub_get_time_ms (); + if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) + dev->ports[i - 1].soft_limit_time = tm + 250; + if (tm >= dev->ports[i - 1].soft_limit_time) + { + if (dev->controller.dev->pending_reset) + continue; + /* Now do reset of port. */ + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_RESET, + i, 0, 0); + dev->ports[i - 1].state = PORT_STATE_NORMAL; + grub_boot_time ("Resetting port %p:%d", dev, i - 1); + + rescan = 1; + /* We cannot reset more than one device at the same time ! + * Resetting more devices together results in very bad + * situation: more than one device has default address 0 + * at the same time !!! + * Additionaly, we cannot perform another reset + * anywhere on the same OHCI controller until + * we will finish addressing of reseted device ! */ + dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + npending++; + continue; + } + if (tm >= dev->ports[i - 1].hard_limit_time) + { + dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE; + continue; + } + continue_waiting = 1; + } + return continue_waiting && dev->controller.dev->pending_reset == 0; +} + static void poll_nonroot_hub (grub_usb_device_t dev) { grub_usb_err_t err; unsigned i; - grub_uint8_t changed; + grub_uint32_t changed; grub_size_t actual, len; - int j, total; if (!dev->hub_transfer) return; @@ -342,7 +503,7 @@ poll_nonroot_hub (grub_usb_device_t dev) if (len > sizeof (dev->statuschange)) len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len, + = grub_usb_bulk_read_background (dev, dev->hub_endpoint, len, (char *) &dev->statuschange); if (err || actual == 0 || changed == 0) @@ -352,9 +513,9 @@ poll_nonroot_hub (grub_usb_device_t dev) for (i = 1; i <= dev->nports; i++) { grub_uint32_t status; - grub_uint32_t current_status = 0; - if (!(changed & (1 << i))) + if (!(changed & (1 << i)) + || dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) continue; /* Get the port status. */ @@ -407,52 +568,19 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Connected and status of connection changed ? */ if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { + grub_boot_time ("Before the stable power wait portno=%d", i); /* A device is actually connected to this port. */ - /* Wait for completion of insertion and stable power (USB spec.) - * Should be at least 100ms, some devices requires more... - * There is also another thing - some devices have worse contacts - * and connected signal is unstable for some time - we should handle - * it - but prevent deadlock in case when device is too faulty... */ - for (total = j = 0; (j < 250) && (total < 2000); j++, total++) - { - grub_millisleep (1); - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, - sizeof (current_status), - (char *) ¤t_status); - if (err) - { - total = 2000; - break; - } - if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) - j = 0; - } - grub_dprintf ("usb", "(non-root) total=%d\n", total); - if (total >= 2000) - continue; - - /* Now do reset of port. */ - grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - rescan = 1; - /* We cannot reset more than one device at the same time ! - * Resetting more devices together results in very bad - * situation: more than one device has default address 0 - * at the same time !!! - * Additionaly, we cannot perform another reset - * anywhere on the same OHCI controller until - * we will finish addressing of reseted device ! */ - dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; - return; + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + dev->ports[i - 1].soft_limit_time = grub_get_time_ms () + 250; + dev->ports[i - 1].hard_limit_time = dev->ports[i - 1].soft_limit_time + 1750; + dev->ports[i - 1].state = PORT_STATE_WAITING_FOR_STABLE_POWER; + grub_boot_time ("Scheduling stable power wait for port %p:%d", + dev, i - 1); + continue; } } @@ -464,10 +592,14 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_CLEAR_FEATURE, GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); + grub_boot_time ("Port %d reset", i); + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { grub_usb_speed_t speed; grub_usb_device_t next_dev; + int split_hubport = 0; + int split_hubaddr = 0; /* Determine the device speed. */ if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) @@ -483,9 +615,42 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Wait a recovery time after reset, spec. says 10ms */ grub_millisleep (10); + /* Find correct values for SPLIT hubport and hubaddr */ + if (speed == GRUB_USB_SPEED_HIGH) + { + /* HIGH speed device needs not transaction translation */ + split_hubport = 0; + split_hubaddr = 0; + } + else + /* FULL/LOW device needs hub port and hub address + for transaction translation (if connected to EHCI) */ + if (dev->speed == GRUB_USB_SPEED_HIGH) + { + /* This port is the first FULL/LOW speed port + in the chain from root hub. Attached device + should use its port number and hub address */ + split_hubport = i; + split_hubaddr = dev->addr; + } + else + { + /* This port is NOT the first FULL/LOW speed port + in the chain from root hub. Attached device + should use values inherited from some parent + HIGH speed hub - if any. */ + split_hubport = dev->split_hubport; + split_hubaddr = dev->split_hubaddr; + } + /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); - dev->controller.dev->pending_reset = 0; + next_dev = grub_usb_hub_add_dev (&dev->controller, speed, + split_hubport, split_hubaddr); + if (dev->controller.dev->pending_reset) + { + dev->controller.dev->pending_reset = 0; + npending--; + } if (! next_dev) continue; @@ -500,7 +665,7 @@ poll_nonroot_hub (grub_usb_device_t dev) } void -grub_usb_poll_devices (void) +grub_usb_poll_devices (int wait_for_completion) { struct grub_usb_hub *hub; int i; @@ -514,7 +679,7 @@ grub_usb_poll_devices (void) grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; int changed = 0; - if (!hub->controller->dev->pending_reset) + if (hub->controller->dev->pending_reset) { /* Check for possible timeout */ if (grub_get_time_ms () > hub->controller->dev->pending_reset) @@ -522,10 +687,13 @@ grub_usb_poll_devices (void) /* Something went wrong, reset device was not * addressed properly, timeout happened */ hub->controller->dev->pending_reset = 0; - speed = hub->controller->dev->detect_dev (hub->controller, - i, &changed); + npending--; } } + if (!hub->controller->dev->pending_reset) + speed = hub->controller->dev->detect_dev (hub->controller, + i, &changed); + if (changed) { detach_device (hub->devices[i]); @@ -548,15 +716,30 @@ grub_usb_poll_devices (void) if (dev && dev->descdev.class == 0x09) poll_nonroot_hub (dev); } - if (!rescan) - break; - grub_millisleep (50); - } + while (1) + { + int continue_waiting = 0; + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + grub_usb_device_t dev = grub_usb_devs[i]; + + if (dev && dev->descdev.class == 0x09) + continue_waiting = continue_waiting || wait_power_nonroot_hub (dev); + } + if (!continue_waiting) + break; + grub_millisleep (1); + } + + if (!(rescan || (npending && wait_for_completion))) + break; + grub_millisleep (25); + } } int -grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) +grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) { int i; @@ -564,7 +747,7 @@ grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) { if (grub_usb_devs[i]) { - if (hook (grub_usb_devs[i])) + if (hook (grub_usb_devs[i], hook_data)) return 1; } } diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index 167fae5a2..557e71c2e 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -25,6 +25,19 @@ #include #include + +static inline unsigned int +grub_usb_bulk_maxpacket (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint) +{ + /* Use the maximum packet size given in the endpoint descriptor. */ + if (dev->initialized && endpoint) + return endpoint->maxpacket; + + return 64; +} + + static grub_usb_err_t grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, grub_usb_transfer_t transfer, @@ -199,7 +212,8 @@ grub_usb_control_msg (grub_usb_device_t dev, static grub_usb_transfer_t grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, + struct grub_usb_desc_endp *endpoint, + grub_size_t size0, char *data_in, grub_transfer_type_t type) { int i; @@ -210,7 +224,7 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; - int toggle = dev->toggle[endpoint]; + int toggle = dev->toggle[endpoint->endp_addr]; grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size, type); @@ -224,20 +238,6 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, if (type == GRUB_USB_TRANSFER_TYPE_OUT) grub_memcpy ((char *) data, data_in, size); - /* Use the maximum packet size given in the endpoint descriptor. */ - if (dev->initialized) - { - struct grub_usb_desc_endp *endpdesc; - endpdesc = grub_usb_get_endpdescriptor (dev, endpoint); - - if (endpdesc) - max = endpdesc->maxpacket; - else - max = 64; - } - else - max = 64; - /* Create a transfer. */ transfer = grub_malloc (sizeof (struct grub_usb_transfer)); if (! transfer) @@ -246,10 +246,12 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, return NULL; } + max = grub_usb_bulk_maxpacket (dev, endpoint); + datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint; + transfer->endpoint = endpoint->endp_addr; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; transfer->dir = type; @@ -315,7 +317,8 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) static grub_usb_err_t grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, + struct grub_usb_desc_endp *endpoint, + grub_size_t size0, char *data_in, grub_transfer_type_t type, int timeout, grub_size_t *actual) { @@ -333,31 +336,61 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, return err; } -grub_usb_err_t -grub_usb_bulk_write (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data) +static grub_usb_err_t +grub_usb_bulk_readwrite_packetize (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_transfer_type_t type, + grub_size_t size, char *data) { - grub_size_t actual; - grub_usb_err_t err; + grub_size_t actual, transferred; + grub_usb_err_t err = GRUB_USB_ERR_NONE; + grub_size_t current_size, position; + grub_size_t max_bulk_transfer_len = MAX_USB_TRANSFER_LEN; + grub_size_t max; - err = grub_usb_bulk_readwrite (dev, endpoint, size, data, - GRUB_USB_TRANSFER_TYPE_OUT, 1000, &actual); - if (!err && actual != size) + if (dev->controller.dev->max_bulk_tds) + { + max = grub_usb_bulk_maxpacket (dev, endpoint); + + /* Calculate max. possible length of bulk transfer */ + max_bulk_transfer_len = dev->controller.dev->max_bulk_tds * max; + } + + for (position = 0, transferred = 0; + position < size; position += max_bulk_transfer_len) + { + current_size = size - position; + if (current_size >= max_bulk_transfer_len) + current_size = max_bulk_transfer_len; + err = grub_usb_bulk_readwrite (dev, endpoint, current_size, + &data[position], type, 1000, &actual); + transferred += actual; + if (err || (current_size != actual)) break; + } + + if (!err && transferred != size) err = GRUB_USB_ERR_DATA; return err; } grub_usb_err_t -grub_usb_bulk_read (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data) +grub_usb_bulk_write (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data) { - grub_size_t actual; - grub_usb_err_t err; - err = grub_usb_bulk_readwrite (dev, endpoint, size, data, - GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual); - if (!err && actual != size) - err = GRUB_USB_ERR_DATA; - return err; + return grub_usb_bulk_readwrite_packetize (dev, endpoint, + GRUB_USB_TRANSFER_TYPE_OUT, + size, data); +} + +grub_usb_err_t +grub_usb_bulk_read (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data) +{ + return grub_usb_bulk_readwrite_packetize (dev, endpoint, + GRUB_USB_TRANSFER_TYPE_IN, + size, data); } grub_usb_err_t @@ -378,7 +411,8 @@ grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) grub_usb_transfer_t grub_usb_bulk_read_background (grub_usb_device_t dev, - int endpoint, grub_size_t size, void *data) + struct grub_usb_desc_endp *endpoint, + grub_size_t size, void *data) { grub_usb_err_t err; grub_usb_transfer_t transfer; @@ -405,7 +439,8 @@ grub_usb_cancel_transfer (grub_usb_transfer_t transfer) grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data, int timeout, grub_size_t *actual) { return grub_usb_bulk_readwrite (dev, endpoint, size, data, diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index c6be5e1f5..14f639c6d 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -142,49 +142,59 @@ iszero (grub_uint8_t *reg, int size) } #if defined (__i386__) || defined (__x86_64__) +/* Context for grub_acpi_create_ebda. */ +struct grub_acpi_create_ebda_ctx { + int ebda_len; + grub_uint64_t highestlow; +}; + +/* Helper for grub_acpi_create_ebda. */ +static int +find_hook (grub_uint64_t start, grub_uint64_t size, grub_memory_type_t type, + void *data) +{ + struct grub_acpi_create_ebda_ctx *ctx = data; + grub_uint64_t end = start + size; + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + if (end > 0x100000) + end = 0x100000; + if (end > start + ctx->ebda_len + && ctx->highestlow < ((end - ctx->ebda_len) & (~0xf)) ) + ctx->highestlow = (end - ctx->ebda_len) & (~0xf); + return 0; +} + grub_err_t grub_acpi_create_ebda (void) { - int ebda_kb_len; - int ebda_len; + struct grub_acpi_create_ebda_ctx ctx = { + .highestlow = 0 + }; + int ebda_kb_len = 0; int mmapregion = 0; grub_uint8_t *ebda, *v1inebda = 0, *v2inebda = 0; - grub_uint64_t highestlow = 0; grub_uint8_t *targetebda, *target; struct grub_acpi_rsdp_v10 *v1; struct grub_acpi_rsdp_v20 *v2; - auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); - int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size, - grub_memory_type_t type) - { - grub_uint64_t end = start + size; - if (type != GRUB_MEMORY_AVAILABLE) - return 0; - if (end > 0x100000) - end = 0x100000; - if (end > start + ebda_len - && highestlow < ((end - ebda_len) & (~0xf)) ) - highestlow = (end - ebda_len) & (~0xf); - return 0; - } ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); - ebda_kb_len = *(grub_uint16_t *) ebda; - if (! ebda || ebda_kb_len > 16) + if (ebda) + ebda_kb_len = *(grub_uint16_t *) ebda; + if (ebda_kb_len > 16) ebda_kb_len = 0; - ebda_len = (ebda_kb_len + 1) << 10; + ctx.ebda_len = (ebda_kb_len + 1) << 10; /* FIXME: use low-memory mm allocation once it's available. */ - grub_mmap_iterate (find_hook); - targetebda = (grub_uint8_t *) (grub_addr_t) highestlow; + grub_mmap_iterate (find_hook, &ctx); + targetebda = (grub_uint8_t *) (grub_addr_t) ctx.highestlow; grub_dprintf ("acpi", "creating ebda @%llx\n", - (unsigned long long) highestlow); - if (! highestlow) + (unsigned long long) ctx.highestlow); + if (! ctx.highestlow) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't find space for the new EBDA"); - mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len, + mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ctx.ebda_len, GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -207,7 +217,7 @@ grub_acpi_create_ebda (void) { grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n"); for (; target < targetebda + 0x400 - v2->length; target += 0x10) - if (grub_memcmp (target, "RSD PTR ", 8) == 0 + if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) target)->revision != 0 @@ -228,7 +238,7 @@ grub_acpi_create_ebda (void) grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n"); for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10); target += 0x10) - if (grub_memcmp (target, "RSD PTR ", 8) == 0 + if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0) { @@ -289,7 +299,7 @@ grub_acpi_create_ebda (void) for (target = targetebda; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10); target += 0x10) - if (grub_memcmp (target, "RSD PTR ", 8) == 0 + if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0 && target != v1inebda && target != v2inebda) @@ -355,13 +365,13 @@ setup_common_tables (void) numoftables++; rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr; - playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * numoftables; + playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; rsdt_entry = (grub_uint32_t *) (rsdt + 1); /* Fill RSDT header. */ grub_memcpy (&(rsdt->signature), "RSDT", 4); - rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables; + rsdt->length = sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; rsdt->revision = 1; grub_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid)); grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable)); @@ -384,7 +394,7 @@ setv1table (void) /* Create RSDP. */ rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr; playground_ptr += sizeof (struct grub_acpi_rsdp_v10); - grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", + grub_memcpy (&(rsdpv1_new->signature), GRUB_RSDP_SIGNATURE, sizeof (rsdpv1_new->signature)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); rsdpv1_new->revision = 0; @@ -409,13 +419,13 @@ setv2table (void) /* Create XSDT. */ xsdt = (struct grub_acpi_table_header *) playground_ptr; - playground_ptr += sizeof (struct grub_acpi_table_header) + 8 * numoftables; + playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; xsdt_entry = (grub_uint64_t *)(xsdt + 1); for (cur = acpi_tables; cur; cur = cur->next) *(xsdt_entry++) = (grub_addr_t) cur->addr; grub_memcpy (&(xsdt->signature), "XSDT", 4); - xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables; + xsdt->length = sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; xsdt->revision = 1; grub_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid)); grub_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable)); @@ -428,7 +438,7 @@ setv2table (void) /* Create RSDPv2. */ rsdpv2_new = (struct grub_acpi_rsdp_v20 *) playground_ptr; playground_ptr += sizeof (struct grub_acpi_rsdp_v20); - grub_memcpy (&(rsdpv2_new->rsdpv1.signature), "RSD PTR ", + grub_memcpy (&(rsdpv2_new->rsdpv1.signature), GRUB_RSDP_SIGNATURE, sizeof (rsdpv2_new->rsdpv1.signature)); grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid, sizeof (rsdpv2_new->rsdpv1.oemid)); @@ -698,11 +708,11 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* DSDT. */ playground_size += dsdt_size; /* RSDT. */ - playground_size += sizeof (struct grub_acpi_table_header) + 4 * numoftables; + playground_size += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; /* RSDPv1. */ playground_size += sizeof (struct grub_acpi_rsdp_v10); /* XSDT. */ - playground_size += sizeof (struct grub_acpi_table_header) + 8 * numoftables; + playground_size += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; /* RSDPv2. */ playground_size += sizeof (struct grub_acpi_rsdp_v20); diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c index a8014de14..09421a6c6 100644 --- a/grub-core/commands/acpihalt.c +++ b/grub-core/commands/acpihalt.c @@ -22,6 +22,7 @@ #include #include #include +#include #define grub_dprintf(cond, args...) printf ( args ) #define grub_printf printf @@ -184,7 +185,6 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, grub_uint8_t *scope, int scope_len) { grub_uint8_t *prev = table; - int sleep_type = -2; if (!ptr) ptr = table + sizeof (struct grub_acpi_table_header); @@ -233,14 +233,11 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, switch (*ptr2) { case GRUB_ACPI_OPCODE_ZERO: - sleep_type = 0; - break; + return 0; case GRUB_ACPI_OPCODE_ONE: - sleep_type = 1; - break; + return 1; case GRUB_ACPI_OPCODE_BYTE_CONST: - sleep_type = ptr2[1]; - break; + return ptr2[1]; default: grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); return -1; @@ -286,8 +283,7 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, } } - grub_dprintf ("acpi", "TYP = %d\n", sleep_type); - return sleep_type; + return -2; } #ifdef GRUB_DSDT_TEST @@ -299,7 +295,7 @@ main (int argc, char **argv) unsigned char *buf; if (argc < 2) printf ("Usage: %s FILE\n", argv[0]); - f = fopen (argv[1], "rb"); + f = grub_util_fopen (argv[1], "rb"); if (!f) { printf ("Couldn't open file\n"); @@ -311,13 +307,13 @@ main (int argc, char **argv) buf = malloc (len); if (!buf) { - printf ("Couldn't malloc buffer\n"); + printf (_("error: %s.\n"), _("out of memory")); fclose (f); return 2; } if (fread (buf, 1, len, f) != len) { - printf ("Read failed\n"); + printf (_("cannot read `%s': %s"), argv[1], strerror (errno)); free (buf); fclose (f); return 2; @@ -369,11 +365,13 @@ grub_acpi_halt (void) grub_dprintf ("acpi", "PM1a port=%x\n", port); if (grub_memcmp (dsdt->signature, "DSDT", - sizeof (dsdt->signature)) == 0) + sizeof (dsdt->signature)) == 0 + && sleep_type < 0) sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length, NULL, 0); } - else if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "SSDT", 4) == 0) + else if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "SSDT", 4) == 0 + && sleep_type < 0) { struct grub_acpi_table_header *ssdt = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; @@ -385,13 +383,10 @@ grub_acpi_halt (void) } } + grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", sleep_type, port); if (port && sleep_type >= 0 && sleep_type < 8) - { - 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_outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), + port & 0xffff); grub_millisleep (1500); diff --git a/grub-core/commands/arc/lsdev.c b/grub-core/commands/arc/lsdev.c index 5d4b0cd09..27ed0a248 100644 --- a/grub-core/commands/arc/lsdev.c +++ b/grub-core/commands/arc/lsdev.c @@ -24,18 +24,22 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Helper for grub_cmd_lsdev. */ +static int +grub_cmd_lsdev_iter (const char *name, + const struct grub_arc_component *comp __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_printf ("%s\n", name); + return 0; +} + static grub_err_t grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - auto int hook (const char *name, const struct grub_arc_component *comp); - int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused))) - { - grub_printf ("%s\n", name); - return 0; - } - grub_arc_iterate_devs (hook, 0); + grub_arc_iterate_devs (grub_cmd_lsdev_iter, 0, 0); return 0; } diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c index 164a6fea3..d1a47b504 100644 --- a/grub-core/commands/blocklist.c +++ b/grub-core/commands/blocklist.c @@ -28,58 +28,95 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Context for grub_cmd_blocklist. */ +struct blocklist_ctx +{ + unsigned long start_sector; + unsigned num_sectors; + int num_entries; + grub_disk_addr_t part_start; +}; + +/* Helper for grub_cmd_blocklist. */ +static void +print_blocklist (grub_disk_addr_t sector, unsigned num, + unsigned offset, unsigned length, struct blocklist_ctx *ctx) +{ + if (ctx->num_entries++) + grub_printf (","); + + grub_printf ("%llu", (unsigned long long) (sector - ctx->part_start)); + if (num > 0) + grub_printf ("+%u", num); + if (offset != 0 || length != 0) + grub_printf ("[%u-%u]", offset, offset + length); +} + +/* Helper for grub_cmd_blocklist. */ +static void +read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length, + void *data) +{ + struct blocklist_ctx *ctx = data; + + if (ctx->num_sectors > 0) + { + if (ctx->start_sector + ctx->num_sectors == sector + && offset == 0 && length >= GRUB_DISK_SECTOR_SIZE) + { + ctx->num_sectors += length >> GRUB_DISK_SECTOR_BITS; + sector += length >> GRUB_DISK_SECTOR_BITS; + length &= (GRUB_DISK_SECTOR_SIZE - 1); + } + + if (!length) + return; + print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx); + ctx->num_sectors = 0; + } + + if (offset) + { + unsigned l = length + offset; + l &= (GRUB_DISK_SECTOR_SIZE - 1); + l -= offset; + print_blocklist (sector, 0, offset, l, ctx); + length -= l; + sector++; + offset = 0; + } + + if (!length) + return; + + if (length & (GRUB_DISK_SECTOR_SIZE - 1)) + { + if (length >> GRUB_DISK_SECTOR_BITS) + { + print_blocklist (sector, length >> GRUB_DISK_SECTOR_BITS, 0, 0, ctx); + sector += length >> GRUB_DISK_SECTOR_BITS; + } + print_blocklist (sector, 0, 0, length & (GRUB_DISK_SECTOR_SIZE - 1), ctx); + } + else + { + ctx->start_sector = sector; + ctx->num_sectors = length >> GRUB_DISK_SECTOR_BITS; + } +} + static grub_err_t grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_file_t file; char buf[GRUB_DISK_SECTOR_SIZE]; - unsigned long start_sector = 0; - unsigned num_sectors = 0; - int num_entries = 0; - grub_disk_addr_t part_start = 0; - auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset, - unsigned length); - auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num, - unsigned offset, unsigned length); - - void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - if (num_sectors > 0) - { - if (start_sector + num_sectors == sector - && offset == 0 && length == GRUB_DISK_SECTOR_SIZE) - { - num_sectors++; - return; - } - - print_blocklist (start_sector, num_sectors, 0, 0); - num_sectors = 0; - } - - if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE) - { - start_sector = sector; - num_sectors++; - } - else - print_blocklist (sector, 0, offset, length); - } - - void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num, - unsigned offset, unsigned length) - { - if (num_entries++) - grub_printf (","); - - grub_printf ("%llu", (unsigned long long) (sector - part_start)); - if (num > 0) - grub_printf ("+%u", num); - if (offset != 0 || length != 0) - grub_printf ("[%u-%u]", offset, offset + length); - } + struct blocklist_ctx ctx = { + .start_sector = 0, + .num_sectors = 0, + .num_entries = 0, + .part_start = 0 + }; if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); @@ -93,15 +130,16 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_DEVICE, "this command is available only for disk devices"); - part_start = grub_partition_get_start (file->device->disk->partition); + ctx.part_start = grub_partition_get_start (file->device->disk->partition); file->read_hook = read_blocklist; + file->read_hook_data = &ctx; while (grub_file_read (file, buf, sizeof (buf)) > 0) ; - if (num_sectors > 0) - print_blocklist (start_sector, num_sectors, 0, 0); + if (ctx.num_sectors > 0) + print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx); grub_file_close (file); diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index 91ec87d80..bbca81e94 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -146,8 +146,7 @@ grub_loader_boot (void) return grub_error (GRUB_ERR_NO_KERNEL, N_("you need to load the kernel first")); - if (grub_loader_flags & GRUB_LOADER_FLAG_NORETURN) - grub_machine_fini (); + grub_machine_fini (grub_loader_flags); for (cur = preboots_head; cur; cur = cur->next) { @@ -183,22 +182,14 @@ grub_cmd_boot (struct grub_command *cmd __attribute__ ((unused)), static grub_command_t cmd_boot; -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_boot_init (void) -#else GRUB_MOD_INIT(boot) -#endif { cmd_boot = grub_register_command ("boot", grub_cmd_boot, 0, N_("Boot an operating system.")); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_boot_fini (void) -#else GRUB_MOD_FINI(boot) -#endif { grub_unregister_command (cmd_boot); } diff --git a/grub-core/commands/boottime.c b/grub-core/commands/boottime.c new file mode 100644 index 000000000..7370d271c --- /dev/null +++ b/grub-core/commands/boottime.c @@ -0,0 +1,65 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +static grub_err_t +grub_cmd_boottime (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + struct grub_boot_time *cur; + grub_uint64_t last_time = 0, start_time = 0; + if (!grub_boot_time_head) + { + grub_puts_ (N_("No boot time statistics is available\n")); + return 0; + } + start_time = last_time = grub_boot_time_head->tp; + for (cur = grub_boot_time_head; cur; cur = cur->next) + { + grub_uint32_t tmabs = cur->tp - start_time; + grub_uint32_t tmrel = cur->tp - last_time; + last_time = cur->tp; + + grub_printf ("%3d.%03ds %2d.%03ds %s:%d %s\n", + tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, cur->file, cur->line, + cur->msg); + } + return 0; +} + +static grub_command_t cmd_boottime; + +GRUB_MOD_INIT(boottime) +{ + cmd_boottime = + grub_register_command ("boottime", grub_cmd_boottime, + 0, N_("Get boot time statistics.")); +} + +GRUB_MOD_FINI(boottime) +{ + grub_unregister_command (cmd_boottime); +} diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index cd2d76099..8a7f1af78 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -39,9 +40,15 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) struct grub_arg_list *state = ctxt->state; int dos = 0; grub_file_t file; - char buf[GRUB_DISK_SECTOR_SIZE]; + unsigned char buf[GRUB_DISK_SECTOR_SIZE]; grub_ssize_t size; int key = GRUB_TERM_NO_KEY; + grub_uint32_t code = 0; + int count = 0; + unsigned char utbuf[GRUB_MAX_UTF8_PER_CODEPOINT + 1]; + int utcount = 0; + int is_0d = 0; + int j; if (state[0].set) dos = 1; @@ -60,21 +67,65 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) for (i = 0; i < size; i++) { - unsigned char c = buf[i]; + utbuf[utcount++] = buf[i]; - if ((grub_isprint (c) || grub_isspace (c)) && c != '\r') - grub_printf ("%c", c); - else if (dos && c == '\r' && i + 1 < size && buf[i + 1] == '\n') - { - grub_printf ("\n"); - i++; - } - else + if (is_0d && buf[i] != '\n') { grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); - grub_printf ("<%x>", (int) c); + grub_printf ("<%x>", (int) '\r'); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); } + + is_0d = 0; + + if (!grub_utf8_process (buf[i], &code, &count)) + { + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + for (j = 0; j < utcount - 1; j++) + grub_printf ("<%x>", (unsigned int) utbuf[j]); + code = 0; + count = 0; + if (utcount == 1 || !grub_utf8_process (buf[i], &code, &count)) + { + grub_printf ("<%x>", (unsigned int) buf[i]); + code = 0; + count = 0; + utcount = 0; + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + continue; + } + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + utcount = 1; + } + if (count) + continue; + + if ((code >= 0xa1 || grub_isprint (code) + || grub_isspace (code)) && code != '\r') + { + grub_printf ("%C", code); + count = 0; + code = 0; + utcount = 0; + continue; + } + + if (dos && code == '\r') + { + is_0d = 1; + count = 0; + code = 0; + utcount = 0; + continue; + } + + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + for (j = 0; j < utcount; j++) + grub_printf ("<%x>", (unsigned int) utbuf[j]); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + count = 0; + code = 0; + utcount = 0; } do @@ -82,6 +133,18 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) while (key != GRUB_TERM_ESC && key != GRUB_TERM_NO_KEY); } + if (is_0d) + { + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("<%x>", (unsigned int) '\r'); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + } + + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + for (j = 0; j < utcount; j++) + grub_printf ("<%x>", (unsigned int) utbuf[j]); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + grub_xputs ("\n"); grub_refresh (); grub_file_close (file); diff --git a/grub-core/commands/configfile.c b/grub-core/commands/configfile.c index 99c0a2479..f2d2abb5f 100644 --- a/grub-core/commands/configfile.c +++ b/grub-core/commands/configfile.c @@ -78,7 +78,7 @@ GRUB_MOD_INIT(configfile) cmd_extractor_configfile = grub_register_command ("extract_entries_configfile", grub_cmd_source, N_("FILE"), - N_("Load another config file without changing context but take only menu entries.") + N_("Load another config file but take only menu entries.") ); cmd_dot = diff --git a/grub-core/commands/efi/fixvideo.c b/grub-core/commands/efi/fixvideo.c index 3ed40b386..d9d54a2e8 100644 --- a/grub-core/commands/efi/fixvideo.c +++ b/grub-core/commands/efi/fixvideo.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -40,8 +41,9 @@ static struct grub_video_patch {0, 0, 0, 0, 0} }; -static int NESTED_FUNC_ATTR -scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +scan_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_pci_address_t addr; @@ -93,7 +95,7 @@ grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { - grub_pci_iterate (scan_card); + grub_pci_iterate (scan_card, NULL); return 0; } diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c new file mode 100644 index 000000000..8dffbdc30 --- /dev/null +++ b/grub-core/commands/efi/lsefi.c @@ -0,0 +1,153 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct known_protocol +{ + grub_efi_guid_t guid; + const char *name; +} known_protocols[] = + { + { GRUB_EFI_DISK_IO_GUID, "disk" }, + { GRUB_EFI_BLOCK_IO_GUID, "block" }, + { GRUB_EFI_SERIAL_IO_GUID, "serial" }, + { GRUB_EFI_SIMPLE_NETWORK_GUID, "network" }, + { GRUB_EFI_PXE_GUID, "pxe" }, + { GRUB_EFI_DEVICE_PATH_GUID, "device path" }, + { GRUB_EFI_PCI_IO_GUID, "PCI" }, + { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root" }, + { GRUB_EFI_EDID_ACTIVE_GUID, "active EDID" }, + { GRUB_EFI_EDID_DISCOVERED_GUID, "discovered EDID" }, + { GRUB_EFI_EDID_OVERRIDE_GUID, "override EDID" }, + { GRUB_EFI_GOP_GUID, "GOP" }, + { GRUB_EFI_UGA_DRAW_GUID, "UGA draw" }, + { GRUB_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID, "simple text output" }, + { GRUB_EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID, "simple text input" }, + { GRUB_EFI_SIMPLE_POINTER_PROTOCOL_GUID, "simple pointer" }, + { GRUB_EFI_CONSOLE_CONTROL_GUID, "console control" }, + { GRUB_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" }, + { GRUB_EFI_DRIVER_BINDING_PROTOCOL_GUID, "EFI driver binding" }, + { GRUB_EFI_LOAD_FILE_PROTOCOL_GUID, "load file" }, + { GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "simple FS" }, + { GRUB_EFI_TAPE_IO_PROTOCOL_GUID, "tape I/O" }, + { GRUB_EFI_UNICODE_COLLATION_PROTOCOL_GUID, "unicode collation" }, + { GRUB_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O" }, + { GRUB_EFI_USB2_HC_PROTOCOL_GUID, "USB host" }, + { GRUB_EFI_DEBUG_SUPPORT_PROTOCOL_GUID, "debug support" }, + { GRUB_EFI_DEBUGPORT_PROTOCOL_GUID, "debug port" }, + { GRUB_EFI_DECOMPRESS_PROTOCOL_GUID, "decompress" }, + { GRUB_EFI_LOADED_IMAGE_PROTOCOL_GUID, "loaded image" }, + { GRUB_EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, "device path to text" }, + { GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID, "device path utilities" }, + { GRUB_EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID, "device path from text" }, + { GRUB_EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, "HII config routing" }, + { GRUB_EFI_HII_DATABASE_PROTOCOL_GUID, "HII database" }, + { GRUB_EFI_HII_STRING_PROTOCOL_GUID, "HII string" }, + { GRUB_EFI_HII_IMAGE_PROTOCOL_GUID, "HII image" }, + { GRUB_EFI_HII_FONT_PROTOCOL_GUID, "HII font" }, + { GRUB_EFI_COMPONENT_NAME2_PROTOCOL_GUID, "component name 2" }, + { GRUB_EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID, + "HII configuration access" }, + { GRUB_EFI_USB_IO_PROTOCOL_GUID, "USB I/O" }, + }; + +static grub_err_t +grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; + unsigned i, j, k; + + handles = grub_efi_locate_handle (GRUB_EFI_ALL_HANDLES, + NULL, NULL, &num_handles); + + for (i = 0; i < num_handles; i++) + { + grub_efi_handle_t handle = handles[i]; + grub_efi_status_t status; + grub_efi_uintn_t num_protocols; + grub_efi_guid_t **protocols; + grub_efi_device_path_t *dp; + + grub_printf ("Handle %p\n", handle); + + dp = grub_efi_get_device_path (handle); + if (dp) + { + grub_printf (" "); + grub_efi_print_device_path (dp); + } + + status = efi_call_3 (grub_efi_system_table->boot_services->protocols_per_handle, + handle, &protocols, &num_protocols); + if (status != GRUB_EFI_SUCCESS) + grub_printf ("Unable to retrieve protocols\n"); + for (j = 0; j < num_protocols; j++) + { + for (k = 0; k < ARRAY_SIZE (known_protocols); k++) + if (grub_memcmp (protocols[j], &known_protocols[k].guid, + sizeof (known_protocols[k].guid)) == 0) + break; + if (k < ARRAY_SIZE (known_protocols)) + grub_printf (" %s\n", known_protocols[k].name); + else + grub_printf (" %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + protocols[j]->data1, + protocols[j]->data2, + protocols[j]->data3, + (unsigned) protocols[j]->data4[0], + (unsigned) protocols[j]->data4[1], + (unsigned) protocols[j]->data4[2], + (unsigned) protocols[j]->data4[3], + (unsigned) protocols[j]->data4[4], + (unsigned) protocols[j]->data4[5], + (unsigned) protocols[j]->data4[6], + (unsigned) protocols[j]->data4[7]); + } + + } + + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsefi) +{ + cmd = grub_register_command ("lsefi", grub_cmd_lsefi, + NULL, "Display EFI handles."); +} + +GRUB_MOD_FINI(lsefi) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/eval.c b/grub-core/commands/eval.c new file mode 100644 index 000000000..f826a4f22 --- /dev/null +++ b/grub-core/commands/eval.c @@ -0,0 +1,71 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_eval (grub_command_t cmd __attribute__((__unused__)), + int argc, char *argv[]) +{ + int i; + grub_size_t size = argc; /* +1 for final zero */ + char *str, *p; + grub_err_t ret; + + if (argc == 0) + return GRUB_ERR_NONE; + + for (i = 0; i < argc; i++) + size += grub_strlen (argv[i]); + + str = p = grub_malloc (size); + if (!str) + return grub_errno; + + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *p++ = ' '; + } + *--p = '\0'; + + ret = grub_script_execute_sourcecode (str); + grub_free (str); + return ret; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(eval) +{ + cmd = grub_register_command ("eval", grub_cmd_eval, N_("STRING ..."), + N_("Evaluate arguments as GRUB commands")); +} + +GRUB_MOD_FINI(eval) +{ + grub_unregister_command (cmd); +} + diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c index 1a203dc59..3db62887b 100644 --- a/grub-core/commands/gptsync.c +++ b/grub-core/commands/gptsync.c @@ -37,11 +37,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); Is it a problem? */ static void -lba_to_chs (int lba, grub_uint8_t *cl, grub_uint8_t *ch, +lba_to_chs (grub_uint32_t lba, grub_uint8_t *cl, grub_uint8_t *ch, grub_uint8_t *dh) { - int cylinder, head, sector; - int sectors = 63, heads = 255, cylinders = 1024; + grub_uint32_t cylinder, head, sector; + grub_uint32_t sectors = 63, heads = 255, cylinders = 1024; sector = lba % sectors + 1; head = (lba / sectors) % heads; diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index ba33ea294..d18687351 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -63,17 +63,23 @@ hextoval (char c) static grub_err_t hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) { - grub_uint8_t context[hash->contextsize]; - grub_uint8_t readbuf[4096]; + void *context; + grub_uint8_t *readbuf; +#define BUF_SIZE 4096 + readbuf = grub_malloc (BUF_SIZE); + if (!readbuf) + return grub_errno; + context = grub_zalloc (hash->contextsize); + if (!readbuf || !context) + goto fail; - grub_memset (context, 0, sizeof (context)); hash->init (context); while (1) { grub_ssize_t r; - r = grub_file_read (file, readbuf, sizeof (readbuf)); + r = grub_file_read (file, readbuf, BUF_SIZE); if (r < 0) - return grub_errno; + goto fail; if (r == 0) break; hash->write (context, readbuf, r); @@ -81,7 +87,15 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) hash->final (context); grub_memcpy (result, hash->read (context), hash->mdlen); + grub_free (readbuf); + grub_free (context); + return GRUB_ERR_NONE; + + fail: + grub_free (readbuf); + grub_free (context); + return grub_errno; } static grub_err_t @@ -90,12 +104,15 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, { grub_file_t hashlist, file; char *buf = NULL; - grub_uint8_t expected[hash->mdlen]; - grub_uint8_t actual[hash->mdlen]; + grub_uint8_t expected[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t actual[GRUB_CRYPTO_MAX_MDLEN]; grub_err_t err; unsigned i; unsigned unread = 0, mismatch = 0; + if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return grub_error (GRUB_ERR_BUG, "mdlen is too long"); + hashlist = grub_file_open (hashfilename); if (!hashlist) return grub_errno; @@ -205,6 +222,9 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt, if (!hash) return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown hash"); + if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return grub_error (GRUB_ERR_BUG, "mdlen is too long"); + if (state[2].set) prefix = state[2].arg; @@ -218,7 +238,7 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt, for (i = 0; i < (unsigned) argc; i++) { - GRUB_PROPERLY_ALIGNED_ARRAY (result, hash->mdlen); + GRUB_PROPERLY_ALIGNED_ARRAY (result, GRUB_CRYPTO_MAX_MDLEN); grub_file_t file; grub_err_t err; unsigned j; diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index d64c28915..f0be89baa 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -99,12 +99,13 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, else { int i; - grub_command_t cmd_iter, cmd; + grub_command_t cmd_iter, cmd, cmd_next; for (i = 0; i < argc; i++) { currarg = args[i]; - FOR_COMMANDS(cmd_iter) + + FOR_COMMANDS_SAFE (cmd_iter, cmd_next) { if (!(cmd_iter->prio & GRUB_COMMAND_FLAG_ACTIVE)) continue; diff --git a/grub-core/commands/i386/cmosdump.c b/grub-core/commands/i386/cmosdump.c new file mode 100644 index 000000000..952d200a4 --- /dev/null +++ b/grub-core/commands/i386/cmosdump.c @@ -0,0 +1,64 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_cmosdump (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) +{ + int i; + + for (i = 0; i < 256; i++) + { + grub_err_t err; + grub_uint8_t value; + if ((i & 0xf) == 0) + grub_printf ("%02x: ", i); + + err = grub_cmos_read (i, &value); + if (err) + return err; + + grub_printf ("%02x ", value); + if ((i & 0xf) == 0xf) + grub_printf ("\n"); + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + + +GRUB_MOD_INIT(cmosdump) +{ + cmd = grub_register_command ("cmosdump", grub_cmd_cmosdump, + 0, + N_("Dump CMOS contents.")); +} + +GRUB_MOD_FINI(cmosdump) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index d2a184026..6f7271bf9 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -81,7 +81,25 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), return grub_cmos_write (byte, value & (~(1 << bit))); } -static grub_command_t cmd, cmd_clean; +static grub_err_t +grub_cmd_cmosset (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + grub_uint8_t value; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + err = grub_cmos_read (byte, &value); + if (err) + return err; + + return grub_cmos_write (byte, value | (1 << bit)); +} + +static grub_command_t cmd, cmd_clean, cmd_set; GRUB_MOD_INIT(cmostest) @@ -92,10 +110,14 @@ GRUB_MOD_INIT(cmostest) cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, N_("BYTE:BIT"), N_("Clean bit at BYTE:BIT in CMOS.")); + cmd_set = grub_register_command ("cmosset", grub_cmd_cmosset, + N_("BYTE:BIT"), + N_("Set bit at BYTE:BIT in CMOS.")); } GRUB_MOD_FINI(cmostest) { grub_unregister_command (cmd); grub_unregister_command (cmd_clean); + grub_unregister_command (cmd_set); } diff --git a/grub-core/commands/i386/coreboot/cb_timestamps.c b/grub-core/commands/i386/coreboot/cb_timestamps.c new file mode 100644 index 000000000..5299ad4d8 --- /dev/null +++ b/grub-core/commands/i386/coreboot/cb_timestamps.c @@ -0,0 +1,118 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint32_t +tsc2ms (grub_uint64_t tsc) +{ + grub_uint64_t ah = tsc >> 32; + grub_uint64_t al = tsc & 0xffffffff; + + return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate; +} + +static const char *descs[] = { + [1] = "romstage", + [2] = "before RAM init", + [3] = "after RAM init", + [4] = "end of romstage", + [8] = "start of RAM copy", + [9] = "end of RAM copy", + [10] = "start of ramstage", + [30] = "device enumerate", + [40] = "device configure", + [50] = "device enable", + [60] = "device initialize", + [70] = "device done", + [75] = "CBMEM POST", + [80] = "writing tables", + [90] = "loading payload", + [98] = "wake jump", + [99] = "selfboot jump", +}; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data) +{ + int *available = data; + grub_uint64_t last_tsc = 0; + struct grub_linuxbios_timestamp_table *ts_table; + unsigned i; + + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_TIMESTAMPS) + return 0; + + *available = 1; + ts_table = (struct grub_linuxbios_timestamp_table *) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1); + + for (i = 0; i < ts_table->used; i++) + { + grub_uint32_t tmabs = tsc2ms (ts_table->entries[i].tsc); + grub_uint32_t tmrel = tsc2ms (ts_table->entries[i].tsc - last_tsc); + last_tsc = ts_table->entries[i].tsc; + + grub_printf ("%3d.%03ds %2d.%03ds %02d %s\n", + tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, + ts_table->entries[i].id, + (ts_table->entries[i].id < ARRAY_SIZE (descs) + && descs[ts_table->entries[i].id]) + ? descs[ts_table->entries[i].id] : ""); + } + return 1; +} + + +static grub_err_t +grub_cmd_coreboot_boottime (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + int available = 0; + + grub_linuxbios_table_iterate (iterate_linuxbios_table, &available); + if (!available) + { + grub_puts_ (N_("No boot time statistics is available\n")); + return 0; + } + return 0; +} + +static grub_command_t cmd_boottime; + +GRUB_MOD_INIT(cbtime) +{ + cmd_boottime = + grub_register_command ("coreboot_boottime", grub_cmd_coreboot_boottime, + 0, N_("Get coreboot boot time statistics.")); +} + +GRUB_MOD_FINI(cbtime) +{ + grub_unregister_command (cmd_boottime); +} diff --git a/grub-core/commands/i386/coreboot/cbls.c b/grub-core/commands/i386/coreboot/cbls.c new file mode 100644 index 000000000..e0a10596f --- /dev/null +++ b/grub-core/commands/i386/coreboot/cbls.c @@ -0,0 +1,143 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const char *console_descs[] = { + "8250 UART", + "VGA", + "BTEXT", + "log buffer console", + "SROM", + "EHCI debug", + "memory-mapped 8250 UART" +}; + +static const char *descs[] = { + [GRUB_LINUXBIOS_MEMBER_MEMORY] = "memory map (`lsmmap' to list)", + [GRUB_LINUXBIOS_MEMBER_MAINBOARD] = "mainboard", + [4] = "version", + [5] = "extra version", + [6] = "build", + [7] = "compile time", + [8] = "compile by", + [9] = "compile host", + [0xa] = "compile domain", + [0xb] = "compiler", + [0xc] = "linker", + [0xd] = "assembler", + [0xf] = "serial", + [GRUB_LINUXBIOS_MEMBER_CONSOLE] = "console", + [GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER] = "framebuffer", + [0x13] = "GPIO", + [0x15] = "VDAT", + [GRUB_LINUXBIOS_MEMBER_TIMESTAMPS] = "timestamps (`coreboot_boottime' to list)", + [GRUB_LINUXBIOS_MEMBER_CBMEMC] = "CBMEM console (`cbmemc' to list)", + [0x18] = "MRC cache", + [0x19] = "VBNV", + [0xc8] = "CMOS option table", + [0xc9] = "CMOS option", + [0xca] = "CMOS option enum", + [0xcb] = "CMOS option defaults", + [0xcc] = "CMOS checksum", +}; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data __attribute__ ((unused))) +{ + if (table_item->tag < ARRAY_SIZE (descs) && descs[table_item->tag]) + grub_printf ("tag=%02x size=%02x %s", + table_item->tag, table_item->size, descs[table_item->tag]); + else + grub_printf ("tag=%02x size=%02x", + table_item->tag, table_item->size); + + switch (table_item->tag) + { + case GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER: + { + struct grub_linuxbios_table_framebuffer *fb; + fb = (struct grub_linuxbios_table_framebuffer *) (table_item + 1); + + grub_printf (": %dx%dx%d pitch=%d lfb=0x%llx %d/%d/%d/%d %d/%d/%d/%d", + fb->width, fb->height, + fb->bpp, fb->pitch, + (unsigned long long) fb->lfb, + fb->red_mask_size, fb->green_mask_size, + fb->blue_mask_size, fb->reserved_mask_size, + fb->red_field_pos, fb->green_field_pos, + fb->blue_field_pos, fb->reserved_field_pos); + break; + } + case GRUB_LINUXBIOS_MEMBER_MAINBOARD: + { + struct grub_linuxbios_mainboard *mb; + mb = (struct grub_linuxbios_mainboard *) (table_item + 1); + grub_printf (": vendor=`%s' part_number=`%s'", + mb->strings + mb->vendor, + mb->strings + mb->part_number); + break; + } + case 0x04 ... 0x0d: + grub_printf (": `%s'", (char *) (table_item + 1)); + break; + case GRUB_LINUXBIOS_MEMBER_CONSOLE: + { + grub_uint16_t *val = (grub_uint16_t *) (table_item + 1); + grub_printf (": id=%d", *val); + if (*val < ARRAY_SIZE (console_descs) + && console_descs[*val]) + grub_printf (" %s", console_descs[*val]); + } + } + grub_printf ("\n"); + + return 0; +} + + +static grub_err_t +grub_cmd_lscoreboot (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + grub_linuxbios_table_iterate (iterate_linuxbios_table, 0); + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(cbls) +{ + cmd = + grub_register_command ("lscoreboot", grub_cmd_lscoreboot, + 0, N_("List coreboot tables.")); +} + +GRUB_MOD_FINI(cbls) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index 3b895cb93..af753590d 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -29,11 +29,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); -#define cpuid(num,a,b,c,d) \ - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ - : "0" (num)) - static const struct grub_arg_option options[] = { /* TRANSLATORS: "(default)" at the end means that this option is used if @@ -78,18 +73,18 @@ GRUB_MOD_INIT(cpuid) goto done; /* Check the highest input value for eax. */ - cpuid (0, eax, ebx, ecx, edx); + grub_cpuid (0, eax, ebx, ecx, edx); /* We only look at the first four characters. */ max_level = eax; if (max_level == 0) goto done; - cpuid (0x80000000, eax, ebx, ecx, edx); + grub_cpuid (0x80000000, eax, ebx, ecx, edx); ext_level = eax; if (ext_level < 0x80000000) goto done; - cpuid (0x80000001, eax, ebx, ecx, edx); + grub_cpuid (0x80000001, eax, ebx, ecx, edx); grub_cpuid_has_longmode = !!(edx & bit_LM); done: #endif diff --git a/grub-core/commands/i386/nthibr.c b/grub-core/commands/i386/nthibr.c new file mode 100644 index 000000000..92ce629d9 --- /dev/null +++ b/grub-core/commands/i386/nthibr.c @@ -0,0 +1,79 @@ +/* nthibr.c - tests whether an MS Windows system partition is hibernated */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Peter Lustig + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_nthibr (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_uint8_t hibr_file_magic[4]; + grub_file_t hibr_file = 0; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + hibr_file = grub_file_open (args[0]); + if (!hibr_file) + return grub_errno; + + /* Try to read magic number of 'hiberfil.sys' */ + if (grub_file_read (hibr_file, hibr_file_magic, + sizeof (hibr_file_magic)) + != (grub_ssize_t) sizeof (hibr_file_magic)) + { + if (!grub_errno) + grub_error (GRUB_ERR_TEST_FAILURE, "false"); + goto exit; + } + + if (!(grub_memcmp ("hibr", hibr_file_magic, sizeof (hibr_file_magic)) == 0 + || grub_memcmp ("HIBR", hibr_file_magic, sizeof (hibr_file_magic)) == 0)) + grub_error (GRUB_ERR_TEST_FAILURE, "false"); + + exit: + grub_file_close (hibr_file); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT (check_nt_hiberfil) +{ + cmd = grub_register_command ("check_nt_hiberfil", grub_cmd_nthibr, + N_("FILE"), + N_("Test whether a hiberfil.sys is " + "in hibernated state.")); +} + +GRUB_MOD_FINI (check_nt_hiberfil) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/i386/pc/acpi.c b/grub-core/commands/i386/pc/acpi.c index 88e4f55cf..d415d2305 100644 --- a/grub-core/commands/i386/pc/acpi.c +++ b/grub-core/commands/i386/pc/acpi.c @@ -32,7 +32,7 @@ grub_machine_acpi_get_rsdpv1 (void) if (! ebda_len) return 0; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0) return (struct grub_acpi_rsdp_v10 *) ptr; @@ -40,7 +40,7 @@ grub_machine_acpi_get_rsdpv1 (void) grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0) return (struct grub_acpi_rsdp_v10 *) ptr; @@ -59,7 +59,7 @@ grub_machine_acpi_get_rsdpv2 (void) if (! ebda_len) return 0; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0 && ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024 @@ -70,7 +70,7 @@ grub_machine_acpi_get_rsdpv2 (void) grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0 && ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024 diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index 10a018181..40798c96c 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -28,80 +28,12 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); #define BASE_TEMPO (60 * 1000) -/* The speaker port. */ -#define SPEAKER 0x61 - -/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output - from timer 2. */ -#define SPEAKER_TMR2 0x01 - -/* If SPEAKER_TMR2 is not set, this provides direct input into the - speaker. Otherwise, this enables or disables the output from the - timer. */ -#define SPEAKER_DATA 0x02 - -/* The PIT channel value ports. You can write to and read from them. - Do not mess with timer 0 or 1. */ -#define PIT_COUNTER_0 0x40 -#define PIT_COUNTER_1 0x41 -#define PIT_COUNTER_2 0x42 - -/* The frequency of the PIT clock. */ -#define PIT_FREQUENCY 0x1234dd - -/* The PIT control port. You can only write to it. Do not mess with - timer 0 or 1. */ -#define PIT_CTRL 0x43 -#define PIT_CTRL_SELECT_MASK 0xc0 -#define PIT_CTRL_SELECT_0 0x00 -#define PIT_CTRL_SELECT_1 0x40 -#define PIT_CTRL_SELECT_2 0x80 - -/* Read and load control. */ -#define PIT_CTRL_READLOAD_MASK 0x30 -#define PIT_CTRL_COUNTER_LATCH 0x00 /* Hold timer value until read. */ -#define PIT_CTRL_READLOAD_LSB 0x10 /* Read/load the LSB. */ -#define PIT_CTRL_READLOAD_MSB 0x20 /* Read/load the MSB. */ -#define PIT_CTRL_READLOAD_WORD 0x30 /* Read/load the LSB then the MSB. */ - -/* Mode control. */ -#define PIT_CTRL_MODE_MASK 0x0e - -/* Interrupt on terminal count. Setting the mode sets output to low. - When counter is set and terminated, output is set to high. */ -#define PIT_CTRL_INTR_ON_TERM 0x00 - -/* Programmable one-shot. When loading counter, output is set to - high. When counter terminated, output is set to low. Can be - triggered again from that point on by setting the gate pin to - high. */ -#define PIT_CTRL_PROGR_ONE_SHOT 0x02 - -/* Rate generator. Output is low for one period of the counter, and - high for the other. */ -#define PIT_CTRL_RATE_GEN 0x04 - -/* Square wave generator. Output is low for one half of the period, - and high for the other half. */ -#define PIT_CTRL_SQUAREWAVE_GEN 0x06 - -/* Software triggered strobe. Setting the mode sets output to high. - When counter is set and terminated, output is set to low. */ -#define PIT_CTRL_SOFTSTROBE 0x08 - -/* Hardware triggered strobe. Like software triggered strobe, but - only starts the counter when the gate pin is set to high. */ -#define PIT_CTRL_HARDSTROBE 0x0a - -/* Count mode. */ -#define PIT_CTRL_COUNT_MASK 0x01 -#define PIT_CTRL_COUNT_BINARY 0x00 /* 16-bit binary counter. */ -#define PIT_CTRL_COUNT_BCD 0x01 /* 4-decade BCD counter. */ #define T_REST ((grub_uint16_t) 0) #define T_FINE ((grub_uint16_t) -1) @@ -112,39 +44,6 @@ struct note grub_uint16_t duration; }; -static void -beep_off (void) -{ - unsigned char status; - - status = grub_inb (SPEAKER); - grub_outb (status & ~(SPEAKER_TMR2 | SPEAKER_DATA), SPEAKER); -} - -static void -beep_on (grub_uint16_t pitch) -{ - unsigned char status; - unsigned int counter; - - if (pitch < 20) - pitch = 20; - else if (pitch > 20000) - pitch = 20000; - - counter = PIT_FREQUENCY / pitch; - - /* Program timer 2. */ - grub_outb (PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD - | PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY, PIT_CTRL); - grub_outb (counter & 0xff, PIT_COUNTER_2); /* LSB */ - grub_outb ((counter >> 8) & 0xff, PIT_COUNTER_2); /* MSB */ - - /* Start speaker. */ - status = grub_inb (SPEAKER); - grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER); -} - /* Returns whether playing should continue. */ static int play (unsigned tempo, struct note *note) @@ -160,11 +59,11 @@ play (unsigned tempo, struct note *note) switch (note->pitch) { case T_REST: - beep_off (); + grub_speaker_beep_off (); break; default: - beep_on (note->pitch); + grub_speaker_beep_on (note->pitch); break; } @@ -263,7 +162,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), } } - beep_off (); + grub_speaker_beep_off (); return 0; } diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 17f648d78..d985cb33f 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -286,48 +286,49 @@ grub_sendkey_preboot (int noret __attribute__ ((unused))) return GRUB_ERR_NONE; } +/* Helper for grub_cmd_sendkey. */ +static int +find_key_code (char *key) +{ + unsigned i; + + for (i = 0; i < 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; +} + +/* Helper for grub_cmd_sendkey. */ +static 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; +} + 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; diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c index 6b5141c29..da04389e3 100644 --- a/grub-core/commands/keylayouts.c +++ b/grub-core/commands/keylayouts.c @@ -132,6 +132,9 @@ map_key_core (int code, int status, int *alt_gr_consumed) { *alt_gr_consumed = 0; + if (code >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + return 0; + if (status & GRUB_TERM_STATUS_RALT) { if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) @@ -242,7 +245,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), goto fail; } - if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION) + if (version != grub_cpu_to_le32_compile_time (GRUB_KEYBOARD_LAYOUTS_VERSION)) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version"); goto fail; @@ -290,21 +293,13 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), static grub_command_t cmd; -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_keylayouts_init (void) -#else GRUB_MOD_INIT(keylayouts) -#endif { cmd = grub_register_command ("keymap", grub_cmd_keymap, 0, N_("Load a keyboard layout.")); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_keylayouts_fini (void) -#else GRUB_MOD_FINI(keylayouts) -#endif { grub_unregister_command (cmd); } diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index 0925c6a0f..460cf4e7e 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -42,7 +42,7 @@ grub_getkeystatus (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); FOR_ACTIVE_TERM_INPUTS(term) { diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 5293accab..4443341b4 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -35,6 +35,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Helper for legacy_file. */ +static grub_err_t +legacy_file_getline (char **line, int cont __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + *line = 0; + return GRUB_ERR_NONE; +} + static grub_err_t legacy_file (const char *filename) { @@ -43,14 +52,6 @@ legacy_file (const char *filename) grub_menu_t menu; char *suffix = grub_strdup (""); - auto grub_err_t getline (char **line, int cont); - grub_err_t getline (char **line, - int cont __attribute__ ((unused))) - { - *line = 0; - return GRUB_ERR_NONE; - } - if (!suffix) return grub_errno; @@ -134,7 +135,7 @@ legacy_file (const char *filename) if (parsed && !entryname) { - grub_normal_parse_line (parsed, getline); + grub_normal_parse_line (parsed, legacy_file_getline, NULL); grub_print_error (); grub_free (parsed); parsed = NULL; @@ -180,7 +181,7 @@ legacy_file (const char *filename) grub_free (args); } - grub_normal_parse_line (suffix, getline); + grub_normal_parse_line (suffix, legacy_file_getline, NULL); grub_print_error (); grub_free (suffix); grub_free (entrysrc); @@ -357,7 +358,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), dev = grub_device_open (0); if (dev && dev->disk && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID - && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) + && dev->disk->id >= 0x80 && dev->disk->id <= 0x90) { struct grub_partition *part = dev->disk->partition; bsd_device = dev->disk->id - 0x80 - hdbias; @@ -545,8 +546,6 @@ struct legacy_md5_password grub_uint8_t hash[MD5_HASHLEN]; }; -#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" - static int check_password_md5_real (const char *entered, struct legacy_md5_password *pw) @@ -554,8 +553,13 @@ check_password_md5_real (const char *entered, grub_size_t enteredlen = grub_strlen (entered); unsigned char alt_result[MD5_HASHLEN]; unsigned char *digest; - grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + grub_uint8_t *ctx; grub_size_t i; + int ret; + + ctx = grub_zalloc (GRUB_MD_MD5->contextsize); + if (!ctx) + return 0; GRUB_MD_MD5->init (ctx); GRUB_MD_MD5->write (ctx, entered, enteredlen); @@ -601,7 +605,9 @@ check_password_md5_real (const char *entered, GRUB_MD_MD5->final (ctx); } - return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); + ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); + grub_free (ctx); + return ret; } static grub_err_t @@ -724,18 +730,11 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), NULL); } -static grub_err_t -grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), - int argc, char **args) +int +grub_legacy_check_md5_password (int argc, char **args, + char *entered) { struct legacy_md5_password *pw = NULL; - char entered[GRUB_AUTH_MAX_PASSLEN]; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); - grub_puts_ (N_("Enter password: ")); - if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) - return GRUB_ACCESS_DENIED; if (args[0][0] != '-' || args[0][1] != '-') { @@ -744,17 +743,31 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse grub_memset (correct, 0, sizeof (correct)); grub_strncpy (correct, args[0], sizeof (correct)); - if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0) - return GRUB_ACCESS_DENIED; - return GRUB_ERR_NONE; + return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0; } pw = parse_legacy_md5 (argc, args); if (!pw) + return 0; + + return check_password_md5_real (entered, pw); +} + +static grub_err_t +grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + char entered[GRUB_AUTH_MAX_PASSLEN]; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + grub_puts_ (N_("Enter password: ")); + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) return GRUB_ACCESS_DENIED; - if (!check_password_md5_real (entered, pw)) + if (!grub_legacy_check_md5_password (argc, args, + entered)) return GRUB_ACCESS_DENIED; return GRUB_ERR_NONE; diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 18ebb7eab..de6da2616 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -35,45 +35,53 @@ static const struct grub_arg_option options[] = /* TRANSLATORS: This option is used to override default filename for loading and storing environment. */ {"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME}, + {"skip-sig", 's', 0, + N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE}, {0, 0, 0, 0, 0, 0} }; +/* Opens 'filename' with compression filters disabled. Optionally disables the + PUBKEY filter (that insists upon properly signed files) as well. PUBKEY + filter is restored before the function returns. */ static grub_file_t -open_envblk_file (char *filename) +open_envblk_file (char *filename, int untrusted) { grub_file_t file; + char *buf = 0; if (! filename) { const char *prefix; + int len; prefix = grub_env_get ("prefix"); - if (prefix) - { - int len; - - len = grub_strlen (prefix); - filename = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); - if (! filename) - return 0; - - grub_strcpy (filename, prefix); - filename[len] = '/'; - grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG); - grub_file_filter_disable_compression (); - file = grub_file_open (filename); - grub_free (filename); - return file; - } - else + if (! prefix) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; } + + len = grub_strlen (prefix); + buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); + if (! buf) + return 0; + filename = buf; + + grub_strcpy (filename, prefix); + filename[len] = '/'; + grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG); } + /* The filters that are disabled will be re-enabled by the call to + grub_file_open() after this particular file is opened. */ grub_file_filter_disable_compression (); - return grub_file_open (filename); + if (untrusted) + grub_file_filter_disable_pubkey (); + + file = grub_file_open (filename); + + grub_free (buf); + return file; } static grub_envblk_t @@ -114,23 +122,56 @@ read_envblk_file (grub_file_t file) return envblk; } +struct grub_env_whitelist +{ + grub_size_t len; + char **list; +}; +typedef struct grub_env_whitelist grub_env_whitelist_t; + +static int +test_whitelist_membership (const char* name, + const grub_env_whitelist_t* whitelist) +{ + grub_size_t i; + + for (i = 0; i < whitelist->len; i++) + if (grub_strcmp (name, whitelist->list[i]) == 0) + return 1; /* found it */ + + return 0; /* not found */ +} + +/* Helper for grub_cmd_load_env. */ +static int +set_var (const char *name, const char *value, void *whitelist) +{ + if (! whitelist) + { + grub_env_set (name, value); + return 0; + } + + if (test_whitelist_membership (name, + (const grub_env_whitelist_t *) whitelist)) + grub_env_set (name, value); + + return 0; +} + static grub_err_t -grub_cmd_load_env (grub_extcmd_context_t ctxt, - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; + grub_env_whitelist_t whitelist; - auto int set_var (const char *name, const char *value); - int set_var (const char *name, const char *value) - { - grub_env_set (name, value); - return 0; - } + whitelist.len = argc; + whitelist.list = args; - file = open_envblk_file ((state[0].set) ? state[0].arg : 0); + /* state[0] is the -f flag; state[1] is the --skip-sig flag */ + file = open_envblk_file ((state[0].set) ? state[0].arg : 0, state[1].set); if (! file) return grub_errno; @@ -138,7 +179,8 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, if (! envblk) goto fail; - grub_envblk_iterate (envblk, set_var); + /* argc > 0 indicates caller provided a whitelist of variables to read. */ + grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var); grub_envblk_close (envblk); fail: @@ -146,6 +188,15 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, return grub_errno; } +/* Print all variables in current context. */ +static int +print_var (const char *name, const char *value, + void *hook_data __attribute__ ((unused))) +{ + grub_printf ("%s=%s\n", name, value); + return 0; +} + static grub_err_t grub_cmd_list_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), @@ -155,15 +206,7 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt, grub_file_t file; grub_envblk_t envblk; - /* Print all variables in current context. */ - auto int print_var (const char *name, const char *value); - int print_var (const char *name, const char *value) - { - grub_printf ("%s=%s\n", name, value); - return 0; - } - - file = open_envblk_file ((state[0].set) ? state[0].arg : 0); + file = open_envblk_file ((state[0].set) ? state[0].arg : 0, 0); if (! file) return grub_errno; @@ -171,7 +214,7 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt, if (! envblk) goto fail; - grub_envblk_iterate (envblk, print_var); + grub_envblk_iterate (envblk, NULL, print_var); grub_envblk_close (envblk); fail: @@ -216,10 +259,28 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, for (p = blocklists; p; p = p->next) { struct blocklist *q; + /* Check if any pair of blocks overlap. */ for (q = p->next; q; q = q->next) { - /* Check if any pair of blocks overlap. */ - if (p->sector == q->sector) + grub_disk_addr_t s1, s2; + grub_disk_addr_t e1, e2, t; + + s1 = p->sector; + e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); + + s2 = q->sector; + e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); + + if (s2 > s1) + { + t = s2; + s2 = s1; + s1 = t; + t = e2; + e2 = e1; + e1 = t; + } + if (e1 > s2) { /* This might be actually valid, but it is unbelievable that any filesystem makes such a silly allocation. */ @@ -243,9 +304,18 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, part_start = grub_partition_get_start (disk->partition); buf = grub_envblk_buffer (envblk); + char *blockbuf = NULL; + grub_size_t blockbuf_len = 0; for (p = blocklists, index = 0; p; index += p->length, p = p->next) { - char blockbuf[GRUB_DISK_SECTOR_SIZE]; + if (p->length > blockbuf_len) + { + grub_free (blockbuf); + blockbuf_len = 2 * p->length; + blockbuf = grub_malloc (blockbuf_len); + if (!blockbuf) + return grub_errno; + } if (grub_disk_read (disk, p->sector - part_start, p->offset, p->length, blockbuf)) @@ -283,49 +353,53 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, return 1; } +/* Context for grub_cmd_save_env. */ +struct grub_cmd_save_env_ctx +{ + struct blocklist *head, *tail; +}; + +/* Store blocklists in a linked list. */ +static void +save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length, + void *data) +{ + struct grub_cmd_save_env_ctx *ctx = data; + struct blocklist *block; + + block = grub_malloc (sizeof (*block)); + if (! block) + return; + + block->sector = sector; + block->offset = offset; + block->length = length; + + /* Slightly complicated, because the list should be FIFO. */ + block->next = 0; + if (ctx->tail) + ctx->tail->next = block; + ctx->tail = block; + if (! ctx->head) + ctx->head = block; +} + static grub_err_t grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; - struct blocklist *head = 0; - struct blocklist *tail = 0; - - /* Store blocklists in a linked list. */ - auto void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, - unsigned offset, - unsigned length); - void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, - unsigned offset, unsigned length) - { - struct blocklist *block; - - if (offset + length > GRUB_DISK_SECTOR_SIZE) - /* Seemingly a bug. */ - return; - - block = grub_malloc (sizeof (*block)); - if (! block) - return; - - block->sector = sector; - block->offset = offset; - block->length = length; - - /* Slightly complicated, because the list should be FIFO. */ - block->next = 0; - if (tail) - tail->next = block; - tail = block; - if (! head) - head = block; - } + struct grub_cmd_save_env_ctx ctx = { + .head = 0, + .tail = 0 + }; if (! argc) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified"); - file = open_envblk_file ((state[0].set) ? state[0].arg : 0); + file = open_envblk_file ((state[0].set) ? state[0].arg : 0, + 1 /* allow untrusted */); if (! file) return grub_errno; @@ -335,13 +409,14 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required"); } - file->read_hook = read_hook; + file->read_hook = save_env_read_hook; + file->read_hook_data = &ctx; envblk = read_envblk_file (file); file->read_hook = 0; if (! envblk) goto fail; - if (check_blocklists (envblk, head, file)) + if (check_blocklists (envblk, ctx.head, file)) goto fail; while (argc) @@ -357,17 +432,19 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) goto fail; } } + else + grub_envblk_delete (envblk, args[0]); argc--; args++; } - write_blocklists (envblk, head, file); + write_blocklists (envblk, ctx.head, file); fail: if (envblk) grub_envblk_close (envblk); - free_blocklists (head); + free_blocklists (ctx.head); grub_file_close (file); return grub_errno; } @@ -377,7 +454,8 @@ static grub_extcmd_t cmd_load, cmd_list, cmd_save; GRUB_MOD_INIT(loadenv) { cmd_load = - grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, + N_("[-f FILE] [-s|--skip-sig] [whitelisted_variable_name] [...]"), N_("Load variables from environment block file."), options); cmd_list = diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 913bb6546..0eaf83652 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -43,23 +43,24 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; +/* Helper for grub_ls_list_devices. */ +static int +grub_ls_print_devices (const char *name, void *data) +{ + int *longlist = data; + + if (*longlist) + grub_normal_print_device_info (name); + else + grub_printf ("(%s) ", name); + + return 0; +} static grub_err_t grub_ls_list_devices (int longlist) { - auto int grub_ls_print_devices (const char *name); - int grub_ls_print_devices (const char *name) - { - if (longlist) - grub_normal_print_device_info (name); - else - grub_printf ("(%s) ", name); - - return 0; - } - - grub_device_iterate (grub_ls_print_devices); + grub_device_iterate (grub_ls_print_devices, &longlist); grub_xputs ("\n"); #if 0 @@ -82,6 +83,93 @@ grub_ls_list_devices (int longlist) return 0; } +/* Context for grub_ls_list_files. */ +struct grub_ls_list_files_ctx +{ + char *dirname; + int all; + int human; +}; + +/* Helper for grub_ls_list_files. */ +static int +print_files (const char *filename, const struct grub_dirhook_info *info, + void *data) +{ + struct grub_ls_list_files_ctx *ctx = data; + + if (ctx->all || filename[0] != '.') + grub_printf ("%s%s ", filename, info->dir ? "/" : ""); + + return 0; +} + +/* Helper for grub_ls_list_files. */ +static int +print_files_long (const char *filename, const struct grub_dirhook_info *info, + void *data) +{ + struct grub_ls_list_files_ctx *ctx = data; + + if ((! ctx->all) && (filename[0] == '.')) + return 0; + + if (! info->dir) + { + grub_file_t file; + char *pathname; + + if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/') + pathname = grub_xasprintf ("%s%s", ctx->dirname, filename); + else + pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename); + + if (!pathname) + return 1; + + /* XXX: For ext2fs symlinks are detected as files while they + should be reported as directories. */ + grub_file_filter_disable_compression (); + file = grub_file_open (pathname); + if (! file) + { + grub_errno = 0; + grub_free (pathname); + return 0; + } + + if (! ctx->human) + grub_printf ("%-12llu", (unsigned long long) file->size); + else + grub_printf ("%-12s", grub_get_human_size (file->size, + GRUB_HUMAN_SIZE_SHORT)); + grub_file_close (file); + grub_free (pathname); + } + else + grub_printf ("%-12s", _("DIR")); + + if (info->mtimeset) + { + struct grub_datetime datetime; + grub_unixtime2datetime (info->mtime, &datetime); + if (ctx->human) + grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", + datetime.year, datetime.month, datetime.day, + datetime.hour, datetime.minute, + datetime.second, + grub_get_weekday_name (&datetime)); + else + grub_printf (" %04d%02d%02d%02d%02d%02d ", + datetime.year, datetime.month, + datetime.day, datetime.hour, + datetime.minute, datetime.second); + } + grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); + + return 0; +} + static grub_err_t grub_ls_list_files (char *dirname, int longlist, int all, int human) { @@ -90,107 +178,6 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) const char *path; grub_device_t dev; - auto int print_files (const char *filename, - const struct grub_dirhook_info *info); - auto int print_files_long (const char *filename, - const struct grub_dirhook_info *info); - - int print_files (const char *filename, const struct grub_dirhook_info *info) - { - if (all || filename[0] != '.') - grub_printf ("%s%s ", filename, info->dir ? "/" : ""); - - return 0; - } - - int print_files_long (const char *filename, - const struct grub_dirhook_info *info) - { - if ((! all) && (filename[0] == '.')) - return 0; - - if (! info->dir) - { - grub_file_t file; - char *pathname; - - if (dirname[grub_strlen (dirname) - 1] == '/') - pathname = grub_xasprintf ("%s%s", dirname, filename); - else - pathname = grub_xasprintf ("%s/%s", dirname, filename); - - if (!pathname) - return 1; - - /* XXX: For ext2fs symlinks are detected as files while they - should be reported as directories. */ - grub_file_filter_disable_compression (); - file = grub_file_open (pathname); - if (! file) - { - grub_errno = 0; - grub_free (pathname); - return 0; - } - - if (! human) - grub_printf ("%-12llu", (unsigned long long) file->size); - else - { - grub_uint64_t fsize = file->size * 100ULL; - grub_uint64_t fsz = file->size; - int units = 0; - char buf[20]; - - while (fsz / 1024) - { - fsize = (fsize + 512) / 1024; - fsz /= 1024; - units++; - } - - if (units) - { - grub_uint64_t whole, fraction; - - whole = grub_divmod64 (fsize, 100, &fraction); - grub_snprintf (buf, sizeof (buf), - "%" PRIuGRUB_UINT64_T - ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction, - grub_human_sizes[units]); - grub_printf ("%-12s", buf); - } - else - grub_printf ("%-12llu", (unsigned long long) file->size); - - } - grub_file_close (file); - grub_free (pathname); - } - else - grub_printf ("%-12s", _("DIR")); - - if (info->mtimeset) - { - struct grub_datetime datetime; - grub_unixtime2datetime (info->mtime, &datetime); - if (human) - grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", - datetime.year, datetime.month, datetime.day, - datetime.hour, datetime.minute, - datetime.second, - grub_get_weekday_name (&datetime)); - else - grub_printf (" %04d%02d%02d%02d%02d%02d ", - datetime.year, datetime.month, - datetime.day, datetime.hour, - datetime.minute, datetime.second); - } - grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); - - return 0; - } - device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); if (! dev) @@ -218,10 +205,16 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) } else if (fs) { + struct grub_ls_list_files_ctx ctx = { + .dirname = dirname, + .all = all, + .human = human + }; + if (longlist) - (fs->dir) (dev, path, print_files_long); + (fs->dir) (dev, path, print_files_long, &ctx); else - (fs->dir) (dev, path, print_files); + (fs->dir) (dev, path, print_files, &ctx); if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && path[grub_strlen (path) - 1] != '/') @@ -247,9 +240,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) all = 1; grub_memset (&info, 0, sizeof (info)); if (longlist) - print_files_long (p, &info); + print_files_long (p, &info, &ctx); else - print_files (p, &info); + print_files (p, &info, &ctx); grub_free (dirname); } diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index 07c3f0d55..082491405 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -44,7 +44,8 @@ static void disp_acpi_table (struct grub_acpi_table_header *t) { print_field (t->signature); - grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u chksum=0x%02x (%s) OEM=", t->length, t->revision, t->checksum, + grub_byte_checksum (t, t->length) == 0 ? "valid" : "invalid"); print_field (t->oemid); print_field (t->oemtable); grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); @@ -66,39 +67,87 @@ disp_madt_table (struct grub_acpi_madt *t) d = t->entries; for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len)) { - grub_printf (" type=%x l=%u ", d->type, d->len); - switch (d->type) { + case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC: + { + struct grub_acpi_madt_entry_lapic *dt = (void *) d; + grub_printf (" LAPIC ACPI_ID=%02x APIC_ID=%02x Flags=%08x\n", + dt->acpiid, dt->apicid, dt->flags); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + break; + } + + case GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC: + { + struct grub_acpi_madt_entry_ioapic *dt = (void *) d; + grub_printf (" IOAPIC ID=%02x address=%08x GSI=%08x\n", + dt->id, dt->address, dt->global_sys_interrupt); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad) + grub_printf (" non-zero pad: %02x\n", dt->pad); + break; + } + case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE: { struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d; - grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", + grub_printf (" Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", dt->bus, dt->source, dt->global_sys_interrupt, dt->flags); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); } break; + + case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI: + { + struct grub_acpi_madt_entry_lapic_nmi *dt = (void *) d; + grub_printf (" LAPIC_NMI ACPI_ID=%02x Flags=%04x lint=%02x\n", + dt->acpiid, dt->flags, dt->lint); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + break; + } + case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC: { struct grub_acpi_madt_entry_sapic *dt = (void *) d; - grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T + grub_printf (" IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T "\n", dt->id, dt->global_sys_interrupt_base, dt->addr); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad) + grub_printf (" non-zero pad: %02x\n", dt->pad); + } break; case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC: { struct grub_acpi_madt_entry_lsapic *dt = (void *) d; - grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", + grub_printf (" LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", dt->cpu_id, dt->id, dt->eid, dt->flags); if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED) grub_printf (" Enabled\n"); else grub_printf (" Disabled\n"); if (d->len > sizeof (struct grub_acpi_madt_entry_sapic)) - grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, + grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, dt->cpu_uid_str); + if (dt->hdr.len != sizeof (*dt) + grub_strlen ((char *) dt->cpu_uid_str) + 1) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad[0] || dt->pad[1] || dt->pad[2]) + grub_printf (" non-zero pad: %02x%02x%02x\n", dt->pad[0], dt->pad[1], dt->pad[2]); } break; case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE: @@ -107,17 +156,18 @@ disp_madt_table (struct grub_acpi_madt *t) static const char * const platint_type[] = {"Nul", "PMI", "INIT", "CPEI"}; - grub_printf ("Platform INT flags=%04x type=%02x (%s)" + grub_printf (" Platform INT flags=%04x type=%02x (%s)" " ID=%02x EID=%02x\n", dt->flags, dt->inttype, (dt->inttype < ARRAY_SIZE (platint_type)) ? platint_type[dt->inttype] : "??", dt->cpu_id, dt->cpu_eid); - grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", + grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", dt->sapic_vector, dt->global_sys_int, dt->src_flags); } break; default: + grub_printf (" type=%x l=%u ", d->type, d->len); grub_printf (" ??\n"); } } @@ -182,7 +232,7 @@ static void disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) { print_field (rsdp->signature); - grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum); + grub_printf ("chksum:%02x (%s), OEM-ID: ", rsdp->checksum, grub_byte_checksum (rsdp, sizeof (*rsdp)) == 0 ? "valid" : "invalid"); print_field (rsdp->oemid); grub_printf ("rev=%d\n", rsdp->revision); grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr); @@ -192,8 +242,13 @@ static void disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) { disp_acpi_rsdpv1 (&rsdp->rsdpv1); - grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, + grub_printf ("len=%d chksum=%02x (%s) XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, rsdp->checksum, grub_byte_checksum (rsdp, rsdp->length) == 0 ? "valid" : "invalid", rsdp->xsdt_addr); + if (rsdp->length != sizeof (*rsdp)) + grub_printf (" length mismatch %d != %d\n", rsdp->length, + (int) sizeof (*rsdp)); + if (rsdp->reserved[0] || rsdp->reserved[1] || rsdp->reserved[2]) + grub_printf (" non-zero reserved %02x%02x%02x\n", rsdp->reserved[0], rsdp->reserved[1], rsdp->reserved[2]); } static const struct grub_arg_option options[] = { diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index bd32c338e..4b504fd28 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -21,9 +21,11 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); +#ifndef GRUB_MACHINE_EMU static const char *names[] = { [GRUB_MEMORY_AVAILABLE] = N_("available RAM"), @@ -35,30 +37,33 @@ static const char *names[] = is required to save accross hibernations. */ [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"), [GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"), - [GRUB_MEMORY_CODE] = N_("RAM holding firmware code"), - [GRUB_MEMORY_HOLE] = N_("Address range not associated with RAM") + [GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"), + [GRUB_MEMORY_CODE] = N_("RAM holding firmware code") }; +/* Helper for grub_cmd_lsmmap. */ +static int +lsmmap_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + if (type < (int) ARRAY_SIZE (names) && type >= 0 && names[type]) + grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"), + (long long) addr, (long long) size, _(names[type])); + else + grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"), + (long long) addr, (long long) size, type); + return 0; +} +#endif + static grub_err_t grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_memory_type_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_memory_type_t type) - { - if (type < ARRAY_SIZE (names) && names[type]) - grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"), - (long long) addr, (long long) size, _(names[type])); - else - grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"), - (long long) addr, (long long) size, type); - return 0; - } #ifndef GRUB_MACHINE_EMU - grub_machine_mmap_iterate (hook); + grub_machine_mmap_iterate (lsmmap_hook, NULL); #endif return 0; diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index 9f836298f..65213a372 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -126,8 +127,9 @@ static const struct grub_arg_option options[] = static int iospace; -static int NESTED_FUNC_ATTR -grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t class; const char *sclass; @@ -218,7 +220,7 @@ grub_cmd_lspci (grub_extcmd_context_t ctxt, char **args __attribute__ ((unused))) { iospace = ctxt->state[0].set; - grub_pci_iterate (grub_lspci_iter); + grub_pci_iterate (grub_lspci_iter, NULL); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c new file mode 100644 index 000000000..33b6b99ea --- /dev/null +++ b/grub-core/commands/nativedisk.c @@ -0,0 +1,317 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const char *modnames_def[] = { + /* FIXME: autogenerate this. */ +#if defined (__i386__) || defined (__x86_64__) || defined (GRUB_MACHINE_MIPS_LOONGSON) + "pata", "ahci", "usbms", "ohci", "uhci", "ehci" +#elif defined (GRUB_MACHINE_MIPS_QEMU_MIPS) + "pata" +#else +#error "Fill this" +#endif + }; + +static grub_err_t +get_uuid (const char *name, char **uuid, int getnative) +{ + grub_device_t dev; + grub_fs_t fs = 0; + + *uuid = 0; + + dev = grub_device_open (name); + if (!dev) + return grub_errno; + + if (!dev->disk) + { + grub_dprintf ("nativedisk", "Skipping non-disk\n"); + return 0; + } + + switch (dev->disk->dev->id) + { + /* Firmware disks. */ + case GRUB_DISK_DEVICE_BIOSDISK_ID: + case GRUB_DISK_DEVICE_OFDISK_ID: + case GRUB_DISK_DEVICE_EFIDISK_ID: + case GRUB_DISK_DEVICE_NAND_ID: + case GRUB_DISK_DEVICE_ARCDISK_ID: + case GRUB_DISK_DEVICE_HOSTDISK_ID: + case GRUB_DISK_DEVICE_UBOOTDISK_ID: + break; + + /* Native disks. */ + case GRUB_DISK_DEVICE_ATA_ID: + case GRUB_DISK_DEVICE_SCSI_ID: + case GRUB_DISK_DEVICE_XEN: + if (getnative) + break; + + /* Virtual disks. */ + /* GRUB dynamically generated files. */ + case GRUB_DISK_DEVICE_PROCFS_ID: + /* To access through host OS routines (grub-emu only). */ + case GRUB_DISK_DEVICE_HOST_ID: + /* To access coreboot roms. */ + case GRUB_DISK_DEVICE_CBFSDISK_ID: + /* GRUB-only memdisk. Can't match any of firmware devices. */ + case GRUB_DISK_DEVICE_MEMDISK_ID: + grub_dprintf ("nativedisk", "Skipping native disk %s\n", + dev->disk->name); + return 0; + + /* FIXME: those probably need special handling. */ + case GRUB_DISK_DEVICE_LOOPBACK_ID: + case GRUB_DISK_DEVICE_DISKFILTER_ID: + case GRUB_DISK_DEVICE_CRYPTODISK_ID: + break; + } + if (dev) + fs = grub_fs_probe (dev); + if (!fs) + { + grub_device_close (dev); + return grub_errno; + } + if (!fs->uuid || fs->uuid (dev, uuid) || !*uuid) + { + grub_device_close (dev); + + if (!grub_errno) + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("%s does not support UUIDs"), fs->name); + + return grub_errno; + } + grub_device_close (dev); + return GRUB_ERR_NONE; +} + +struct search_ctx +{ + char *root_uuid; + char *prefix_uuid; + const char *prefix_path; + int prefix_found, root_found; +}; + +static int +iterate_device (const char *name, void *data) +{ + struct search_ctx *ctx = data; + char *cur_uuid; + + if (get_uuid (name, &cur_uuid, 1)) + { + if (grub_errno == GRUB_ERR_UNKNOWN_FS) + grub_errno = 0; + grub_print_error (); + return 0; + } + + grub_dprintf ("nativedisk", "checking %s: %s\n", name, + cur_uuid); + if (ctx->prefix_uuid && grub_strcasecmp (cur_uuid, ctx->prefix_uuid) == 0) + { + char *prefix; + prefix = grub_xasprintf ("(%s)/%s", name, ctx->prefix_path); + grub_env_set ("prefix", prefix); + grub_free (prefix); + ctx->prefix_found = 1; + } + if (ctx->root_uuid && grub_strcasecmp (cur_uuid, ctx->root_uuid) == 0) + { + grub_env_set ("root", name); + ctx->root_found = 1; + } + return ctx->prefix_found && ctx->root_found; +} + +static grub_err_t +grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args_in) +{ + char *uuid_root = 0, *uuid_prefix, *prefdev = 0; + const char *prefix = 0; + const char *path_prefix = 0; + int mods_loaded = 0; + grub_dl_t *mods; + const char **args; + int i; + + if (argc == 0) + { + argc = ARRAY_SIZE (modnames_def); + args = modnames_def; + } + else + args = (const char **) args_in; + + prefix = grub_env_get ("prefix"); + + if (! prefix) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); + + if (prefix) + path_prefix = (prefix[0] == '(') ? grub_strchr (prefix, ')') : NULL; + if (path_prefix) + path_prefix++; + else + path_prefix = prefix; + + mods = grub_malloc (argc * sizeof (mods[0])); + if (!mods) + return grub_errno; + + if (get_uuid (NULL, &uuid_root, 0)) + return grub_errno; + + prefdev = grub_file_get_device_name (prefix); + if (grub_errno) + { + grub_print_error (); + prefdev = 0; + } + + if (get_uuid (prefdev, &uuid_prefix, 0)) + { + grub_free (uuid_root); + return grub_errno; + } + + grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n", + uuid_prefix, uuid_root); + + for (mods_loaded = 0; mods_loaded < argc; mods_loaded++) + { + char *filename; + grub_dl_t mod; + grub_file_t file = NULL; + grub_ssize_t size; + void *core = 0; + + mod = grub_dl_get (args[mods_loaded]); + if (mod) + { + mods[mods_loaded] = 0; + continue; + } + + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod", + prefix, args[mods_loaded]); + if (! filename) + goto fail; + + file = grub_file_open (filename); + grub_free (filename); + if (! file) + goto fail; + + size = grub_file_size (file); + core = grub_malloc (size); + if (! core) + { + grub_file_close (file); + goto fail; + } + + if (grub_file_read (file, core, size) != (grub_ssize_t) size) + { + grub_file_close (file); + grub_free (core); + goto fail; + } + + grub_file_close (file); + + mods[mods_loaded] = grub_dl_load_core_noinit (core, size); + if (! mods[mods_loaded]) + goto fail; + } + + for (i = 0; i < argc; i++) + if (mods[i]) + grub_dl_init (mods[i]); + + if (uuid_prefix || uuid_root) + { + struct search_ctx ctx; + grub_fs_autoload_hook_t saved_autoload; + + /* No need to autoload FS since obviously we already have the necessary fs modules. */ + saved_autoload = grub_fs_autoload_hook; + grub_fs_autoload_hook = 0; + + ctx.root_uuid = uuid_root; + ctx.prefix_uuid = uuid_prefix; + ctx.prefix_path = path_prefix; + ctx.prefix_found = !uuid_prefix; + ctx.root_found = !uuid_root; + + /* FIXME: try to guess the correct values. */ + grub_device_iterate (iterate_device, &ctx); + + grub_fs_autoload_hook = saved_autoload; + } + grub_free (uuid_root); + grub_free (uuid_prefix); + + return GRUB_ERR_NONE; + + fail: + grub_free (uuid_root); + grub_free (uuid_prefix); + + for (i = 0; i < mods_loaded; i++) + if (mods[i]) + { + mods[i]->fini = 0; + grub_dl_unload (mods[i]); + } + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(nativedisk) +{ + cmd = grub_register_command ("nativedisk", grub_cmd_nativedisk, N_("[MODULE1 MODULE2 ...]"), + N_("Switch to native disk drivers. If no modules are specified default set (pata,ahci,usbms,ohci,uhci,ehci) is used")); +} + +GRUB_MOD_FINI(nativedisk) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index fadf87327..f144c511b 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -94,6 +94,50 @@ grub_parttool_unregister (int handle) grub_dl_unref (mymod); } +static grub_err_t +show_help (grub_device_t dev) +{ + int found = 0; + struct grub_parttool *cur; + + for (cur = parts; cur; cur = cur->next) + if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0) + { + struct grub_parttool_argdesc *curarg; + found = 1; + for (curarg = cur->args; curarg->name; curarg++) + { + int spacing = 20; + + spacing -= grub_strlen (curarg->name); + grub_printf ("%s", curarg->name); + + switch (curarg->type) + { + case GRUB_PARTTOOL_ARG_BOOL: + grub_printf ("+/-"); + spacing -= 3; + break; + + case GRUB_PARTTOOL_ARG_VAL: + grub_xputs (_("=VAL")); + spacing -= 4; + break; + + case GRUB_PARTTOOL_ARG_END: + break; + } + while (spacing-- > 0) + grub_printf (" "); + grub_puts_ (curarg->desc); + } + } + if (! found) + grub_printf_ (N_("Sorry no parttool is available for %s\n"), + dev->disk->partition->partmap->name); + return GRUB_ERR_NONE; +} + static grub_err_t grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) @@ -104,48 +148,6 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), int i, j; grub_err_t err = GRUB_ERR_NONE; - auto grub_err_t show_help (void); - grub_err_t show_help (void) - { - int found = 0; - for (cur = parts; cur; cur = cur->next) - if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0) - { - struct grub_parttool_argdesc *curarg; - found = 1; - for (curarg = cur->args; curarg->name; curarg++) - { - int spacing = 20; - - spacing -= grub_strlen (curarg->name); - grub_printf ("%s", curarg->name); - - switch (curarg->type) - { - case GRUB_PARTTOOL_ARG_BOOL: - grub_printf ("+/-"); - spacing -= 3; - break; - - case GRUB_PARTTOOL_ARG_VAL: - grub_xputs (_("=VAL")); - spacing -= 4; - break; - - case GRUB_PARTTOOL_ARG_END: - break; - } - while (spacing-- > 0) - grub_printf (" "); - grub_puts_ (curarg->desc); - } - } - if (! found) - grub_printf_ (N_("Sorry no parttool is available for %s\n"), - dev->disk->partition->partmap->name); - return GRUB_ERR_NONE; - } - if (argc < 1) { grub_puts_ (helpmsg); @@ -177,7 +179,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } /* Load modules. */ - if (! grub_no_autoload) + if (! grub_no_modules) { const char *prefix; prefix = grub_env_get ("prefix"); @@ -241,11 +243,11 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } if (argc == 1) - return show_help (); + return show_help (dev); for (i = 1; i < argc; i++) if (grub_strcmp (args[i], "help") == 0) - return show_help (); + return show_help (dev); parsed = (int *) grub_zalloc (argc * sizeof (int)); diff --git a/grub-core/commands/pcidump.c b/grub-core/commands/pcidump.c new file mode 100644 index 000000000..223d86a74 --- /dev/null +++ b/grub-core/commands/pcidump.c @@ -0,0 +1,175 @@ +/* lspci.c - List PCI devices. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct iter_cxt +{ + grub_uint32_t pciid_check_mask, pciid_check_value; + int bus, device, function; + int check_bus, check_device, check_function; +}; + +static const struct grub_arg_option options[] = + { + {0, 'd', 0, N_("Select device by vendor and device IDs."), + N_("[vendor]:[device]"), ARG_TYPE_STRING}, + {0, 's', 0, N_("Select device by its position on the bus."), + N_("[bus]:[slot][.func]"), ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +static int +grub_pcidump_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data) +{ + struct iter_cxt *ctx = data; + grub_pci_address_t addr; + int i; + + if ((pciid & ctx->pciid_check_mask) != ctx->pciid_check_value) + return 0; + + if (ctx->check_bus && grub_pci_get_bus (dev) != ctx->bus) + return 0; + + if (ctx->check_device && grub_pci_get_device (dev) != ctx->device) + return 0; + + if (ctx->check_function && grub_pci_get_function (dev) != ctx->function) + return 0; + + for (i = 0; i < 256; i += 4) + { + addr = grub_pci_make_address (dev, i); + grub_printf ("%08x ", grub_pci_read (addr)); + if ((i & 0xc) == 0xc) + grub_printf ("\n"); + } + + return 0; +} + +static grub_err_t +grub_cmd_pcidump (grub_extcmd_context_t ctxt, + int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) +{ + const char *ptr; + struct iter_cxt ctx = + { + .pciid_check_value = 0, + .pciid_check_mask = 0, + .check_bus = 0, + .check_device = 0, + .check_function = 0, + .bus = 0, + .function = 0, + .device = 0 + }; + + if (ctxt->state[0].set) + { + ptr = ctxt->state[0].arg; + ctx.pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = ctxt->state[0].arg; + } + else + ctx.pciid_check_mask |= 0xffff; + if (grub_errno) + return grub_errno; + if (*ptr != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); + ptr++; + ctx.pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff) + << 16; + if (grub_errno == GRUB_ERR_BAD_NUMBER) + grub_errno = GRUB_ERR_NONE; + else + ctx.pciid_check_mask |= 0xffff0000; + } + + ctx.pciid_check_value &= ctx.pciid_check_mask; + + if (ctxt->state[1].set) + { + const char *optr; + + ptr = ctxt->state[1].arg; + optr = ptr; + ctx.bus = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = optr; + } + else + ctx.check_bus = 1; + if (grub_errno) + return grub_errno; + if (*ptr != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); + ptr++; + optr = ptr; + ctx.device = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = optr; + } + else + ctx.check_device = 1; + if (*ptr == '.') + { + ptr++; + ctx.function = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + return grub_errno; + ctx.check_function = 1; + } + } + + grub_pci_iterate (grub_pcidump_iter, &ctx); + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(pcidump) +{ + cmd = grub_register_extcmd ("pcidump", grub_cmd_pcidump, 0, + N_("[-s POSITION] [-d DEVICE]"), + N_("Dump PCI configuration space."), options); +} + +GRUB_MOD_FINI(pcidump) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index eeece876d..cf2793e1d 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -83,6 +83,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) grub_env_set (state[0].arg, val); else grub_printf ("%s", val); + grub_device_close (dev); return GRUB_ERR_NONE; } if (state[2].set) @@ -94,6 +95,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) grub_env_set (state[0].arg, val); else grub_printf ("%s", val); + grub_device_close (dev); return GRUB_ERR_NONE; } fs = grub_fs_probe (dev); @@ -105,6 +107,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) grub_env_set (state[0].arg, fs->name); else grub_printf ("%s", fs->name); + grub_device_close (dev); return GRUB_ERR_NONE; } if (state[4].set) @@ -125,6 +128,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) else grub_printf ("%s", uuid); grub_free (uuid); + grub_device_close (dev); return GRUB_ERR_NONE; } if (state[5].set) @@ -147,8 +151,10 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) else grub_printf ("%s", label); grub_free (label); + grub_device_close (dev); return GRUB_ERR_NONE; } + grub_device_close (dev); return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised target"); } diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c index b0706d069..f00b184c8 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -46,6 +46,18 @@ static const struct grub_arg_option options[] = { 0, 0, 0, 0, 0, 0 } }; +static grub_err_t +setvar (char *str, char *v, regmatch_t *m) +{ + char ch; + grub_err_t err; + ch = str[m->rm_eo]; + str[m->rm_eo] = '\0'; + err = grub_env_set (v, str + m->rm_so); + str[m->rm_eo] = ch; + return err; +} + static grub_err_t set_matches (char **varnames, char *str, grub_size_t nmatches, regmatch_t *matches) @@ -56,18 +68,9 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, grub_err_t err; unsigned long j; - auto void setvar (char *v, regmatch_t *m); - void setvar (char *v, regmatch_t *m) - { - char ch; - ch = str[m->rm_eo]; - str[m->rm_eo] = '\0'; - err = grub_env_set (v, str + m->rm_so); - str[m->rm_eo] = ch; - } - for (i = 0; varnames && varnames[i]; i++) { + err = GRUB_ERR_NONE; p = grub_strchr (varnames[i], ':'); if (! p) { @@ -75,7 +78,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, if (nmatches < 2 || matches[1].rm_so == -1) grub_env_unset (varnames[i]); else - setvar (varnames[i], &matches[1]); + err = setvar (str, varnames[i], &matches[1]); } else { @@ -87,7 +90,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, if (nmatches <= j || matches[j].rm_so == -1) grub_env_unset (p + 1); else - setvar (p + 1, &matches[j]); + err = setvar (str, p + 1, &matches[j]); } if (err != GRUB_ERR_NONE) diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index 5e9b7e381..16143a34c 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -42,23 +42,29 @@ struct cache_entry static struct cache_entry *cache; -void -FUNC_NAME (const char *key, const char *var, int no_floppy, - char **hints, unsigned nhints) +/* Context for FUNC_NAME. */ +struct search_ctx { - int count = 0; - int is_cache = 0; - grub_fs_autoload_hook_t saved_autoload; + const char *key; + const char *var; + int no_floppy; + char **hints; + unsigned nhints; + int count; + int is_cache; +}; - auto int iterate_device (const char *name); - int iterate_device (const char *name) - { - int found = 0; +/* Helper for FUNC_NAME. */ +static int +iterate_device (const char *name, void *data) +{ + struct search_ctx *ctx = data; + int found = 0; - /* Skip floppy drives when requested. */ - if (no_floppy && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') - return 0; + /* Skip floppy drives when requested. */ + if (ctx->no_floppy && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') + return 0; #ifdef DO_SEARCH_FS_UUID #define compare_fn grub_strcasecmp @@ -67,34 +73,34 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, #endif #ifdef DO_SEARCH_FILE - { - char *buf; - grub_file_t file; + { + char *buf; + grub_file_t file; - buf = grub_xasprintf ("(%s)%s", name, key); - if (! buf) - return 1; + buf = grub_xasprintf ("(%s)%s", name, ctx->key); + if (! buf) + return 1; - grub_file_filter_disable_compression (); - file = grub_file_open (buf); - if (file) - { - found = 1; - grub_file_close (file); - } - grub_free (buf); - } + grub_file_filter_disable_compression (); + file = grub_file_open (buf); + if (file) + { + found = 1; + grub_file_close (file); + } + grub_free (buf); + } #else - { - /* SEARCH_FS_UUID or SEARCH_LABEL */ - grub_device_t dev; - grub_fs_t fs; - char *quid; + { + /* SEARCH_FS_UUID or SEARCH_LABEL */ + grub_device_t dev; + grub_fs_t fs; + char *quid; - dev = grub_device_open (name); - if (dev) - { - fs = grub_fs_probe (dev); + dev = grub_device_open (name); + if (dev) + { + fs = grub_fs_probe (dev); #ifdef DO_SEARCH_FS_UUID #define read_fn uuid @@ -102,173 +108,191 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, #define read_fn label #endif - if (fs && fs->read_fn) - { - fs->read_fn (dev, &quid); + if (fs && fs->read_fn) + { + fs->read_fn (dev, &quid); - if (grub_errno == GRUB_ERR_NONE && quid) - { - if (compare_fn (quid, key) == 0) - found = 1; + if (grub_errno == GRUB_ERR_NONE && quid) + { + if (compare_fn (quid, ctx->key) == 0) + found = 1; - grub_free (quid); - } - } + grub_free (quid); + } + } - grub_device_close (dev); - } - } + grub_device_close (dev); + } + } #endif - if (!is_cache && found && count == 0) - { - struct cache_entry *cache_ent; - cache_ent = grub_malloc (sizeof (*cache_ent)); - if (cache_ent) - { - cache_ent->key = grub_strdup (key); - cache_ent->value = grub_strdup (name); - if (cache_ent->value && cache_ent->key) - { - cache_ent->next = cache; - cache = cache_ent; - } - else - { - grub_free (cache_ent->value); - grub_free (cache_ent->key); - grub_free (cache_ent); - grub_errno = GRUB_ERR_NONE; - } - } - else - grub_errno = GRUB_ERR_NONE; - } + if (!ctx->is_cache && found && ctx->count == 0) + { + struct cache_entry *cache_ent; + cache_ent = grub_malloc (sizeof (*cache_ent)); + if (cache_ent) + { + cache_ent->key = grub_strdup (ctx->key); + cache_ent->value = grub_strdup (name); + if (cache_ent->value && cache_ent->key) + { + cache_ent->next = cache; + cache = cache_ent; + } + else + { + grub_free (cache_ent->value); + grub_free (cache_ent->key); + grub_free (cache_ent); + grub_errno = GRUB_ERR_NONE; + } + } + else + grub_errno = GRUB_ERR_NONE; + } - if (found) - { - count++; - if (var) - grub_env_set (var, name); - else - grub_printf (" %s", name); - } + if (found) + { + ctx->count++; + if (ctx->var) + grub_env_set (ctx->var, name); + else + grub_printf (" %s", name); + } - grub_errno = GRUB_ERR_NONE; - return (found && var); - } + grub_errno = GRUB_ERR_NONE; + return (found && ctx->var); +} - auto int part_hook (grub_disk_t disk, const grub_partition_t partition); - int part_hook (grub_disk_t disk, const grub_partition_t partition) - { - char *partition_name, *devname; - int ret; +/* Helper for FUNC_NAME. */ +static int +part_hook (grub_disk_t disk, const grub_partition_t partition, void *data) +{ + struct search_ctx *ctx = data; + char *partition_name, *devname; + int ret; - partition_name = grub_partition_get_name (partition); - if (! partition_name) - return 1; + partition_name = grub_partition_get_name (partition); + if (! partition_name) + return 1; - devname = grub_xasprintf ("%s,%s", disk->name, partition_name); - grub_free (partition_name); - if (!devname) - return 1; - ret = iterate_device (devname); - grub_free (devname); + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 1; + ret = iterate_device (devname, ctx); + grub_free (devname); - return ret; - } + return ret; +} - auto void try (void); - void try (void) - { - unsigned i; - struct cache_entry **prev; - struct cache_entry *cache_ent; +/* Helper for FUNC_NAME. */ +static void +try (struct search_ctx *ctx) +{ + unsigned i; + struct cache_entry **prev; + struct cache_entry *cache_ent; - for (prev = &cache, cache_ent = *prev; cache_ent; - prev = &cache_ent->next, cache_ent = *prev) - if (compare_fn (cache_ent->key, key) == 0) - break; - if (cache_ent) - { - is_cache = 1; - if (iterate_device (cache_ent->value)) - { - is_cache = 0; + for (prev = &cache, cache_ent = *prev; cache_ent; + prev = &cache_ent->next, cache_ent = *prev) + if (compare_fn (cache_ent->key, ctx->key) == 0) + break; + if (cache_ent) + { + ctx->is_cache = 1; + if (iterate_device (cache_ent->value, ctx)) + { + ctx->is_cache = 0; + return; + } + ctx->is_cache = 0; + /* Cache entry was outdated. Remove it. */ + if (!ctx->count) + { + grub_free (cache_ent->key); + grub_free (cache_ent->value); + grub_free (cache_ent); + *prev = cache_ent->next; + } + } + + for (i = 0; i < ctx->nhints; i++) + { + char *end; + if (!ctx->hints[i][0]) + continue; + end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1; + if (*end == ',') + *end = 0; + if (iterate_device (ctx->hints[i], ctx)) + { + if (!*end) + *end = ','; + return; + } + if (!*end) + { + grub_device_t dev; + int ret; + dev = grub_device_open (ctx->hints[i]); + if (!dev) + { + if (!*end) + *end = ','; + continue; + } + if (!dev->disk) + { + grub_device_close (dev); + if (!*end) + *end = ','; + continue; + } + ret = grub_partition_iterate (dev->disk, part_hook, ctx); + if (!*end) + *end = ','; + grub_device_close (dev); + if (ret) return; - } - is_cache = 0; - /* Cache entry was outdated. Remove it. */ - if (!count) - { - grub_free (cache_ent->key); - grub_free (cache_ent->value); - grub_free (cache_ent); - *prev = cache_ent->next; - } - } + } + } + grub_device_iterate (iterate_device, ctx); +} - for (i = 0; i < nhints; i++) - { - char *end; - if (!hints[i][0]) - continue; - end = hints[i] + grub_strlen (hints[i]) - 1; - if (*end == ',') - *end = 0; - if (iterate_device (hints[i])) - { - if (!*end) - *end = ','; - return; - } - if (!*end) - { - grub_device_t dev; - int ret; - dev = grub_device_open (hints[i]); - if (!dev) - { - if (!*end) - *end = ','; - continue; - } - if (!dev->disk) - { - grub_device_close (dev); - if (!*end) - *end = ','; - continue; - } - ret = grub_partition_iterate (dev->disk, part_hook); - if (!*end) - *end = ','; - grub_device_close (dev); - if (ret) - return; - } - } - grub_device_iterate (iterate_device); - } +void +FUNC_NAME (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints) +{ + struct search_ctx ctx = { + .key = key, + .var = var, + .no_floppy = no_floppy, + .hints = hints, + .nhints = nhints, + .count = 0, + .is_cache = 0 + }; + grub_fs_autoload_hook_t saved_autoload; /* First try without autoloading if we're setting variable. */ if (var) { saved_autoload = grub_fs_autoload_hook; grub_fs_autoload_hook = 0; - try (); + try (&ctx); /* Restore autoload hook. */ grub_fs_autoload_hook = saved_autoload; /* Retry with autoload if nothing found. */ - if (grub_errno == GRUB_ERR_NONE && count == 0) - try (); + if (grub_errno == GRUB_ERR_NONE && ctx.count == 0) + try (&ctx); } else - try (); + try (&ctx); - if (grub_errno == GRUB_ERR_NONE && count == 0) + if (grub_errno == GRUB_ERR_NONE && ctx.count == 0) grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); } diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index fcfec4058..d5bc97d60 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -83,8 +83,9 @@ static int regsize; static grub_uint16_t regaddr; static const char *varname; -static int NESTED_FUNC_ATTR -grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t regval = 0; grub_pci_address_t addr; @@ -128,7 +129,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (!write_mask) { - grub_printf (_("Register %x of %d:%d.%d is %x\n"), regaddr, + grub_printf (_("Register %x of %x:%02x.%x is %x\n"), regaddr, grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), @@ -320,7 +321,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) return grub_error (GRUB_ERR_BAD_ARGUMENT, "option -v isn't valid for writes"); - grub_pci_iterate (grub_setpci_iter); + grub_pci_iterate (grub_setpci_iter, NULL); return GRUB_ERR_NONE; } @@ -330,7 +331,7 @@ GRUB_MOD_INIT(setpci) { cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0, N_("[-s POSITION] [-d DEVICE] [-v VAR] " - "[REGISTER][=VALUE[:MASK]]"), + "REGISTER[=VALUE[:MASK]]"), N_("Manipulate PCI devices."), options); } diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index 0294bf946..96a6a9e17 100644 --- a/grub-core/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -34,7 +34,7 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static grub_uint16_t *pos; +static struct grub_term_coordinate *pos; static void do_print (int n) @@ -103,6 +103,8 @@ grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args) return 0; } + grub_refresh (); + pos = grub_term_save_pos (); for (; n; n--) diff --git a/grub-core/commands/terminal.c b/grub-core/commands/terminal.c index 425a41126..3002186d2 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -108,9 +108,9 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, if (term) break; if (again) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), - args[i]); + args[i]); for (aut = autoloads; aut; aut = aut->next) if (grub_strcmp (args[i], aut->name) == 0 || (grub_strcmp (args[i], "ofconsole") == 0 @@ -126,6 +126,14 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, grub_errno = GRUB_ERR_NONE; break; } + if (grub_memcmp (args[i], "serial_usb", + sizeof ("serial_usb") - 1) == 0 + && grub_term_poll_usb) + { + grub_term_poll_usb (1); + again = 1; + continue; + } if (!aut) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c index 3a0e0e069..c98c13d8c 100644 --- a/grub-core/commands/test.c +++ b/grub-core/commands/test.c @@ -38,114 +38,125 @@ grub_strtosl (char *arg, char **end, int base) return grub_strtoul (arg, end, base); } +/* Context for test_parse. */ +struct test_parse_ctx +{ + int invert; + int or, and; + int file_exists; + struct grub_dirhook_info file_info; + char *filename; +}; + +/* Take care of discarding and inverting. */ +static void +update_val (int val, struct test_parse_ctx *ctx) +{ + ctx->and = ctx->and && (ctx->invert ? ! val : val); + ctx->invert = 0; +} + +/* A hook for iterating directories. */ +static int +find_file (const char *cur_filename, const struct grub_dirhook_info *info, + void *data) +{ + struct test_parse_ctx *ctx = data; + + if ((info->case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename) + : grub_strcmp (cur_filename, ctx->filename)) == 0) + { + ctx->file_info = *info; + ctx->file_exists = 1; + return 1; + } + return 0; +} + +/* Check if file exists and fetch its information. */ +static void +get_fileinfo (char *path, struct test_parse_ctx *ctx) +{ + char *pathname; + char *device_name; + grub_fs_t fs; + grub_device_t dev; + + ctx->file_exists = 0; + device_name = grub_file_get_device_name (path); + dev = grub_device_open (device_name); + if (! dev) + { + grub_free (device_name); + return; + } + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_free (device_name); + grub_device_close (dev); + return; + } + + pathname = grub_strchr (path, ')'); + if (! pathname) + pathname = path; + else + pathname++; + + /* Remove trailing '/'. */ + while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') + pathname[grub_strlen (pathname) - 1] = 0; + + /* Split into path and filename. */ + ctx->filename = grub_strrchr (pathname, '/'); + if (! ctx->filename) + { + path = grub_strdup ("/"); + ctx->filename = pathname; + } + else + { + ctx->filename++; + path = grub_strdup (pathname); + path[ctx->filename - pathname] = 0; + } + + /* It's the whole device. */ + if (! *pathname) + { + ctx->file_exists = 1; + grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info)); + /* Root is always a directory. */ + ctx->file_info.dir = 1; + + /* Fetch writing time. */ + ctx->file_info.mtimeset = 0; + if (fs->mtime) + { + if (! fs->mtime (dev, &ctx->file_info.mtime)) + ctx->file_info.mtimeset = 1; + grub_errno = GRUB_ERR_NONE; + } + } + else + (fs->dir) (dev, path, find_file, ctx); + + grub_device_close (dev); + grub_free (path); + grub_free (device_name); +} + /* Parse a test expression starting from *argn. */ static int test_parse (char **args, int *argn, int argc) { - int ret = 0, discard = 0, invert = 0; - int file_exists; - struct grub_dirhook_info file_info; - - auto void update_val (int val); - auto void get_fileinfo (char *pathname); - - /* Take care of discarding and inverting. */ - void update_val (int val) - { - if (! discard) - ret = invert ? ! val : val; - invert = discard = 0; - } - - /* Check if file exists and fetch its information. */ - void get_fileinfo (char *path) - { - char *filename, *pathname; - char *device_name; - grub_fs_t fs; - grub_device_t dev; - - /* A hook for iterating directories. */ - auto int find_file (const char *cur_filename, - const struct grub_dirhook_info *info); - int find_file (const char *cur_filename, - const struct grub_dirhook_info *info) - { - if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename) - : grub_strcmp (cur_filename, filename)) == 0) - { - file_info = *info; - file_exists = 1; - return 1; - } - return 0; - } - - file_exists = 0; - device_name = grub_file_get_device_name (path); - dev = grub_device_open (device_name); - if (! dev) - { - grub_free (device_name); - return; - } - - fs = grub_fs_probe (dev); - if (! fs) - { - grub_free (device_name); - grub_device_close (dev); - return; - } - - pathname = grub_strchr (path, ')'); - if (! pathname) - pathname = path; - else - pathname++; - - /* Remove trailing '/'. */ - while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') - pathname[grub_strlen (pathname) - 1] = 0; - - /* Split into path and filename. */ - filename = grub_strrchr (pathname, '/'); - if (! filename) - { - path = grub_strdup ("/"); - filename = pathname; - } - else - { - filename++; - path = grub_strdup (pathname); - path[filename - pathname] = 0; - } - - /* It's the whole device. */ - if (! *pathname) - { - file_exists = 1; - grub_memset (&file_info, 0, sizeof (file_info)); - /* Root is always a directory. */ - file_info.dir = 1; - - /* Fetch writing time. */ - file_info.mtimeset = 0; - if (fs->mtime) - { - if (! fs->mtime (dev, &file_info.mtime)) - file_info.mtimeset = 1; - grub_errno = GRUB_ERR_NONE; - } - } - else - (fs->dir) (dev, path, find_file); - - grub_device_close (dev); - grub_free (path); - grub_free (device_name); - } + struct test_parse_ctx ctx = { + .and = 1, + .or = 0, + .invert = 0 + }; /* Here we have the real parsing. */ while (*argn < argc) @@ -157,14 +168,16 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "=") == 0 || grub_strcmp (args[*argn + 1], "==") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], "!=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0, + &ctx); (*argn) += 3; continue; } @@ -172,28 +185,32 @@ test_parse (char **args, int *argn, int argc) /* GRUB extension: lexicographical sorting. */ if (grub_strcmp (args[*argn + 1], "<") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], "<=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], ">") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], ">=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0, + &ctx); (*argn) += 3; continue; } @@ -202,7 +219,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-eq") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - == grub_strtosl (args[*argn + 2], 0, 0)); + == grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -210,7 +227,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-ge") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - >= grub_strtosl (args[*argn + 2], 0, 0)); + >= grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -218,7 +235,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-gt") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - > grub_strtosl (args[*argn + 2], 0, 0)); + > grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -226,7 +243,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-le") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - <= grub_strtosl (args[*argn + 2], 0, 0)); + <= grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -234,7 +251,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-lt") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - < grub_strtosl (args[*argn + 2], 0, 0)); + < grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -242,7 +259,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-ne") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - != grub_strtosl (args[*argn + 2], 0, 0)); + != grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -265,10 +282,10 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-pgt") == 0) update_val (grub_strtoul (args[*argn] + i, 0, 0) - > grub_strtoul (args[*argn + 2] + i, 0, 0)); + > grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx); else update_val (grub_strtoul (args[*argn] + i, 0, 0) - < grub_strtoul (args[*argn + 2] + i, 0, 0)); + < grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx); (*argn) += 3; continue; } @@ -283,22 +300,24 @@ test_parse (char **args, int *argn, int argc) int bias = 0; /* Fetch fileinfo. */ - get_fileinfo (args[*argn]); - file1 = file_info; - file1exists = file_exists; - get_fileinfo (args[*argn + 2]); + get_fileinfo (args[*argn], &ctx); + file1 = ctx.file_info; + file1exists = ctx.file_exists; + get_fileinfo (args[*argn + 2], &ctx); if (args[*argn + 1][3]) bias = grub_strtosl (args[*argn + 1] + 3, 0, 0); if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0) - update_val ((file1exists && ! file_exists) - || (file1.mtimeset && file_info.mtimeset - && file1.mtime + bias > file_info.mtime)); + update_val ((file1exists && ! ctx.file_exists) + || (file1.mtimeset && ctx.file_info.mtimeset + && file1.mtime + bias > ctx.file_info.mtime), + &ctx); else - update_val ((! file1exists && file_exists) - || (file1.mtimeset && file_info.mtimeset - && file1.mtime + bias < file_info.mtime)); + update_val ((! file1exists && ctx.file_exists) + || (file1.mtimeset && ctx.file_info.mtimeset + && file1.mtime + bias < ctx.file_info.mtime), + &ctx); (*argn) += 3; continue; } @@ -310,27 +329,27 @@ test_parse (char **args, int *argn, int argc) /* File tests. */ if (grub_strcmp (args[*argn], "-d") == 0) { - get_fileinfo (args[*argn + 1]); - update_val (file_exists && file_info.dir); + get_fileinfo (args[*argn + 1], &ctx); + update_val (ctx.file_exists && ctx.file_info.dir, &ctx); (*argn) += 2; - return ret; + return ctx.or || ctx.and; } if (grub_strcmp (args[*argn], "-e") == 0) { - get_fileinfo (args[*argn + 1]); - update_val (file_exists); + get_fileinfo (args[*argn + 1], &ctx); + update_val (ctx.file_exists, &ctx); (*argn) += 2; - return ret; + return ctx.or || ctx.and; } if (grub_strcmp (args[*argn], "-f") == 0) { - get_fileinfo (args[*argn + 1]); + get_fileinfo (args[*argn + 1], &ctx); /* FIXME: check for other types. */ - update_val (file_exists && ! file_info.dir); + update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx); (*argn) += 2; - return ret; + return ctx.or || ctx.and; } if (grub_strcmp (args[*argn], "-s") == 0) @@ -338,25 +357,25 @@ test_parse (char **args, int *argn, int argc) grub_file_t file; grub_file_filter_disable_compression (); file = grub_file_open (args[*argn + 1]); - update_val (file && (grub_file_size (file) != 0)); + update_val (file && (grub_file_size (file) != 0), &ctx); if (file) grub_file_close (file); grub_errno = GRUB_ERR_NONE; (*argn) += 2; - return ret; + return ctx.or || ctx.and; } /* String tests. */ if (grub_strcmp (args[*argn], "-n") == 0) { - update_val (args[*argn + 1][0]); + update_val (args[*argn + 1][0], &ctx); (*argn) += 2; continue; } if (grub_strcmp (args[*argn], "-z") == 0) { - update_val (! args[*argn + 1][0]); + update_val (! args[*argn + 1][0], &ctx); (*argn) += 2; continue; } @@ -368,42 +387,40 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn], ")") == 0) { (*argn)++; - return ret; + return ctx.or || ctx.and; } /* Recursively invoke if parenthesis. */ if (grub_strcmp (args[*argn], "(") == 0) { (*argn)++; - update_val (test_parse (args, argn, argc)); + update_val (test_parse (args, argn, argc), &ctx); continue; } if (grub_strcmp (args[*argn], "!") == 0) { - invert = ! invert; + ctx.invert = ! ctx.invert; (*argn)++; continue; } if (grub_strcmp (args[*argn], "-a") == 0) { - /* If current value is 0 second value is to be discarded. */ - discard = ! ret; (*argn)++; continue; } if (grub_strcmp (args[*argn], "-o") == 0) { - /* If current value is 1 second value is to be discarded. */ - discard = ret; + ctx.or = ctx.or || ctx.and; + ctx.and = 1; (*argn)++; continue; } /* No test found. Interpret if as just a string. */ - update_val (args[*argn][0]); + update_val (args[*argn][0], &ctx); (*argn)++; } - return ret; + return ctx.or || ctx.and; } static grub_err_t diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c index a1bf775b8..cfab6763d 100644 --- a/grub-core/commands/testload.c +++ b/grub-core/commands/testload.c @@ -31,6 +31,20 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Helper for grub_cmd_testload. */ +static void +read_progress (grub_disk_addr_t sector __attribute__ ((unused)), + unsigned offset __attribute__ ((unused)), + unsigned len, + void *data __attribute__ ((unused))) +{ + for (; len >= GRUB_DISK_SECTOR_SIZE; len -= GRUB_DISK_SECTOR_SIZE) + grub_xputs ("."); + if (len) + grub_xputs ("."); + grub_refresh (); +} + static grub_err_t grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -39,15 +53,6 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), char *buf; grub_size_t size; grub_off_t pos; - auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len); - - void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)), - unsigned offset __attribute__ ((unused)), - unsigned len __attribute__ ((unused))) - { - grub_xputs ("."); - grub_refresh (); - } if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); @@ -68,7 +73,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), goto fail; grub_printf ("Reading %s sequentially", argv[0]); - file->read_hook = read_func; + file->read_hook = read_progress; if (grub_file_read (file, buf, size) != (grub_ssize_t) size) goto fail; grub_printf (" Done.\n"); diff --git a/grub-core/commands/testspeed.c b/grub-core/commands/testspeed.c new file mode 100644 index 000000000..042645f8d --- /dev/null +++ b/grub-core/commands/testspeed.c @@ -0,0 +1,115 @@ +/* testspeed.c - Command to test file read speed */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define DEFAULT_BLOCK_SIZE 65536 + +static const struct grub_arg_option options[] = + { + {"size", 's', 0, N_("Specify size for each read operation"), 0, ARG_TYPE_INT}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +grub_cmd_testspeed (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + grub_uint64_t start; + grub_uint64_t end; + grub_ssize_t block_size; + grub_disk_addr_t total_size; + char *buffer; + grub_file_t file; + grub_uint64_t whole, fraction; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + block_size = (state[0].set) ? + grub_strtoul (state[0].arg, 0, 0) : DEFAULT_BLOCK_SIZE; + + if (block_size <= 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid block size")); + + buffer = grub_malloc (block_size); + if (buffer == NULL) + return grub_errno; + + file = grub_file_open (args[0]); + if (file == NULL) + goto quit; + + total_size = 0; + start = grub_get_time_ms (); + while (1) + { + grub_ssize_t size = grub_file_read (file, buffer, block_size); + if (size <= 0) + break; + total_size += size; + } + end = grub_get_time_ms (); + grub_file_close (file); + + grub_printf_ (N_("File size: %s\n"), + grub_get_human_size (total_size, GRUB_HUMAN_SIZE_NORMAL)); + whole = grub_divmod64 (end - start, 1000, &fraction); + grub_printf_ (N_("Elapsed time: %d.%03d s \n"), + (unsigned) whole, + (unsigned) fraction); + + if (end != start) + { + grub_uint64_t speed = + grub_divmod64 (total_size * 100ULL * 1000ULL, end - start, 0); + + grub_printf_ (N_("Speed: %s \n"), + grub_get_human_size (speed, + GRUB_HUMAN_SIZE_SPEED)); + } + + quit: + grub_free (buffer); + + return grub_errno; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(testspeed) +{ + cmd = grub_register_extcmd ("testspeed", grub_cmd_testspeed, 0, N_("[-s SIZE] FILENAME"), + N_("Test file read speed."), + options); +} + +GRUB_MOD_FINI(testspeed) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/tr.c b/grub-core/commands/tr.c new file mode 100644 index 000000000..adb292b55 --- /dev/null +++ b/grub-core/commands/tr.c @@ -0,0 +1,126 @@ +/* tr.c -- The tr command. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const struct grub_arg_option options[] = + { + { "set", 's', 0, N_("Variable name to update."), N_("VARNAME"), ARG_TYPE_STRING }, + { "upcase", 'U', 0, N_("Translate to upper case."), 0, 0 }, + { "downcase", 'D', 0, N_("Translate to lower case."), 0, 0 }, + { 0, 0, 0, 0, 0, 0 } + }; + +static const char *letters_lowercase = "abcdefghijklmnopqrstuvwxyz"; +static const char *letters_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static grub_err_t +grub_cmd_tr (grub_extcmd_context_t ctxt, int argc, char **args) +{ + char *var = 0; + const char *input = 0; + char *output = 0, *optr; + const char *s1 = 0; + const char *s2 = 0; + const char *iptr; + + /* Select the defaults from options. */ + if (ctxt->state[0].set) { + var = ctxt->state[0].arg; + input = grub_env_get (var); + } + + if (ctxt->state[1].set) { + s1 = letters_lowercase; + s2 = letters_uppercase; + } + + if (ctxt->state[2].set) { + s1 = letters_uppercase; + s2 = letters_lowercase; + } + + /* Check for arguments and update the defaults. */ + if (argc == 1) + input = args[0]; + + else if (argc == 2) { + s1 = args[0]; + s2 = args[1]; + + } else if (argc == 3) { + s1 = args[0]; + s2 = args[1]; + input = args[2]; + + } else if (argc > 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters"); + + if (argc <= 0 && (!s1 || !s2 || !input)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing parameters"); + + if (grub_strlen (s1) != grub_strlen (s2)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "set sizes did not match"); + + /* Translate input into output buffer. */ + + output = grub_malloc (grub_strlen (input) + 1); + if (! output) + return grub_errno; + + optr = output; + for (iptr = input; *iptr; iptr++) + { + char *p = grub_strchr (s1, *iptr); + if (p) + *optr++ = s2[p - s1]; + else + *optr++ = *iptr; + } + *optr = '\0'; + + if (ctxt->state[0].set) + grub_env_set (var, output); + else + grub_printf ("%s\n", output); + + grub_free (output); + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(tr) +{ + cmd = grub_register_extcmd ("tr", grub_cmd_tr, 0, N_("[OPTIONS] [SET1] [SET2] [STRING]"), + N_("Translate SET1 characters to SET2 in STRING."), options); +} + +GRUB_MOD_FINI(tr) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c index 72475901d..01cdca934 100644 --- a/grub-core/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -129,7 +129,7 @@ usb_print_str (const char *description, grub_usb_device_t dev, int idx) } static int -usb_iterate (grub_usb_device_t dev) +usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused))) { struct grub_usb_desc_device *descdev; int i; @@ -196,10 +196,10 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_usb_poll_devices (); + grub_usb_poll_devices (1); grub_printf ("USB devices:\n\n"); - grub_usb_iterate (usb_iterate); + grub_usb_iterate (usb_iterate, NULL); return 0; } diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c new file mode 100644 index 000000000..04960c5d6 --- /dev/null +++ b/grub-core/commands/verify.c @@ -0,0 +1,964 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +enum + { + OPTION_SKIP_SIG = 0 + }; + +static const struct grub_arg_option options[] = + { + {"skip-sig", 's', 0, + N_("Skip signature-checking of the signature file."), 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +read_packet_header (grub_file_t sig, grub_uint8_t *out_type, grub_size_t *len) +{ + grub_uint8_t type; + grub_uint8_t l; + grub_uint16_t l16; + grub_uint32_t l32; + + /* New format. */ + switch (grub_file_read (sig, &type, sizeof (type))) + { + case 1: + break; + case 0: + { + *out_type = 0xff; + return 0; + } + default: + if (grub_errno) + return grub_errno; + /* TRANSLATORS: it's about GNUPG signatures. */ + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + } + + if (type == 0) + { + *out_type = 0xfe; + return 0; + } + + if (!(type & 0x80)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + if (type & 0x40) + { + *out_type = (type & 0x3f); + if (grub_file_read (sig, &l, sizeof (l)) != 1) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + if (l < 192) + { + *len = l; + return 0; + } + if (l < 224) + { + *len = (l - 192) << GRUB_CHAR_BIT; + if (grub_file_read (sig, &l, sizeof (l)) != 1) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len |= l; + return 0; + } + if (l == 255) + { + if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = grub_be_to_cpu32 (l32); + return 0; + } + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + } + *out_type = ((type >> 2) & 0xf); + switch (type & 0x3) + { + case 0: + if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = l; + return 0; + case 1: + if (grub_file_read (sig, &l16, sizeof (l16)) != sizeof (l16)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = grub_be_to_cpu16 (l16); + return 0; + case 2: + if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = grub_be_to_cpu32 (l32); + return 0; + } + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); +} + +struct signature_v4_header +{ + grub_uint8_t type; + grub_uint8_t pkeyalgo; + grub_uint8_t hash; + grub_uint16_t hashed_sub; +} __attribute__ ((packed)); + +const char *hashes[] = { + [0x01] = "md5", + [0x02] = "sha1", + [0x03] = "ripemd160", + [0x08] = "sha256", + [0x09] = "sha384", + [0x0a] = "sha512", + [0x0b] = "sha224" +}; + +struct gcry_pk_spec *grub_crypto_pk_dsa; +struct gcry_pk_spec *grub_crypto_pk_ecdsa; +struct gcry_pk_spec *grub_crypto_pk_rsa; + +static int +dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); +static int +rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); + +struct +{ + const char *name; + grub_size_t nmpisig; + grub_size_t nmpipub; + struct gcry_pk_spec **algo; + int (*pad) (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); + const char *module; +} pkalgos[] = + { + [1] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" }, + [3] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" }, + [17] = { "dsa", 2, 4, &grub_crypto_pk_dsa, dsa_pad, "gcry_dsa" }, + }; + +struct grub_public_key +{ + struct grub_public_key *next; + struct grub_public_subkey *subkeys; +}; + +struct grub_public_subkey +{ + struct grub_public_subkey *next; + grub_uint8_t type; + grub_uint32_t fingerprint[5]; + gcry_mpi_t mpis[10]; +}; + +static void +free_pk (struct grub_public_key *pk) +{ + struct grub_public_subkey *nsk, *sk; + for (sk = pk->subkeys; sk; sk = nsk) + { + nsk = sk->next; + grub_free (sk); + } + grub_free (pk); +} + +struct grub_public_key * +grub_load_public_key (grub_file_t f) +{ + grub_err_t err; + struct grub_public_key *ret; + struct grub_public_subkey **last = 0; + void *fingerprint_context; + + fingerprint_context = grub_zalloc (GRUB_MD_SHA1->contextsize); + if (!fingerprint_context) + return NULL; + + ret = grub_zalloc (sizeof (*ret)); + if (!ret) + { + grub_free (fingerprint_context); + return NULL; + } + + last = &ret->subkeys; + + while (1) + { + grub_uint8_t type; + grub_size_t len; + grub_uint8_t v, pk; + grub_uint32_t creation_time; + grub_off_t pend; + struct grub_public_subkey *sk; + grub_size_t i; + grub_uint16_t len_be; + + err = read_packet_header (f, &type, &len); + + if (err) + goto fail; + if (type == 0xfe) + continue; + if (type == 0xff) + { + grub_free (fingerprint_context); + return ret; + } + + grub_dprintf ("crypt", "len = %x\n", (int) len); + + pend = grub_file_tell (f) + len; + if (type != 6 && type != 14 + && type != 5 && type != 7) + { + grub_file_seek (f, pend); + continue; + } + + if (grub_file_read (f, &v, sizeof (v)) != sizeof (v)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + grub_dprintf ("crypt", "v = %x\n", v); + + if (v != 4) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + if (grub_file_read (f, &creation_time, sizeof (creation_time)) != sizeof (creation_time)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + grub_dprintf ("crypt", "time = %x\n", creation_time); + + if (grub_file_read (f, &pk, sizeof (pk)) != sizeof (pk)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + grub_dprintf ("crypt", "pk = %x\n", pk); + + if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL) + { + grub_file_seek (f, pend); + continue; + } + + sk = grub_zalloc (sizeof (struct grub_public_subkey)); + if (!sk) + goto fail; + + grub_memset (fingerprint_context, 0, sizeof (fingerprint_context)); + GRUB_MD_SHA1->init (fingerprint_context); + GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1); + len_be = grub_cpu_to_be16 (len); + GRUB_MD_SHA1->write (fingerprint_context, &len_be, sizeof (len_be)); + GRUB_MD_SHA1->write (fingerprint_context, &v, sizeof (v)); + GRUB_MD_SHA1->write (fingerprint_context, &creation_time, sizeof (creation_time)); + GRUB_MD_SHA1->write (fingerprint_context, &pk, sizeof (pk)); + + for (i = 0; i < pkalgos[pk].nmpipub; i++) + { + grub_uint16_t l; + grub_size_t lb; + grub_uint8_t buffer[4096]; + if (grub_file_read (f, &l, sizeof (l)) != sizeof (l)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT; + if (lb > sizeof (buffer) - sizeof (grub_uint16_t)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + grub_memcpy (buffer, &l, sizeof (l)); + + GRUB_MD_SHA1->write (fingerprint_context, buffer, lb + sizeof (grub_uint16_t)); + + if (gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP, + buffer, lb + sizeof (grub_uint16_t), 0)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + } + + GRUB_MD_SHA1->final (fingerprint_context); + + grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20); + + *last = sk; + last = &sk->next; + + grub_dprintf ("crypt", "actual pos: %x, expected: %x\n", (int)grub_file_tell (f), (int)pend); + + grub_file_seek (f, pend); + } + fail: + free_pk (ret); + grub_free (fingerprint_context); + return NULL; +} + +struct grub_public_key *grub_pk_trusted; + +struct grub_public_subkey * +grub_crypto_pk_locate_subkey (grub_uint64_t keyid, struct grub_public_key *pkey) +{ + struct grub_public_subkey *sk; + for (sk = pkey->subkeys; sk; sk = sk->next) + if (grub_memcmp (sk->fingerprint + 3, &keyid, 8) == 0) + return sk; + return 0; +} + +struct grub_public_subkey * +grub_crypto_pk_locate_subkey_in_trustdb (grub_uint64_t keyid) +{ + struct grub_public_key *pkey; + struct grub_public_subkey *sk; + for (pkey = grub_pk_trusted; pkey; pkey = pkey->next) + { + sk = grub_crypto_pk_locate_subkey (keyid, pkey); + if (sk) + return sk; + } + return 0; +} + + +static int +dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk) +{ + unsigned nbits = gcry_mpi_get_nbits (sk->mpis[1]); + grub_dprintf ("crypt", "must be %u bits got %d bits\n", nbits, + (int)(8 * hash->mdlen)); + return gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, hval, + nbits / 8 < (unsigned) hash->mdlen ? nbits / 8 + : (unsigned) hash->mdlen, 0); +} + +static int +rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk) +{ + grub_size_t tlen, emlen, fflen; + grub_uint8_t *em, *emptr; + unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]); + int ret; + tlen = hash->mdlen + hash->asnlen; + emlen = (nbits + 7) / 8; + if (emlen < tlen + 11) + return 1; + + em = grub_malloc (emlen); + if (!em) + return 1; + + em[0] = 0x00; + em[1] = 0x01; + fflen = emlen - tlen - 3; + for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) + *emptr = 0xff; + *emptr++ = 0x00; + grub_memcpy (emptr, hash->asnoid, hash->asnlen); + emptr += hash->asnlen; + grub_memcpy (emptr, hval, hash->mdlen); + + ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); + grub_free (em); + return ret; +} + +static grub_err_t +grub_verify_signature_real (char *buf, grub_size_t size, + grub_file_t f, grub_file_t sig, + struct grub_public_key *pkey) +{ + grub_size_t len; + grub_uint8_t v; + grub_uint8_t h; + grub_uint8_t t; + grub_uint8_t pk; + const gcry_md_spec_t *hash; + struct signature_v4_header v4; + grub_err_t err; + grub_size_t i; + gcry_mpi_t mpis[10]; + grub_uint8_t type; + + err = read_packet_header (sig, &type, &len); + if (err) + return err; + + if (type != 0x2) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (grub_file_read (sig, &v, sizeof (v)) != sizeof (v)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (v != 4) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (grub_file_read (sig, &v4, sizeof (v4)) != sizeof (v4)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + h = v4.hash; + t = v4.type; + pk = v4.pkeyalgo; + + if (t != 0) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (h >= ARRAY_SIZE (hashes) || hashes[h] == NULL) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "unknown hash"); + + if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + hash = grub_crypto_lookup_md_by_name (hashes[h]); + if (!hash) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]); + + grub_dprintf ("crypt", "alive\n"); + + { + void *context = NULL; + unsigned char *hval; + grub_ssize_t rem = grub_be_to_cpu16 (v4.hashed_sub); + grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6); + grub_uint8_t s; + grub_uint16_t unhashed_sub; + grub_ssize_t r; + grub_uint8_t hash_start[2]; + gcry_mpi_t hmpi; + grub_uint64_t keyid = 0; + struct grub_public_subkey *sk; + + context = grub_zalloc (hash->contextsize); + if (!context) + return grub_errno; + + hash->init (context); + if (buf) + hash->write (context, buf, size); + else + while (1) + { + grub_uint8_t readbuf[4096]; + r = grub_file_read (f, readbuf, sizeof (readbuf)); + if (r < 0) + goto fail; + if (r == 0) + break; + hash->write (context, readbuf, r); + } + + hash->write (context, &v, sizeof (v)); + hash->write (context, &v4, sizeof (v4)); + while (rem) + { + grub_uint8_t readbuf[4096]; + r = grub_file_read (sig, readbuf, rem < (grub_ssize_t) sizeof (readbuf) ? rem : (grub_ssize_t) sizeof (readbuf)); + if (r < 0) + goto fail; + if (r == 0) + break; + hash->write (context, readbuf, r); + rem -= r; + } + hash->write (context, &v, sizeof (v)); + s = 0xff; + hash->write (context, &s, sizeof (s)); + hash->write (context, &headlen, sizeof (headlen)); + r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); + if (r != sizeof (unhashed_sub)) + goto fail; + { + grub_uint8_t readbuf[4096]; + grub_uint8_t *ptr; + grub_uint32_t l; + rem = grub_be_to_cpu16 (unhashed_sub); + if (rem > (int) sizeof (readbuf)) + goto fail; + r = grub_file_read (sig, readbuf, rem); + if (r != rem) + goto fail; + for (ptr = readbuf; ptr < readbuf + rem; ptr += l) + { + if (*ptr < 192) + l = *ptr++; + else if (*ptr < 255) + { + if (ptr + 1 >= readbuf + rem) + break; + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; + ptr += 2; + } + else + { + if (ptr + 5 >= readbuf + rem) + break; + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); + ptr += 5; + } + if (*ptr == 0x10 && l >= 8) + keyid = grub_get_unaligned64 (ptr + 1); + } + } + + hash->final (context); + + grub_dprintf ("crypt", "alive\n"); + + hval = hash->read (context); + + if (grub_file_read (sig, hash_start, sizeof (hash_start)) != sizeof (hash_start)) + goto fail; + if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0) + goto fail; + + grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (sig)); + + for (i = 0; i < pkalgos[pk].nmpisig; i++) + { + grub_uint16_t l; + grub_size_t lb; + grub_uint8_t buffer[4096]; + grub_dprintf ("crypt", "alive\n"); + if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l)) + goto fail; + grub_dprintf ("crypt", "alive\n"); + lb = (grub_be_to_cpu16 (l) + 7) / 8; + grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l)); + if (lb > sizeof (buffer) - sizeof (grub_uint16_t)) + goto fail; + grub_dprintf ("crypt", "alive\n"); + if (grub_file_read (sig, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) + goto fail; + grub_dprintf ("crypt", "alive\n"); + grub_memcpy (buffer, &l, sizeof (l)); + grub_dprintf ("crypt", "alive\n"); + + if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP, + buffer, lb + sizeof (grub_uint16_t), 0)) + goto fail; + grub_dprintf ("crypt", "alive\n"); + } + + if (pkey) + sk = grub_crypto_pk_locate_subkey (keyid, pkey); + else + sk = grub_crypto_pk_locate_subkey_in_trustdb (keyid); + if (!sk) + { + /* TRANSLATORS: %08x is 32-bit key id. */ + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"), + keyid); + goto fail; + } + + if (pkalgos[pk].pad (&hmpi, hval, hash, sk)) + goto fail; + if (!*pkalgos[pk].algo) + { + grub_dl_load (pkalgos[pk].module); + grub_errno = GRUB_ERR_NONE; + } + + if (!*pkalgos[pk].algo) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("module `%s' isn't loaded"), + pkalgos[pk].module); + goto fail; + } + if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0)) + goto fail; + + return GRUB_ERR_NONE; + + fail: + grub_free (context); + if (!grub_errno) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + return grub_errno; + } +} + +grub_err_t +grub_verify_signature (grub_file_t f, grub_file_t sig, + struct grub_public_key *pkey) +{ + return grub_verify_signature_real (0, 0, f, sig, pkey); +} + +static grub_err_t +grub_cmd_trust (grub_extcmd_context_t ctxt, + int argc, char **args) +{ + grub_file_t pkf; + struct grub_public_key *pk = NULL; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + grub_file_filter_disable_compression (); + if (ctxt->state[OPTION_SKIP_SIG].set) + grub_file_filter_disable_pubkey (); + pkf = grub_file_open (args[0]); + if (!pkf) + return grub_errno; + pk = grub_load_public_key (pkf); + if (!pk) + { + grub_file_close (pkf); + return grub_errno; + } + grub_file_close (pkf); + + pk->next = grub_pk_trusted; + grub_pk_trusted = pk; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_list (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_public_key *pk = NULL; + struct grub_public_subkey *sk = NULL; + + for (pk = grub_pk_trusted; pk; pk = pk->next) + for (sk = pk->subkeys; sk; sk = sk->next) + { + unsigned i; + for (i = 0; i < 20; i += 2) + grub_printf ("%02x%02x ", ((grub_uint8_t *) sk->fingerprint)[i], + ((grub_uint8_t *) sk->fingerprint)[i + 1]); + grub_printf ("\n"); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_distrust (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_uint32_t keyid, keyid_be; + struct grub_public_key **pkey; + struct grub_public_subkey *sk; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + keyid = grub_strtoull (args[0], 0, 16); + if (grub_errno) + return grub_errno; + keyid_be = grub_cpu_to_be32 (keyid); + + for (pkey = &grub_pk_trusted; *pkey; pkey = &((*pkey)->next)) + { + struct grub_public_key *next; + for (sk = (*pkey)->subkeys; sk; sk = sk->next) + if (grub_memcmp (sk->fingerprint + 4, &keyid_be, 4) == 0) + break; + if (!sk) + continue; + next = (*pkey)->next; + free_pk (*pkey); + *pkey = next; + return GRUB_ERR_NONE; + } + /* TRANSLATORS: %08x is 32-bit key id. */ + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"), keyid); +} + +static grub_err_t +grub_cmd_verify_signature (grub_extcmd_context_t ctxt, + int argc, char **args) +{ + grub_file_t f, sig; + grub_err_t err; + struct grub_public_key *pk = NULL; + + grub_dprintf ("crypt", "alive\n"); + + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); + + grub_dprintf ("crypt", "alive\n"); + + if (argc > 2) + { + grub_file_t pkf; + grub_file_filter_disable_compression (); + if (ctxt->state[OPTION_SKIP_SIG].set) + grub_file_filter_disable_pubkey (); + pkf = grub_file_open (args[2]); + if (!pkf) + return grub_errno; + pk = grub_load_public_key (pkf); + if (!pk) + { + grub_file_close (pkf); + return grub_errno; + } + grub_file_close (pkf); + } + + grub_file_filter_disable_all (); + f = grub_file_open (args[0]); + if (!f) + return grub_errno; + + grub_file_filter_disable_all (); + sig = grub_file_open (args[1]); + if (!sig) + { + grub_file_close (f); + return grub_errno; + } + + err = grub_verify_signature (f, sig, pk); + grub_file_close (f); + grub_file_close (sig); + return err; +} + +static int sec = 0; + +static grub_ssize_t +verified_read (struct grub_file *file, char *buf, grub_size_t len) +{ + grub_memcpy (buf, (char *) file->data + file->offset, len); + return len; +} + +static grub_err_t +verified_close (struct grub_file *file) +{ + grub_free (file->data); + file->data = 0; + return GRUB_ERR_NONE; +} + +struct grub_fs verified_fs = +{ + .name = "verified_read", + .read = verified_read, + .close = verified_close +}; + +static grub_file_t +grub_pubkey_open (grub_file_t io, const char *filename) +{ + grub_file_t sig; + char *fsuf, *ptr; + grub_err_t err; + grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX]; + grub_file_t ret; + + if (!sec) + return io; + if (io->device->disk && io->device->disk->id == GRUB_DISK_DEVICE_MEMDISK_ID) + return io; + fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig")); + if (!fsuf) + return NULL; + ptr = grub_stpcpy (fsuf, filename); + grub_memcpy (ptr, ".sig", sizeof (".sig")); + + grub_memcpy (curfilt, grub_file_filters_enabled, + sizeof (curfilt)); + grub_file_filter_disable_all (); + sig = grub_file_open (fsuf); + grub_memcpy (grub_file_filters_enabled, curfilt, + sizeof (curfilt)); + grub_free (fsuf); + if (!sig) + return NULL; + + ret = grub_malloc (sizeof (*ret)); + if (!ret) + return NULL; + *ret = *io; + + ret->fs = &verified_fs; + ret->not_easily_seekable = 0; + if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1)) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "big file signature isn't implemented yet"); + return NULL; + } + ret->data = grub_malloc (ret->size); + if (!ret->data) + { + grub_free (ret); + return NULL; + } + if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return NULL; + } + + err = grub_verify_signature_real (ret->data, ret->size, 0, sig, NULL); + grub_file_close (sig); + if (err) + return NULL; + io->device = 0; + grub_file_close (io); + return ret; +} + +static char * +grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), + const char *val) +{ + sec = (*val == '1') || (*val == 'e'); + return grub_strdup (sec ? "enforce" : "no"); +} + +static grub_ssize_t +pseudo_read (struct grub_file *file, char *buf, grub_size_t len) +{ + grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len); + return len; +} + + +/* Filesystem descriptor. */ +struct grub_fs pseudo_fs = + { + .name = "pseudo", + .read = pseudo_read +}; + + +static grub_extcmd_t cmd, cmd_trust; +static grub_command_t cmd_distrust, cmd_list; + +GRUB_MOD_INIT(verify) +{ + const char *val; + struct grub_module_header *header; + + val = grub_env_get ("check_signatures"); + if (val && (val[0] == '1' || val[0] == 'e')) + sec = 1; + else + sec = 0; + + grub_file_filter_register (GRUB_FILE_FILTER_PUBKEY, grub_pubkey_open); + + grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec); + grub_env_export ("check_signatures"); + + grub_pk_trusted = 0; + FOR_MODULES (header) + { + struct grub_file pseudo_file; + struct grub_public_key *pk = NULL; + + grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); + + /* Not an ELF module, skip. */ + if (header->type != OBJ_TYPE_PUBKEY) + continue; + + pseudo_file.fs = &pseudo_fs; + pseudo_file.size = (header->size - sizeof (struct grub_module_header)); + pseudo_file.data = (char *) header + sizeof (struct grub_module_header); + + pk = grub_load_public_key (&pseudo_file); + if (!pk) + grub_fatal ("error loading initial key: %s\n", grub_errmsg); + + pk->next = grub_pk_trusted; + grub_pk_trusted = pk; + } + + if (!val) + grub_env_set ("check_signatures", grub_pk_trusted ? "enforce" : "no"); + + cmd = grub_register_extcmd ("verify_detached", grub_cmd_verify_signature, 0, + N_("[-s|--skip-sig] FILE SIGNATURE_FILE [PUBKEY_FILE]"), + N_("Verify detached signature."), + options); + cmd_trust = grub_register_extcmd ("trust", grub_cmd_trust, 0, + N_("[-s|--skip-sig] PUBKEY_FILE"), + N_("Add PKFILE to trusted keys."), + options); + cmd_list = grub_register_command ("list_trusted", grub_cmd_list, + 0, + N_("List trusted keys.")); + cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust, + N_("PUBKEY_ID"), + N_("Remove KEYID from trusted keys.")); +} + +GRUB_MOD_FINI(verify) +{ + grub_file_filter_unregister (GRUB_FILE_FILTER_PUBKEY); + grub_unregister_extcmd (cmd); + grub_unregister_extcmd (cmd_trust); + grub_unregister_command (cmd_list); + grub_unregister_command (cmd_distrust); +} diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 4a1157615..4be8107d5 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -27,23 +27,28 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static unsigned height, width, depth; -static struct grub_video_mode_info *current_mode; +struct hook_ctx +{ + unsigned height, width, depth; + struct grub_video_mode_info *current_mode; +}; static int -hook (const struct grub_video_mode_info *info) +hook (const struct grub_video_mode_info *info, void *hook_arg) { - if (height && width && (info->width != width || info->height != height)) + struct hook_ctx *ctx = hook_arg; + + if (ctx->height && ctx->width && (info->width != ctx->width || info->height != ctx->height)) return 0; - if (depth && info->bpp != depth) + if (ctx->depth && info->bpp != ctx->depth) return 0; if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) grub_printf (" "); else { - if (current_mode && info->mode_number == current_mode->mode_number) + if (ctx->current_mode && info->mode_number == ctx->current_mode->mode_number) grub_printf ("*"); else grub_printf (" "); @@ -68,9 +73,9 @@ hook (const struct grub_video_mode_info *info) info->blue_field_pos, info->reserved_field_pos); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) - /* TRANSLATORS: In "packed pixel" mode you write the index of the color - in the palette. Synonyms include "paletted color". */ - grub_xputs (_("Packed pixel ")); + /* TRANSLATORS: In "paletted color" mode you write the index of the color + in the palette. Synonyms include "packed pixel". */ + grub_xputs (_("Paletted ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) grub_xputs (_("YUV ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) @@ -126,13 +131,14 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), { grub_video_adapter_t adapter; grub_video_driver_id_t id; + struct hook_ctx ctx; - height = width = depth = 0; + ctx.height = ctx.width = ctx.depth = 0; if (argc) { char *ptr; ptr = args[0]; - width = grub_strtoul (ptr, &ptr, 0); + ctx.width = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; if (*ptr != 'x') @@ -140,13 +146,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), N_("invalid video mode specification `%s'"), args[0]); ptr++; - height = grub_strtoul (ptr, &ptr, 0); + ctx.height = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; if (*ptr == 'x') { ptr++; - depth = grub_strtoul (ptr, &ptr, 0); + ctx.depth = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; } @@ -175,12 +181,12 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), continue; } - current_mode = NULL; + ctx.current_mode = NULL; if (adapter->id == id) { if (grub_video_get_info (&info) == GRUB_ERR_NONE) - current_mode = &info; + ctx.current_mode = &info; else /* Don't worry about errors. */ grub_errno = GRUB_ERR_NONE; @@ -198,14 +204,14 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), if (adapter->print_adapter_specific_info) adapter->print_adapter_specific_info (); - adapter->iterate (hook); + adapter->iterate (hook, &ctx); if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE) print_edid (&edid_info); else grub_errno = GRUB_ERR_NONE; - current_mode = NULL; + ctx.current_mode = NULL; if (adapter->id != id) { diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index 2e4b3a23c..b6c181b52 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -49,7 +49,6 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), if (grub_strcmp (cmd->name, "vbetest") == 0) grub_dl_load ("vbe"); #endif - mode = grub_env_get ("gfxmode"); if (argc) mode = args[0]; @@ -71,10 +70,10 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_font_t fixed; struct grub_font_glyph *glyph; - grub_video_create_render_target (&text_layer, width, height, - GRUB_VIDEO_MODE_TYPE_RGB - | GRUB_VIDEO_MODE_TYPE_ALPHA); - if (!text_layer) + if (grub_video_create_render_target (&text_layer, width, height, + GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA) + || !text_layer) goto fail; grub_video_set_active_render_target (text_layer); @@ -155,26 +154,38 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - for (i = 0; i < 2; i++) - { - color = grub_video_map_rgb (0, 0, 0); - grub_video_fill_rect (color, 0, 0, width, height); - - color = grub_video_map_rgb (255, 0, 0); - grub_video_fill_rect (color, 0, 0, 100, 100); - - color = grub_video_map_rgb (0, 255, 255); - grub_video_fill_rect (color, 100, 100, 100, 100); - - grub_video_set_viewport (x + 150, y + 150, - width - 150 * 2, height - 150 * 2); - color = grub_video_map_rgb (77, 33, 77); - grub_video_fill_rect (color, 0, 0, width, height); - grub_video_swap_buffers (); - } - for (i = 0; i < 5; i++) { + + if (i == 0 || i == 1) + { + color = grub_video_map_rgb (0, 0, 0); + grub_video_fill_rect (color, 0, 0, width, height); + + color = grub_video_map_rgb (255, 0, 0); + grub_video_fill_rect (color, 0, 0, 100, 100); + + color = grub_video_map_rgb (0, 255, 0); + grub_video_fill_rect (color, 100, 0, 100, 100); + + color = grub_video_map_rgb (0, 0, 255); + grub_video_fill_rect (color, 200, 0, 100, 100); + + color = grub_video_map_rgb (0, 255, 255); + grub_video_fill_rect (color, 0, 100, 100, 100); + + color = grub_video_map_rgb (255, 0, 255); + grub_video_fill_rect (color, 100, 100, 100, 100); + + color = grub_video_map_rgb (255, 255, 0); + grub_video_fill_rect (color, 200, 100, 100, 100); + + grub_video_set_viewport (x + 150, y + 150, + width - 150 * 2, height - 150 * 2); + color = grub_video_map_rgb (77, 33, 77); + grub_video_fill_rect (color, 0, 0, width, height); + } + color = grub_video_map_rgb (i, 33, 77); grub_video_fill_rect (color, 0, 0, width, height); grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0, diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 2b73d9ad8..2807f806b 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -210,120 +210,144 @@ split_path (const char *str, const char **noregexop, const char **regexop) *noregexop = split; } +/* Context for match_devices. */ +struct match_devices_ctx +{ + const regex_t *regexp; + int noparts; + int ndev; + char **devs; +}; + +/* Helper for match_devices. */ +static int +match_devices_iter (const char *name, void *data) +{ + struct match_devices_ctx *ctx = data; + char **t; + char *buffer; + + /* skip partitions if asked to. */ + if (ctx->noparts && grub_strchr (name, ',')) + return 0; + + buffer = grub_xasprintf ("(%s)", name); + if (! buffer) + return 1; + + grub_dprintf ("expand", "matching: %s\n", buffer); + if (regexec (ctx->regexp, buffer, 0, 0, 0)) + { + grub_dprintf ("expand", "not matched\n"); + grub_free (buffer); + return 0; + } + + t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2)); + if (! t) + return 1; + + ctx->devs = t; + ctx->devs[ctx->ndev++] = buffer; + ctx->devs[ctx->ndev] = 0; + return 0; +} + static char ** match_devices (const regex_t *regexp, int noparts) { + struct match_devices_ctx ctx = { + .regexp = regexp, + .noparts = noparts, + .ndev = 0, + .devs = 0 + }; int i; - int ndev; - char **devs; - auto int match (const char *name); - int match (const char *name) - { - char **t; - char *buffer; - - /* skip partitions if asked to. */ - if (noparts && grub_strchr(name, ',')) - return 0; - - buffer = grub_xasprintf ("(%s)", name); - if (! buffer) - return 1; - - grub_dprintf ("expand", "matching: %s\n", buffer); - if (regexec (regexp, buffer, 0, 0, 0)) - { - grub_dprintf ("expand", "not matched\n"); - grub_free (buffer); - return 0; - } - - t = grub_realloc (devs, sizeof (char*) * (ndev + 2)); - if (! t) - return 1; - - devs = t; - devs[ndev++] = buffer; - devs[ndev] = 0; - return 0; - } - - ndev = 0; - devs = 0; - - if (grub_device_iterate (match)) + if (grub_device_iterate (match_devices_iter, &ctx)) goto fail; - return devs; + return ctx.devs; fail: - for (i = 0; devs && devs[i]; i++) - grub_free (devs[i]); + for (i = 0; ctx.devs && ctx.devs[i]; i++) + grub_free (ctx.devs[i]); - grub_free (devs); + grub_free (ctx.devs); return 0; } +/* Context for match_files. */ +struct match_files_ctx +{ + const regex_t *regexp; + char **files; + unsigned nfile; + char *dir; +}; + +/* Helper for match_files. */ +static int +match_files_iter (const char *name, const struct grub_dirhook_info *info, + void *data) +{ + struct match_files_ctx *ctx = data; + 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, ctx->dir); + if (regexec (ctx->regexp, name, 0, 0, 0)) + return 0; + + grub_dprintf ("expand", "matched\n"); + + buffer = grub_xasprintf ("%s%s", ctx->dir, name); + if (! buffer) + return 1; + + t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2)); + if (! t) + { + grub_free (buffer); + return 1; + } + + ctx->files = t; + ctx->files[ctx->nfile++] = buffer; + ctx->files[ctx->nfile] = 0; + return 0; +} + static char ** match_files (const char *prefix, const char *suffix, const char *end, const regex_t *regexp) { + struct match_files_ctx ctx = { + .regexp = regexp, + .nfile = 0, + .files = 0 + }; int i; - char **files; - unsigned nfile; - char *dir; const char *path; char *device_name; grub_fs_t fs; grub_device_t dev; - auto int match (const char *name, const struct grub_dirhook_info *info); - int match (const char *name, const struct grub_dirhook_info *info) - { - char **t; - char *buffer; - - /* skip . and .. names */ - if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) - return 0; - - grub_dprintf ("expand", "matching: %s in %s\n", name, dir); - if (regexec (regexp, name, 0, 0, 0)) - return 0; - - grub_dprintf ("expand", "matched\n"); - - buffer = grub_xasprintf ("%s%s", dir, name); - if (! buffer) - return 1; - - t = grub_realloc (files, sizeof (char*) * (nfile + 2)); - if (! t) - { - grub_free (buffer); - return 1; - } - - files = t; - files[nfile++] = buffer; - files[nfile] = 0; - return 0; - } - - nfile = 0; - files = 0; dev = 0; device_name = 0; grub_error_push (); - dir = make_dir (prefix, suffix, end); - if (! dir) + ctx.dir = make_dir (prefix, suffix, end); + if (! ctx.dir) goto fail; - device_name = grub_file_get_device_name (dir); + device_name = grub_file_get_device_name (ctx.dir); dev = grub_device_open (device_name); if (! dev) goto fail; @@ -332,33 +356,33 @@ match_files (const char *prefix, const char *suffix, const char *end, if (! fs) goto fail; - if (dir[0] == '(') + if (ctx.dir[0] == '(') { - path = grub_strchr (dir, ')'); + path = grub_strchr (ctx.dir, ')'); if (!path) goto fail; path++; } else - path = dir; + path = ctx.dir; - if (fs->dir (dev, path, match)) + if (fs->dir (dev, path, match_files_iter, &ctx)) goto fail; - grub_free (dir); + grub_free (ctx.dir); grub_device_close (dev); grub_free (device_name); grub_error_pop (); - return files; + return ctx.files; fail: - grub_free (dir); + grub_free (ctx.dir); - for (i = 0; files && files[i]; i++) - grub_free (files[i]); + for (i = 0; ctx.files && ctx.files[i]; i++) + grub_free (ctx.files[i]); - grub_free (files); + grub_free (ctx.files); if (dev) grub_device_close (dev); @@ -369,28 +393,42 @@ match_files (const char *prefix, const char *suffix, const char *end, return 0; } +/* Context for check_file. */ +struct check_file_ctx +{ + const char *basename; + int found; +}; + +/* Helper for check_file. */ +static int +check_file_iter (const char *name, const struct grub_dirhook_info *info, + void *data) +{ + struct check_file_ctx *ctx = data; + + if (ctx->basename[0] == 0 + || (info->case_insensitive ? grub_strcasecmp (name, ctx->basename) == 0 + : grub_strcmp (name, ctx->basename) == 0)) + { + ctx->found = 1; + return 1; + } + + return 0; +} + static int check_file (const char *dir, const char *basename) { + struct check_file_ctx ctx = { + .basename = basename, + .found = 0 + }; grub_fs_t fs; grub_device_t dev; - int found = 0; const char *device_name, *path; - auto int match (const char *name, const struct grub_dirhook_info *info); - int match (const char *name, const struct grub_dirhook_info *info) - { - if (basename[0] == 0 - || (info->case_insensitive ? grub_strcasecmp (name, basename) == 0 - : grub_strcmp (name, basename) == 0)) - { - found = 1; - return 1; - } - - return 0; - } - device_name = grub_file_get_device_name (dir); dev = grub_device_open (device_name); if (! dev) @@ -410,14 +448,14 @@ check_file (const char *dir, const char *basename) else path = dir; - fs->dir (dev, path[0] ? path : "/", match); + fs->dir (dev, path[0] ? path : "/", check_file_iter, &ctx); if (grub_errno == 0 && basename[0] == 0) - found = 1; + ctx.found = 1; fail: grub_errno = 0; - return found; + return ctx.found; } static void diff --git a/grub-core/commands/xen/lsxen.c b/grub-core/commands/xen/lsxen.c new file mode 100644 index 000000000..841549587 --- /dev/null +++ b/grub-core/commands/xen/lsxen.c @@ -0,0 +1,90 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static int +hook (const char *dir, void *hook_data __attribute__ ((unused))) +{ + grub_printf ("%s\n", dir); + return 0; +} + +static grub_err_t +grub_cmd_lsxen (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + char *dir; + grub_err_t err; + char *buf; + + if (argc >= 1) + return grub_xenstore_dir (args[0], hook, NULL); + + buf = grub_xenstore_get_file ("domid", NULL); + if (!buf) + return grub_errno; + dir = grub_xasprintf ("/local/domain/%s", buf); + grub_free (buf); + err = grub_xenstore_dir (dir, hook, NULL); + grub_free (dir); + return err; +} + +static grub_err_t +grub_cmd_catxen (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + const char *dir = "domid"; + char *buf; + + if (argc >= 1) + dir = args[0]; + + buf = grub_xenstore_get_file (dir, NULL); + if (!buf) + return grub_errno; + grub_xputs (buf); + grub_xputs ("\n"); + grub_free (buf); + return GRUB_ERR_NONE; + +} + +static grub_command_t cmd_ls, cmd_cat; + +GRUB_MOD_INIT (lsxen) +{ + cmd_ls = grub_register_command ("xen_ls", grub_cmd_lsxen, "[DIR]", + N_("List XEN storage.")); + cmd_cat = grub_register_command ("xen_cat", grub_cmd_catxen, "[DIR]", + N_("List XEN storage.")); +} + +GRUB_MOD_FINI (lsxen) +{ + grub_unregister_command (cmd_ls); + grub_unregister_command (cmd_cat); +} diff --git a/grub-core/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c index 8161d570e..ae4b3a415 100644 --- a/grub-core/commands/xnu_uuid.c +++ b/grub-core/commands/xnu_uuid.c @@ -50,7 +50,7 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), grub_uint8_t *xnu_uuid; char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; char *ptr; - grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + void *ctx; int low = 0; if (argc < 1) @@ -65,11 +65,14 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16)); - GRUB_MD_MD5->init (&ctx); - GRUB_MD_MD5->write (&ctx, hash_prefix, sizeof (hash_prefix)); - GRUB_MD_MD5->write (&ctx, &serial, sizeof (serial)); - GRUB_MD_MD5->final (&ctx); - xnu_uuid = GRUB_MD_MD5->read (&ctx); + ctx = grub_zalloc (GRUB_MD_MD5->contextsize); + if (!ctx) + return grub_errno; + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, hash_prefix, sizeof (hash_prefix)); + GRUB_MD_MD5->write (ctx, &serial, sizeof (serial)); + GRUB_MD_MD5->final (ctx); + xnu_uuid = GRUB_MD_MD5->read (ctx); grub_snprintf (uuid_string, sizeof (uuid_string), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", @@ -91,6 +94,8 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), if (argc > 1) grub_env_set (args[1], uuid_string); + grub_free (ctx); + return GRUB_ERR_NONE; } diff --git a/grub-core/disk/AFSplitter.c b/grub-core/disk/AFSplitter.c index ebcc35221..d76a1c447 100644 --- a/grub-core/disk/AFSplitter.c +++ b/grub-core/disk/AFSplitter.c @@ -37,8 +37,8 @@ diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_size_t fullblocks = size / hash->mdlen; int padding = size % hash->mdlen; - grub_uint8_t final[hash->mdlen]; - grub_uint8_t temp[sizeof (IV) + hash->mdlen]; + grub_uint8_t final[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t temp[sizeof (IV) + GRUB_CRYPTO_MAX_MDLEN]; /* hash block the whole data set with different IVs to produce * more than just a single data block @@ -76,6 +76,9 @@ AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, if (bufblock == NULL) return GPG_ERR_OUT_OF_MEMORY; + if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return GPG_ERR_INV_ARG; + grub_memset (bufblock, 0, blocksize); for (i = 0; i < blocknumbers - 1; i++) { diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4ab2d18db..0b13fb8eb 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -75,6 +75,8 @@ struct grub_ahci_hba_port enum grub_ahci_hba_port_command { GRUB_AHCI_HBA_PORT_CMD_ST = 0x01, + GRUB_AHCI_HBA_PORT_CMD_SPIN_UP = 0x02, + GRUB_AHCI_HBA_PORT_CMD_POWER_ON = 0x04, GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10, GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000, GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000, @@ -131,12 +133,13 @@ struct grub_ahci_device volatile struct grub_ahci_cmd_table *command_table; struct grub_pci_dma_chunk *rfis; int present; + int atapi; }; static grub_err_t grub_ahci_readwrite_real (struct grub_ahci_device *dev, struct grub_disk_ata_pass_through_parms *parms, - int spinup); + int spinup, int reset); enum @@ -162,8 +165,517 @@ enum static struct grub_ahci_device *grub_ahci_devices; static int numdevs; +static int +grub_ahci_pciinit (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint32_t class; + grub_uint32_t bar; + unsigned i, nports; + volatile struct grub_ahci_hba *hba; + + /* Read class. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + /* Check if this class ID matches that of a PCI IDE Controller. */ + if (class >> 8 != 0x010601) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); + + bar = grub_pci_read (addr); + + if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_MEM_PREFETCH)) + != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, grub_pci_read_word (addr) | + GRUB_PCI_COMMAND_IO_ENABLED + | GRUB_PCI_COMMAND_MEM_ENABLED + | GRUB_PCI_COMMAND_BUS_MASTER); + + hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, + sizeof (hba)); + grub_dprintf ("ahci", "dev: %x:%x.%x\n", dev.bus, dev.device, dev.function); + + grub_dprintf ("ahci", "tfd[0]: %x\n", + hba->ports[0].task_file_data); + grub_dprintf ("ahci", "cmd[0]: %x\n", + hba->ports[0].command); + grub_dprintf ("ahci", "st[0]: %x\n", + hba->ports[0].status); + grub_dprintf ("ahci", "err[0]: %x\n", + hba->ports[0].sata_error); + + grub_dprintf ("ahci", "tfd[1]: %x\n", + hba->ports[1].task_file_data); + grub_dprintf ("ahci", "cmd[1]: %x\n", + hba->ports[1].command); + grub_dprintf ("ahci", "st[1]: %x\n", + hba->ports[1].status); + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + hba->ports[1].sata_error = hba->ports[1].sata_error; + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "BH:%x\n", hba->bios_handoff); + + if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) + { + grub_uint64_t endtime; + + grub_dprintf ("ahci", "Requesting AHCI ownership\n"); + hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC) + | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n"); + endtime = grub_get_time_ms () + 1000; + while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + && grub_get_time_ms () < endtime); + if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + { + grub_dprintf ("ahci", "Forcibly taking ownership\n"); + hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED; + } + else + grub_dprintf ("ahci", "AHCI ownership obtained\n"); + } + else + grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) + grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); + else + grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + /* { + grub_uint64_t endtime; + hba->global_control |= 1; + endtime = grub_get_time_ms () + 1000; + while (hba->global_control & 1) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't reset AHCI\n"); + return 0; + } + }*/ + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; + + grub_dprintf ("ahci", "%d AHCI ports, PI = 0x%x\n", nports, + hba->ports_implemented); + + struct grub_ahci_device *adevs[GRUB_AHCI_HBA_CAP_NPORTS_MASK + 1]; + struct grub_ahci_device *failed_adevs[GRUB_AHCI_HBA_CAP_NPORTS_MASK + 1]; + grub_uint32_t fr_running = 0; + + for (i = 0; i < nports; i++) + failed_adevs[i] = 0; + for (i = 0; i < nports; i++) + { + if (!(hba->ports_implemented & (1 << i))) + { + adevs[i] = 0; + continue; + } + + adevs[i] = grub_zalloc (sizeof (*adevs[i])); + if (!adevs[i]) + return 1; + + adevs[i]->hba = hba; + adevs[i]->port = i; + adevs[i]->present = 1; + adevs[i]->num = numdevs++; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + adevs[i]->hba->ports[adevs[i]->port].sata_error = adevs[i]->hba->ports[adevs[i]->port].sata_error; + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head)); + if (!adevs[i]->command_list_chunk) + { + adevs[i] = 0; + continue; + } + + adevs[i]->command_table_chunk = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_table)); + if (!adevs[i]->command_table_chunk) + { + grub_dma_free (adevs[i]->command_list_chunk); + adevs[i] = 0; + continue; + } + + adevs[i]->command_list = grub_dma_get_virt (adevs[i]->command_list_chunk); + adevs[i]->command_table = grub_dma_get_virt (adevs[i]->command_table_chunk); + adevs[i]->command_list->command_table_base + = grub_dma_get_phys (adevs[i]->command_table_chunk); + + grub_dprintf ("ahci", "found device ahci%d (port %d), command_table = %p, command_list = %p\n", + adevs[i]->num, adevs[i]->port, grub_dma_get_virt (adevs[i]->command_table_chunk), + grub_dma_get_virt (adevs[i]->command_list_chunk)); + + adevs[i]->hba->ports[adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + } + + grub_uint64_t endtime; + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + { + grub_dprintf ("ahci", "couldn't stop FR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + adevs[i]->hba->ports[adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + { + grub_dprintf ("ahci", "couldn't stop CR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + for (i = 0; i < nports; i++) + if (adevs[i]) + { + adevs[i]->hba->ports[adevs[i]->port].inten = 0; + adevs[i]->hba->ports[adevs[i]->port].intstatus = ~0; + // adevs[i]->hba->ports[adevs[i]->port].fbs = 0; + + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->rfis = grub_memalign_dma32 (4096, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (adevs[i]->rfis), 0, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (adevs[i]->command_list_chunk), 0, + sizeof (struct grub_ahci_cmd_head)); + grub_memset ((char *) grub_dma_get_virt (adevs[i]->command_table_chunk), 0, + sizeof (struct grub_ahci_cmd_table)); + adevs[i]->hba->ports[adevs[i]->port].fis_base = grub_dma_get_phys (adevs[i]->rfis); + adevs[i]->hba->ports[adevs[i]->port].command_list_base + = grub_dma_get_phys (adevs[i]->command_list_chunk); + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + } + + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + { + grub_dprintf ("ahci", "couldn't start FR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + fr_running |= (1 << i); + + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP; + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; + adevs[i]->hba->ports[adevs[i]->port].command |= 1 << 28; + + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + } + + /* 10ms should actually be enough. */ + endtime = grub_get_time_ms () + 100; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].status & 7) != 3) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].status & 7) != 3) + { + grub_dprintf ("ahci", "couldn't detect device on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP; + + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->hba->ports[adevs[i]->port].sata_error = ~0; + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + grub_dprintf ("ahci", "offset: %x, tfd:%x, CMD: %x\n", + (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - + (char *) adevs[i]->hba), + adevs[i]->hba->ports[adevs[i]->port].task_file_data, + adevs[i]->hba->ports[adevs[i]->port].command); + + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + } + + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_dprintf ("ahci", "offset: %x, tfd:%x, CMD: %x\n", + (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - + (char *) adevs[i]->hba), + adevs[i]->hba->ports[adevs[i]->port].task_file_data, + adevs[i]->hba->ports[adevs[i]->port].command); + + grub_dprintf ("ahci", "err: %x\n", + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->hba->ports[adevs[i]->port].command + = (adevs[i]->hba->ports[adevs[i]->port].command & 0x0fffffff) | (1 << 28) | 2 | 4; + + /* struct grub_disk_ata_pass_through_parms parms2; + grub_memset (&parms2, 0, sizeof (parms2)); + parms2.taskfile.cmd = 8; + grub_ahci_readwrite_real (dev, &parms2, 1, 1);*/ + } + + endtime = grub_get_time_ms () + 10000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & 0x88)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & 0x88)) + { + grub_dprintf ("ahci", "port %d is busy\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + { + grub_dprintf ("ahci", "couldn't start CR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + for (i = 0; i < nports; i++) + if (failed_adevs[i] && (fr_running & (1 << i))) + failed_adevs[i]->hba->ports[failed_adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + + endtime = grub_get_time_ms () + 1000; + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (failed_adevs[i] && (fr_running & (1 << i)) && (failed_adevs[i]->hba->ports[failed_adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + break; + if (i == nports) + break; + } + for (i = 0; i < nports; i++) + if (failed_adevs[i]) + { + grub_dma_free (failed_adevs[i]->command_list_chunk); + grub_dma_free (failed_adevs[i]->command_table_chunk); + grub_dma_free (failed_adevs[i]->rfis); + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].sig >> 16) == 0xeb14) + adevs[i]->atapi = 1; + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), + GRUB_AS_LIST (adevs[i])); + } + + return 0; +} + +static grub_err_t +grub_ahci_initialize (void) +{ + grub_pci_iterate (grub_ahci_pciinit, NULL); + return grub_errno; +} + +static grub_err_t +grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_ahci_device *dev; + + for (dev = grub_ahci_devices; dev; dev = dev->next) + { + grub_uint64_t endtime; + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + break; + } + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + break; + } + grub_dma_free (dev->command_list_chunk); + grub_dma_free (dev->command_table_chunk); + grub_dma_free (dev->rfis); + dev->command_list_chunk = NULL; + dev->command_table_chunk = NULL; + dev->rfis = NULL; + } + return GRUB_ERR_NONE; +} + static int -init_port (struct grub_ahci_device *dev) +reinit_port (struct grub_ahci_device *dev) { struct grub_pci_dma_chunk *command_list; struct grub_pci_dma_chunk *command_table; @@ -254,193 +766,13 @@ init_port (struct grub_ahci_device *dev) return 1; } -static int NESTED_FUNC_ATTR -grub_ahci_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) -{ - grub_pci_address_t addr; - grub_uint32_t class; - grub_uint32_t bar; - unsigned i, nports; - volatile struct grub_ahci_hba *hba; - - /* Read class. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - /* Check if this class ID matches that of a PCI IDE Controller. */ - if (class >> 8 != 0x010601) - return 0; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); - bar = grub_pci_read (addr); - - if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK - | GRUB_PCI_ADDR_MEM_PREFETCH)) - != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) - return 0; - - hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, - sizeof (hba)); - - if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) - { - grub_uint64_t endtime; - - grub_dprintf ("ahci", "Requesting AHCI ownership\n"); - hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC) - | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; - grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n"); - endtime = grub_get_time_ms () + 1000; - while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) - && grub_get_time_ms () < endtime); - if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) - { - grub_dprintf ("ahci", "Forcibly taking ownership\n"); - hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; - hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED; - } - else - grub_dprintf ("ahci", "AHCI ownership obtained\n"); - } - else - grub_dprintf ("ahci", "AHCI is already in OS mode\n"); - - if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) - grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); - else - grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); - - for (i = 0; i < 5; i++) - { - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - grub_millisleep (1); - if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) - break; - } - if (i == 5) - { - grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); - return 0; - } - - /* - { - grub_uint64_t endtime; - hba->global_control |= 1; - endtime = grub_get_time_ms () + 1000; - while (hba->global_control & 1) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't reset AHCI\n"); - return 0; - } - } - - for (i = 0; i < 5; i++) - { - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - grub_millisleep (1); - if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) - break; - } - if (i == 5) - { - grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); - return 0; - } - */ - - nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; - - grub_dprintf ("ahci", "%d AHCI ports\n", nports); - - for (i = 0; i < nports; i++) - { - struct grub_ahci_device *adev; - grub_uint32_t st; - - if (!(hba->ports_implemented & (1 << i))) - continue; - - grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status); - /* FIXME: support hotplugging. */ - st = hba->ports[i].status; - if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1) - continue; - - adev = grub_malloc (sizeof (*adev)); - if (!adev) - return 1; - - adev->hba = hba; - adev->port = i; - adev->present = 1; - adev->num = numdevs++; - - if (init_port (adev)) - { - grub_free (adev); - return 1; - } - - grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), - GRUB_AS_LIST (adev)); - } - - return 0; -} - -static grub_err_t -grub_ahci_initialize (void) -{ - grub_pci_iterate (grub_ahci_pciinit); - return grub_errno; -} - -static grub_err_t -grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) -{ - struct grub_ahci_device *dev; - - for (dev = grub_ahci_devices; dev; dev = dev->next) - { - grub_uint64_t endtime; - - dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; - endtime = grub_get_time_ms () + 1000; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't stop FR\n"); - break; - } - - dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - endtime = grub_get_time_ms () + 1000; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't stop CR\n"); - break; - } - grub_dma_free (dev->command_list_chunk); - grub_dma_free (dev->command_table_chunk); - grub_dma_free (dev->rfis); - dev->command_list_chunk = NULL; - dev->command_table_chunk = NULL; - dev->rfis = NULL; - } - return GRUB_ERR_NONE; -} - static grub_err_t grub_ahci_restore_hw (void) { struct grub_ahci_device **pdev; for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next)) - if (init_port (*pdev)) + if (reinit_port (*pdev)) { struct grub_ahci_device *odev; odev = *pdev; @@ -454,8 +786,8 @@ grub_ahci_restore_hw (void) static int -grub_ahci_iterate (int (*hook) (int id, int bus), - grub_disk_pull_t pull) +grub_ahci_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { struct grub_ahci_device *dev; @@ -463,7 +795,7 @@ grub_ahci_iterate (int (*hook) (int id, int bus), return 0; FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num)) + if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num, hook_data)) return 1; return 0; @@ -503,10 +835,54 @@ static const int register_map[11] = { 3 /* Features */, 9 /* LBA48 mid */, 10 /* LBA48 high */ }; +static grub_err_t +grub_ahci_reset_port (struct grub_ahci_device *dev, int force) +{ + grub_uint64_t endtime; + + dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; + + if (force || (dev->hba->ports[dev->port].command_issue & 1) + || (dev->hba->ports[dev->port].task_file_data & 0x80)) + { + struct grub_disk_ata_pass_through_parms parms2; + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR"); + return grub_error (GRUB_ERR_IO, "couldn't stop CR"); + } + dev->hba->ports[dev->port].command |= 8; + while (dev->hba->ports[dev->port].command & 8) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't set CLO\n"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + return grub_error (GRUB_ERR_IO, "couldn't set CLO"); + } + + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + return grub_error (GRUB_ERR_IO, "couldn't stop CR"); + } + dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; + grub_memset (&parms2, 0, sizeof (parms2)); + parms2.taskfile.cmd = 8; + return grub_ahci_readwrite_real (dev, &parms2, 1, 1); + } + return GRUB_ERR_NONE; +} + static grub_err_t grub_ahci_readwrite_real (struct grub_ahci_device *dev, struct grub_disk_ata_pass_through_parms *parms, - int spinup) + int spinup, int reset) { struct grub_pci_dma_chunk *bufc; grub_uint64_t endtime; @@ -516,25 +892,15 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); - if ((dev->hba->ports[dev->port].task_file_data & 0x80)) - { - dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - endtime = grub_get_time_ms () + 1000; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't stop CR\n"); - break; - } - dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; - endtime = grub_get_time_ms () + (spinup ? 10000 : 1000); - while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't start CR\n"); - break; - } - } + if (!reset) + grub_ahci_reset_port (dev, 0); + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->hba->ports[dev->port].task_file_data = 0; + dev->hba->ports[dev->port].command_issue = 0; + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; @@ -550,10 +916,9 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); - dev->hba->ports[dev->port].command |= 8; - - grub_dprintf ("ahci", "AHCI tfd = %x\n", - dev->hba->ports[dev->port].task_file_data); + grub_dprintf ("ahci", "AHCI tfd = %x, CL=%p\n", + dev->hba->ports[dev->port].task_file_data, + dev->command_list); /* FIXME: support port multipliers. */ dev->command_list[0].config = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) @@ -563,17 +928,28 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ) | (parms->taskfile.cmd == 8 ? (1 << 8) : 0); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->command_list[0].transfered = 0; dev->command_list[0].command_table_base = grub_dma_get_phys (dev->command_table_chunk); + grub_memset ((char *) dev->command_list[0].unused, 0, sizeof (dev->command_list[0].unused)); + grub_memset ((char *) &dev->command_table[0], 0, sizeof (dev->command_table[0])); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + if (parms->cmdsize) grub_memcpy ((char *) dev->command_table[0].command, parms->cmd, parms->cmdsize); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D; dev->command_table[0].cfis[1] = 0x80; for (i = 0; i < sizeof (parms->taskfile.raw); i++) @@ -592,16 +968,15 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); dev->command_table[0].prdt[0].unused = 0; - dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) - | GRUB_AHCI_INTERRUPT_ON_COMPLETE; + dev->command_table[0].prdt[0].size = (parms->size - 1); grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%" PRIuGRUB_SIZE ")\n", dev->command_table[0].prdt[0].data_base, dev->command_table[0].prdt[0].unused, dev->command_table[0].prdt[0].size, - (char *) &dev->command_table[0].prdt[0] - - (char *) &dev->command_table[0]); + (grub_size_t) ((char *) &dev->command_table[0].prdt[0] + - (char *) &dev->command_table[0])); if (parms->write) grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); @@ -609,24 +984,36 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, grub_dprintf ("ahci", "AHCI command schedulded\n"); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); + grub_dprintf ("ahci", "AHCI inten = %x\n", + dev->hba->ports[dev->port].inten); + grub_dprintf ("ahci", "AHCI intstatus = %x\n", + dev->hba->ports[dev->port].intstatus); + dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5); dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5); + grub_dprintf ("ahci", "AHCI inten = %x\n", + dev->hba->ports[dev->port].inten); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); - dev->hba->ports[dev->port].command_issue |= 1; + dev->hba->ports[dev->port].sata_active = 1; + dev->hba->ports[dev->port].command_issue = 1; grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); - endtime = grub_get_time_ms () + (spinup ? 10000 : 1000); + endtime = grub_get_time_ms () + (spinup ? 10000 : 5000); while ((dev->hba->ports[dev->port].command_issue & 1)) if (grub_get_time_ms () > endtime) { - grub_dprintf ("ahci", "AHCI status <%x %x %x>\n", + grub_dprintf ("ahci", "AHCI status <%x %x %x %x>\n", dev->hba->ports[dev->port].command_issue, + dev->hba->ports[dev->port].sata_active, dev->hba->ports[dev->port].intstatus, dev->hba->ports[dev->port].task_file_data); + dev->hba->ports[dev->port].command_issue = 0; err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out"); + if (!reset) + grub_ahci_reset_port (dev, 1); break; } @@ -671,7 +1058,7 @@ grub_ahci_readwrite (grub_ata_t disk, struct grub_disk_ata_pass_through_parms *parms, int spinup) { - return grub_ahci_readwrite_real (disk->data, parms, spinup); + return grub_ahci_readwrite_real (disk->data, parms, spinup, 0); } static grub_err_t @@ -693,6 +1080,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) ata->data = dev; ata->dma = 1; + ata->atapi = dev->atapi; ata->maxbuffer = GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH; ata->present = &dev->present; @@ -712,13 +1100,7 @@ static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ahci) { - /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) - { - grub_disk_firmware_fini (); - grub_disk_firmware_fini = NULL; - } + grub_stop_disk_firmware (); /* AHCI initialization. */ grub_ahci_initialize (); diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index 10cbc8759..0cc1993e5 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -80,26 +80,44 @@ arcdisk_hash_add (char *devpath) } +/* Context for grub_arcdisk_iterate. */ +struct grub_arcdisk_iterate_ctx +{ + grub_disk_dev_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_arcdisk_iterate. */ static int -grub_arcdisk_iterate (int (*hook_in) (const char *name), +grub_arcdisk_iterate_iter (const char *name, + const struct grub_arc_component *comp, void *data) +{ + struct grub_arcdisk_iterate_ctx *ctx = data; + + if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK + || comp->type == GRUB_ARC_COMPONENT_TYPE_FLOPPY + || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE)) + return 0; + return ctx->hook (name, ctx->hook_data); +} + +static int +grub_arcdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int hook (const char *name, const struct grub_arc_component *comp); - int hook (const char *name, const struct grub_arc_component *comp) - { - if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK - || comp->type == GRUB_ARC_COMPONENT_TYPE_DISK - || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE)) - return 0; - return hook_in (name); - } + struct grub_arcdisk_iterate_ctx ctx = { hook, hook_data }; + if (pull != GRUB_DISK_PULL_NONE) return 0; - return grub_arc_iterate_devs (hook, 1); + return grub_arc_iterate_devs (grub_arcdisk_iterate_iter, &ctx, 1); } +#ifdef GRUB_CPU_MIPSEL +#define RAW_SUFFIX "partition(0)" +#else #define RAW_SUFFIX "partition(10)" +#endif static grub_err_t reopen (const char *name, int writable) @@ -139,9 +157,7 @@ reopen (const char *name, int writable) static grub_err_t grub_arcdisk_open (const char *name, grub_disk_t disk) { - char *fullname, *optr; - const char *iptr; - int state = 0; + char *fullname; grub_err_t err; grub_arc_err_t r; struct grub_arc_fileinfo info; @@ -149,35 +165,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) if (grub_memcmp (name, "arc/", 4) != 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device"); - fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX)); - if (!fullname) - return grub_errno; - optr = fullname; - for (iptr = name + 4; *iptr; iptr++) - if (state == 0) - { - if (!grub_isdigit (*iptr)) - *optr++ = *iptr; - else - { - *optr++ = '('; - *optr++ = *iptr; - state = 1; - } - } - else - { - if (grub_isdigit (*iptr)) - *optr++ = *iptr; - else - { - *optr++ = ')'; - state = 0; - } - } - if (state) - *optr++ = ')'; - grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX)); + fullname = grub_arc_alt_name_to_norm (name, RAW_SUFFIX); disk->data = fullname; grub_dprintf ("arcdisk", "opening %s\n", fullname); diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index c0d378c1a..2b988490f 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -108,6 +108,9 @@ grub_ata_identify (struct grub_ata *dev) grub_uint16_t *info16; grub_err_t err; + if (dev->atapi) + return grub_atapi_identify (dev); + info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE); info32 = (grub_uint32_t *) info64; info16 = (grub_uint16_t *) info64; @@ -129,7 +132,7 @@ grub_ata_identify (struct grub_ata *dev) grub_free (info16); grub_errno = GRUB_ERR_NONE; if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ - | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR + | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR && (parms.taskfile.error & 0x04 /* ABRT */)) /* Device without ATA IDENTIFY, try ATAPI. */ return grub_atapi_identify (dev); @@ -285,7 +288,6 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { - batch = 65536; if (ata->dma) { cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT; @@ -301,10 +303,6 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, { if (addressing == GRUB_ATA_LBA48) addressing = GRUB_ATA_LBA; - if (addressing != GRUB_ATA_CHS) - batch = 256; - else - batch = 1; if (ata->dma) { cmd = GRUB_ATA_CMD_READ_SECTORS_DMA; @@ -317,8 +315,10 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, } } - if (batch > (ata->maxbuffer >> ata->log_sector_size)) - batch = (ata->maxbuffer >> ata->log_sector_size); + if (addressing != GRUB_ATA_CHS) + batch = 256; + else + batch = 1; while (nsectors < size) { @@ -366,7 +366,7 @@ grub_ata_real_open (int id, int bus) struct grub_ata *ata; grub_ata_dev_t p; - ata = grub_malloc (sizeof (*ata)); + ata = grub_zalloc (sizeof (*ata)); if (!ata) return NULL; for (p = grub_ata_dev_list; p; p = p->next) @@ -382,6 +382,8 @@ grub_ata_real_open (int id, int bus) err = grub_ata_identify (ata); if (err) { + if (!grub_errno) + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device"); grub_free (ata); return NULL; } @@ -392,40 +394,50 @@ grub_ata_real_open (int id, int bus) return NULL; } +/* Context for grub_ata_iterate. */ +struct grub_ata_iterate_ctx +{ + grub_disk_dev_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_ata_iterate. */ static int -grub_ata_iterate (int (*hook_in) (const char *name), +grub_ata_iterate_iter (int id, int bus, void *data) +{ + struct grub_ata_iterate_ctx *ctx = data; + struct grub_ata *ata; + int ret; + char devname[40]; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + grub_snprintf (devname, sizeof (devname), + "%s%d", grub_scsi_names[id], bus); + ret = ctx->hook (devname, ctx->hook_data); + grub_ata_real_close (ata); + return ret; +} + +static int +grub_ata_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int hook (int id, int bus); - int hook (int id, int bus) - { - struct grub_ata *ata; - int ret; - char devname[40]; - - ata = grub_ata_real_open (id, bus); - - if (!ata) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (ata->atapi) - { - grub_ata_real_close (ata); - return 0; - } - grub_snprintf (devname, sizeof (devname), - "%s%d", grub_scsi_names[id], bus); - ret = hook_in (devname); - grub_ata_real_close (ata); - return ret; - } - + struct grub_ata_iterate_ctx ctx = { hook, hook_data }; grub_ata_dev_t p; for (p = grub_ata_dev_list; p; p = p->next) - if (p->iterate && p->iterate (hook, pull)) + if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull)) return 1; return 0; } @@ -452,6 +464,10 @@ grub_ata_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); disk->total_sectors = ata->size; + disk->max_agglomerate = (ata->maxbuffer >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); + if (disk->max_agglomerate > (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size))) + disk->max_agglomerate = (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size)); + disk->log_sector_size = ata->log_sector_size; disk->id = grub_make_scsi_id (id, bus, 0); @@ -561,37 +577,47 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) return GRUB_ERR_NONE; } +/* Context for grub_atapi_iterate. */ +struct grub_atapi_iterate_ctx +{ + grub_scsi_dev_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_atapi_iterate. */ static int -grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns), +grub_atapi_iterate_iter (int id, int bus, void *data) +{ + struct grub_atapi_iterate_ctx *ctx = data; + struct grub_ata *ata; + int ret; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (!ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + ret = ctx->hook (id, bus, 1, ctx->hook_data); + grub_ata_real_close (ata); + return ret; +} + +static int +grub_atapi_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int hook (int id, int bus); - int hook (int id, int bus) - { - struct grub_ata *ata; - int ret; - - ata = grub_ata_real_open (id, bus); - - if (!ata) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (!ata->atapi) - { - grub_ata_real_close (ata); - return 0; - } - ret = hook_in (id, bus, 1); - grub_ata_real_close (ata); - return ret; - } - + struct grub_atapi_iterate_ctx ctx = { hook, hook_data }; grub_ata_dev_t p; for (p = grub_ata_dev_list; p; p = p->next) - if (p->iterate && p->iterate (hook, pull)) + if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull)) return 1; return 0; } diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 1ac906d90..9a4509bf0 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -22,15 +22,12 @@ #include #include #include +#include +#include +#include #ifdef GRUB_UTIL -#include -#include -#include -#include #include -#include -#include #endif GRUB_MOD_LICENSE ("GPLv3+"); @@ -100,7 +97,7 @@ gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES); for (i = 0; i < GRUB_CRYPTODISK_GF_SIZE; i++) { - if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1) + if (((a[GRUB_CRYPTODISK_GF_BYTES - i / GRUB_CHAR_BIT - 1] >> (i % GRUB_CHAR_BIT))) & 1) grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES); gf_mul_x_be (t); } @@ -112,7 +109,9 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, void *iv) { grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; if (size % cipher->cipher->blocksize != 0) @@ -135,7 +134,9 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher, void *iv) { grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; if (size % cipher->cipher->blocksize != 0) @@ -221,6 +222,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, grub_size_t i; gcry_err_code_t err; + if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; + /* The only mode without IV. */ if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey) return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len) @@ -231,7 +235,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, grub_size_t sz = ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) / sizeof (grub_uint32_t)); - grub_uint32_t iv[sz]; + grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]; if (dev->rekey) { @@ -245,7 +249,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, } } - grub_memset (iv, 0, sz * sizeof (iv[0])); + grub_memset (iv, 0, sizeof (iv)); switch (dev->mode_iv) { case GRUB_CRYPTODISK_MODE_IV_NULL: @@ -253,9 +257,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: { grub_uint64_t tmp; - grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8]; + void *ctx; - grub_memset (ctx, 0, sizeof (ctx)); + ctx = grub_zalloc (dev->iv_hash->contextsize); + if (!ctx) + return GPG_ERR_OUT_OF_MEMORY; tmp = grub_cpu_to_le64 (sector << dev->log_sector_size); dev->iv_hash->init (ctx); @@ -264,6 +270,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, dev->iv_hash->final (ctx); grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv)); + grub_free (ctx); } break; case GRUB_CRYPTODISK_MODE_IV_PLAIN64: @@ -403,12 +410,16 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize); if (err) return err; + grub_memcpy (dev->key, key, keysize); + dev->keysize = keysize; /* Configure ESSIV if necessary. */ if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV) { grub_size_t essiv_keysize = dev->essiv_hash->mdlen; - grub_uint8_t hashed_key[essiv_keysize]; + grub_uint8_t hashed_key[GRUB_CRYPTO_MAX_MDLEN]; + if (essiv_keysize > GRUB_CRYPTO_MAX_MDLEN) + return GPG_ERR_INV_ARG; grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); err = grub_crypto_cipher_set_key (dev->essiv_cipher, @@ -448,8 +459,8 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke } static int -grub_cryptodisk_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { grub_cryptodisk_t i; @@ -460,7 +471,7 @@ grub_cryptodisk_iterate (int (*hook) (const char *name), { char buf[30]; grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } @@ -499,11 +510,11 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) #ifdef GRUB_UTIL if (dev->cheat) { - if (dev->cheat_fd == -1) - dev->cheat_fd = open (dev->cheat, O_RDONLY); - if (dev->cheat_fd == -1) + if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd)) + dev->cheat_fd = grub_util_fd_open (dev->cheat, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd)) return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"), - dev->cheat, strerror (errno)); + dev->cheat, grub_util_fd_strerror ()); } #endif @@ -518,6 +529,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) disk->data = dev; disk->total_sectors = dev->total_length; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; disk->id = dev->id; dev->ref++; return GRUB_ERR_NONE; @@ -536,8 +548,8 @@ grub_cryptodisk_close (grub_disk_t disk) #ifdef GRUB_UTIL if (dev->cheat) { - close (dev->cheat_fd); - dev->cheat_fd = -1; + grub_util_fd_close (dev->cheat_fd); + dev->cheat_fd = GRUB_UTIL_FD_INVALID; } #endif grub_disk_close (dev->source_disk); @@ -555,14 +567,15 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, #ifdef GRUB_UTIL if (dev->cheat) { - err = grub_util_fd_seek (dev->cheat_fd, dev->cheat, - sector << disk->log_sector_size); - if (err) - return err; + int r; + r = grub_util_fd_seek (dev->cheat_fd, sector << disk->log_sector_size); + if (r) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + dev->cheat, grub_util_fd_strerror ()); if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - dev->cheat, strerror (errno)); + dev->cheat, grub_util_fd_strerror ()); return GRUB_ERR_NONE; } #endif @@ -599,14 +612,15 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, #ifdef GRUB_UTIL if (dev->cheat) { - err = grub_util_fd_seek (dev->cheat_fd, dev->cheat, - sector << disk->log_sector_size); - if (err) - return err; + int r; + r = grub_util_fd_seek (dev->cheat_fd, sector << disk->log_sector_size); + if (r) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + dev->cheat, grub_util_fd_strerror ()); if (grub_util_fd_write (dev->cheat_fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - dev->cheat, strerror (errno)); + dev->cheat, grub_util_fd_strerror ()); return GRUB_ERR_NONE; } #endif @@ -630,10 +644,16 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, return grub_crypto_gcry_error (gcry_err); } - err = grub_disk_write (dev->source_disk, - (sector << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) + dev->offset, - 0, size << disk->log_sector_size, tmp); + /* Since ->write was called so disk.mod is loaded but be paranoid */ + + if (grub_disk_write_weak) + err = grub_disk_write_weak (dev->source_disk, + (sector << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + + dev->offset, + 0, size << disk->log_sector_size, tmp); + else + err = grub_error (GRUB_ERR_BUG, "disk.mod not loaded"); grub_free (tmp); return err; } @@ -730,7 +750,7 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, return grub_errno; } - newdev->cheat_fd = -1; + newdev->cheat_fd = GRUB_UTIL_FD_INVALID; newdev->source_id = source->id; newdev->source_dev_id = source->dev->id; newdev->id = n++; @@ -741,31 +761,33 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, } void -grub_util_cryptodisk_print_abstraction (grub_disk_t disk) +grub_util_cryptodisk_get_abstraction (grub_disk_t disk, + void (*cb) (const char *val)) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("cryptodisk %s ", dev->modname); + cb ("cryptodisk"); + cb (dev->modname); if (dev->cipher) - grub_printf ("%s ", dev->cipher->cipher->modname); + cb (dev->cipher->cipher->modname); if (dev->secondary_cipher) - grub_printf ("%s ", dev->secondary_cipher->cipher->modname); + cb (dev->secondary_cipher->cipher->modname); if (dev->essiv_cipher) - grub_printf ("%s ", dev->essiv_cipher->cipher->modname); + cb (dev->essiv_cipher->cipher->modname); if (dev->hash) - grub_printf ("%s ", dev->hash->modname); + cb (dev->hash->modname); if (dev->essiv_hash) - grub_printf ("%s ", dev->essiv_hash->modname); + cb (dev->essiv_hash->modname); if (dev->iv_hash) - grub_printf ("%s ", dev->iv_hash->modname); + cb (dev->iv_hash->modname); } -void -grub_util_cryptodisk_print_uuid (grub_disk_t disk) +const char * +grub_util_cryptodisk_get_uuid (grub_disk_t disk) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("%s ", dev->uuid); + return dev->uuid; } #endif @@ -866,7 +888,8 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat) #endif static int -grub_cryptodisk_scan_device (const char *name) +grub_cryptodisk_scan_device (const char *name, + void *data __attribute__ ((unused))) { grub_err_t err; grub_disk_t source; @@ -874,7 +897,10 @@ grub_cryptodisk_scan_device (const char *name) /* Try to open disk. */ source = grub_disk_open (name); if (!source) - return grub_errno; + { + grub_print_error (); + return 0; + } err = grub_cryptodisk_scan_device_real (name, source); @@ -908,7 +934,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) check_boot = state[2].set; search_uuid = args[0]; - grub_device_iterate (&grub_cryptodisk_scan_device); + grub_device_iterate (&grub_cryptodisk_scan_device, NULL); search_uuid = NULL; if (!have_it) @@ -919,7 +945,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) { search_uuid = NULL; check_boot = state[2].set; - grub_device_iterate (&grub_cryptodisk_scan_device); + grub_device_iterate (&grub_cryptodisk_scan_device, NULL); search_uuid = NULL; return GRUB_ERR_NONE; } @@ -928,10 +954,20 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) grub_err_t err; grub_disk_t disk; grub_cryptodisk_t dev; + char *diskname; + char *disklast; search_uuid = NULL; check_boot = state[2].set; - disk = grub_disk_open (args[0]); + diskname = args[0]; + if (diskname[0] == '(' && *(disklast = &diskname[grub_strlen (diskname) - 1]) == ')') + { + *disklast = '\0'; + disk = grub_disk_open (diskname + 1); + *disklast = ')'; + } + else + disk = grub_disk_open (diskname); if (!disk) return grub_errno; @@ -965,6 +1001,115 @@ static struct grub_disk_dev grub_cryptodisk_dev = { .next = 0 }; +static char +hex (grub_uint8_t val) +{ + if (val < 10) + return '0' + val; + return 'a' + val - 10; +} + +/* Open a file named NAME and initialize FILE. */ +static char * +luks_script_get (grub_size_t *sz) +{ + grub_cryptodisk_t i; + grub_size_t size = 0; + char *ptr, *ret; + + *sz = 0; + + for (i = cryptodisk_list; i != NULL; i = i->next) + if (grub_strcmp (i->modname, "luks") == 0) + { + size += sizeof ("luks_mount "); + size += grub_strlen (i->uuid); + size += grub_strlen (i->cipher->cipher->name); + size += 54; + if (i->essiv_hash) + size += grub_strlen (i->essiv_hash->name); + size += i->keysize * 2; + } + + ret = grub_malloc (size + 1); + if (!ret) + return 0; + + ptr = ret; + + for (i = cryptodisk_list; i != NULL; i = i->next) + if (grub_strcmp (i->modname, "luks") == 0) + { + unsigned j; + const char *iptr; + ptr = grub_stpcpy (ptr, "luks_mount "); + ptr = grub_stpcpy (ptr, i->uuid); + *ptr++ = ' '; + grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset); + while (*ptr) + ptr++; + for (iptr = i->cipher->cipher->name; *iptr; iptr++) + *ptr++ = grub_tolower (*iptr); + switch (i->mode) + { + case GRUB_CRYPTODISK_MODE_ECB: + ptr = grub_stpcpy (ptr, "-ecb"); + break; + case GRUB_CRYPTODISK_MODE_CBC: + ptr = grub_stpcpy (ptr, "-cbc"); + break; + case GRUB_CRYPTODISK_MODE_PCBC: + ptr = grub_stpcpy (ptr, "-pcbc"); + break; + case GRUB_CRYPTODISK_MODE_XTS: + ptr = grub_stpcpy (ptr, "-xts"); + break; + case GRUB_CRYPTODISK_MODE_LRW: + ptr = grub_stpcpy (ptr, "-lrw"); + break; + } + + switch (i->mode_iv) + { + case GRUB_CRYPTODISK_MODE_IV_NULL: + ptr = grub_stpcpy (ptr, "-null"); + break; + case GRUB_CRYPTODISK_MODE_IV_PLAIN: + ptr = grub_stpcpy (ptr, "-plain"); + break; + case GRUB_CRYPTODISK_MODE_IV_PLAIN64: + ptr = grub_stpcpy (ptr, "-plain64"); + break; + case GRUB_CRYPTODISK_MODE_IV_BENBI: + ptr = grub_stpcpy (ptr, "-benbi"); + break; + case GRUB_CRYPTODISK_MODE_IV_ESSIV: + ptr = grub_stpcpy (ptr, "-essiv:"); + ptr = grub_stpcpy (ptr, i->essiv_hash->name); + break; + case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64: + case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: + break; + } + *ptr++ = ' '; + for (j = 0; j < i->keysize; j++) + { + *ptr++ = hex (i->key[j] >> 4); + *ptr++ = hex (i->key[j] & 0xf); + } + *ptr++ = '\n'; + } + *ptr = '\0'; + *sz = ptr - ret; + return ret; +} + +struct grub_procfs_entry luks_script = +{ + .name = "luks_script", + .get_contents = luks_script_get +}; + static grub_extcmd_t cmd; GRUB_MOD_INIT (cryptodisk) @@ -973,10 +1118,12 @@ GRUB_MOD_INIT (cryptodisk) cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, N_("SOURCE|-u UUID|-a|-b"), N_("Mount a crypto device."), options); + grub_procfs_register ("luks_script", &luks_script); } GRUB_MOD_FINI (cryptodisk) { grub_disk_dev_unregister (&grub_cryptodisk_dev); cryptodisk_cleanup (); + grub_procfs_unregister (&luks_script); } diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c index 6e9745e35..dc693696a 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -117,68 +117,72 @@ is_valid_diskfilter_name (const char *name) { return (grub_memcmp (name, "md", sizeof ("md") - 1) == 0 || grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0 + || grub_memcmp (name, "lvmid/", sizeof ("lvmid/") - 1) == 0 || grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) == 0); } +/* Helper for scan_disk. */ +static int +scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data) +{ + const char *name = data; + struct grub_diskfilter_vg *arr; + grub_disk_addr_t start_sector; + struct grub_diskfilter_pv_id id; + grub_diskfilter_t diskfilter; + + grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n", + name); +#ifdef GRUB_UTIL + grub_util_info ("Scanning for DISKFILTER devices on disk %s", name); +#endif + + disk->partition = p; + + for (arr = array_list; arr != NULL; arr = arr->next) + { + struct grub_diskfilter_pv *m; + for (m = arr->pvs; m; m = m->next) + if (m->disk && m->disk->id == disk->id + && m->disk->dev->id == disk->dev->id + && m->part_start == grub_partition_get_start (disk->partition) + && m->part_size == grub_disk_get_size (disk)) + return 0; + } + + for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next) + { +#ifdef GRUB_UTIL + grub_util_info ("Scanning for %s devices on disk %s", + diskfilter->name, name); +#endif + id.uuid = 0; + id.uuidlen = 0; + arr = diskfilter->detect (disk, &id, &start_sector); + if (arr && + (! insert_array (disk, &id, arr, start_sector, diskfilter))) + { + if (id.uuidlen) + grub_free (id.uuid); + return 0; + } + if (arr && id.uuidlen) + grub_free (id.uuid); + + /* This error usually means it's not diskfilter, no need to display + it. */ + if (grub_errno != GRUB_ERR_OUT_OF_RANGE) + grub_print_error (); + + grub_errno = GRUB_ERR_NONE; + } + + return 0; +} + static int scan_disk (const char *name, int accept_diskfilter) { - auto int hook (grub_disk_t disk, grub_partition_t p); - int hook (grub_disk_t disk, grub_partition_t p) - { - struct grub_diskfilter_vg *arr; - grub_disk_addr_t start_sector; - struct grub_diskfilter_pv_id id; - grub_diskfilter_t diskfilter; - - grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n", - name); -#ifdef GRUB_UTIL - grub_util_info ("Scanning for DISKFILTER devices on disk %s", name); -#endif - - disk->partition = p; - - for (arr = array_list; arr != NULL; arr = arr->next) - { - struct grub_diskfilter_pv *m; - for (m = arr->pvs; m; m = m->next) - if (m->disk && m->disk->id == disk->id - && m->disk->dev->id == disk->dev->id - && m->part_start == grub_partition_get_start (disk->partition) - && m->part_size == grub_disk_get_size (disk)) - return 0; - } - - for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next) - { -#ifdef GRUB_UTIL - grub_util_info ("Scanning for %s devices on disk %s", - diskfilter->name, name); -#endif - id.uuid = 0; - id.uuidlen = 0; - arr = diskfilter->detect (disk, &id, &start_sector); - if (arr && - (! insert_array (disk, &id, arr, start_sector, diskfilter))) - { - if (id.uuidlen) - grub_free (id.uuid); - return 0; - } - if (arr && id.uuidlen) - grub_free (id.uuid); - - /* This error usually means it's not diskfilter, no need to display - it. */ - if (grub_errno != GRUB_ERR_OUT_OF_RANGE) - grub_print_error (); - - grub_errno = GRUB_ERR_NONE; - } - - return 0; - } grub_disk_t disk; static int scan_depth = 0; @@ -196,23 +200,15 @@ scan_disk (const char *name, int accept_diskfilter) scan_depth--; return 0; } - if (hook (disk, 0)) - { - scan_depth--; - return 1; - } - if (grub_partition_iterate (disk, hook)) - { - scan_depth--; - return 1; - } + scan_disk_partition_iter (disk, 0, (void *) name); + grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name); grub_disk_close (disk); scan_depth--; return 0; } static int -scan_disk_hook (const char *name) +scan_disk_hook (const char *name, void *data __attribute__ ((unused))) { return scan_disk (name, 0); } @@ -224,33 +220,45 @@ scan_devices (const char *arname) grub_disk_pull_t pull; struct grub_diskfilter_vg *vg; struct grub_diskfilter_lv *lv = NULL; + int scan_depth; + int need_rescan; for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) for (p = grub_disk_dev_list; p; p = p->next) if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID && p->iterate) { - if ((p->iterate) (scan_disk_hook, pull)) + if ((p->iterate) (scan_disk_hook, NULL, pull)) return; if (arname && is_lv_readable (find_lv (arname), 1)) return; } - for (vg = array_list; vg; vg = vg->next) + scan_depth = 0; + need_rescan = 1; + while (need_rescan && scan_depth++ < 100) { - if (vg->lvs) - for (lv = vg->lvs; lv; lv = lv->next) - if (!lv->scanned && lv->fullname && lv->became_readable_at) - { - scan_disk (lv->fullname, 1); - lv->scanned = 1; - } + need_rescan = 0; + for (vg = array_list; vg; vg = vg->next) + { + if (vg->lvs) + for (lv = vg->lvs; lv; lv = lv->next) + if (!lv->scanned && lv->fullname && lv->became_readable_at) + { + scan_disk (lv->fullname, 1); + lv->scanned = 1; + need_rescan = 1; + } + } } + + if (need_rescan) + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "DISKFILTER scan depth exceeded"); } static int -grub_diskfilter_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +grub_diskfilter_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { struct grub_diskfilter_vg *array; int islcnt = 0; @@ -271,7 +279,7 @@ grub_diskfilter_iterate (int (*hook) (const char *name), for (lv = array->lvs; lv; lv = lv->next) if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt) { - if (hook (lv->fullname)) + if (hook (lv->fullname, hook_data)) return 1; } } @@ -303,7 +311,7 @@ grub_diskfilter_memberlist (grub_disk_t disk) if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID && p->iterate) { - (p->iterate) (scan_disk_hook, pull); + (p->iterate) (scan_disk_hook, NULL, pull); while (pv && pv->disk) pv = pv->next; } @@ -345,7 +353,8 @@ grub_diskfilter_memberlist (grub_disk_t disk) } void -grub_diskfilter_print_partmap (grub_disk_t disk) +grub_diskfilter_get_partmap (grub_disk_t disk, + void (*cb) (const char *pm)) { struct grub_diskfilter_lv *lv = disk->data; struct grub_diskfilter_pv *pv; @@ -367,7 +376,7 @@ grub_diskfilter_print_partmap (grub_disk_t disk) continue; } for (s = 0; pv->partmaps[s]; s++) - grub_printf ("%s ", pv->partmaps[s]); + cb (pv->partmaps[s]); } } @@ -380,16 +389,12 @@ grub_diskfilter_getname (struct grub_disk *disk) } #endif -static inline int -ascii2hex (char c) +static inline char +hex2ascii (int c) { - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; + if (c >= 10) + return 'a' + c - 10; + return c + '0'; } static struct grub_diskfilter_lv * @@ -398,30 +403,12 @@ find_lv (const char *name) struct grub_diskfilter_vg *vg; struct grub_diskfilter_lv *lv = NULL; - if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0) - { - const char *uuidstr = name + sizeof ("mduuid/") - 1; - grub_size_t uuid_len = grub_strlen (uuidstr) / 2; - grub_uint8_t uuidbin[uuid_len]; - unsigned i; - for (i = 0; i < uuid_len; i++) - uuidbin[i] = ascii2hex (uuidstr[2 * i + 1]) - | (ascii2hex (uuidstr[2 * i]) << 4); - - for (vg = array_list; vg; vg = vg->next) - { - if (uuid_len == vg->uuid_len - && grub_memcmp (uuidbin, vg->uuid, uuid_len) == 0) - if (is_lv_readable (vg->lvs, 0)) - return vg->lvs; - } - } - for (vg = array_list; vg; vg = vg->next) { if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (lv->fullname && grub_strcmp (lv->fullname, name) == 0 + if (((lv->fullname && grub_strcmp (lv->fullname, name) == 0) + || (lv->idname && grub_strcmp (lv->idname, name) == 0)) && is_lv_readable (lv, 0)) return lv; } @@ -433,9 +420,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk) { struct grub_diskfilter_lv *lv; - if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0 - && grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) != 0 - && grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) != 0) + if (!is_valid_diskfilter_name (name)) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown DISKFILTER device %s", name); @@ -460,6 +445,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk) disk->data = lv; disk->total_sectors = lv->size; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; return 0; } @@ -831,7 +817,8 @@ grub_diskfilter_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "diskfilter writes are not supported"); } struct grub_diskfilter_vg * @@ -921,6 +908,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, { struct grub_diskfilter_vg *array; int i; + grub_size_t j; grub_uint64_t totsize; struct grub_diskfilter_pv *pv; grub_err_t err; @@ -946,7 +934,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, case 4: case 5: case 6: - totsize = (nmemb - level / 3) * disk_size; + totsize = (nmemb - ((unsigned) level / 3U)) * disk_size; break; default: @@ -987,6 +975,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, array->name = new_name; } + array->extent_size = 1; array->lvs = grub_zalloc (sizeof (*array->lvs)); if (!array->lvs) @@ -996,6 +985,20 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, array->lvs->name = array->name; array->lvs->fullname = array->name; + array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen); + if (!array->lvs->idname) + goto fail; + + grub_memcpy (array->lvs->idname, "mduuid/", sizeof ("mduuid/") - 1); + for (j = 0; j < uuidlen; j++) + { + array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * j] + = hex2ascii (((unsigned char) uuid[j] >> 4)); + array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * j + 1] + = hex2ascii (((unsigned char) uuid[j] & 0xf)); + } + array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * uuidlen] = '\0'; + array->lvs->size = totsize; array->lvs->segments = grub_zalloc (sizeof (*array->lvs->segments)); @@ -1049,10 +1052,14 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, { struct grub_diskfilter_pv *pv; - grub_dprintf ("diskfilter", "Inserting %s into %s (%s)\n", disk->name, + grub_dprintf ("diskfilter", "Inserting %s (+%lld,%lld) into %s (%s)\n", disk->name, + (unsigned long long) grub_partition_get_start (disk->partition), + (unsigned long long) grub_disk_get_size (disk), array->name, diskfilter->name); #ifdef GRUB_UTIL - grub_util_info ("Inserting %s into %s (%s)\n", disk->name, + grub_util_info ("Inserting %s (+%lld,%lld) into %s (%s)\n", disk->name, + (unsigned long long) grub_partition_get_start (disk->partition), + (unsigned long long) grub_disk_get_size (disk), array->name, diskfilter->name); array->driver = diskfilter; #endif @@ -1096,14 +1103,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, /* Add the device to the array. */ for (lv = array->lvs; lv; lv = lv->next) if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv, 0)) - { - lv->became_readable_at = ++inscnt; - if (is_lv_readable (lv, 1)) - { - scan_disk (lv->fullname, 1); - lv->scanned = 1; - } - } + lv->became_readable_at = ++inscnt; break; } @@ -1130,6 +1130,9 @@ free_array (void) grub_disk_close (pv->disk); if (pv->id.uuidlen) grub_free (pv->id.uuid); +#ifdef GRUB_UTIL + grub_free (pv->partmaps); +#endif grub_free (pv->internal_id); grub_free (pv); } diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c index 7b03e9036..4e7df4310 100644 --- a/grub-core/disk/dmraid_nvidia.c +++ b/grub-core/disk/dmraid_nvidia.c @@ -98,7 +98,6 @@ grub_dmraid_nv_detect (grub_disk_t disk, grub_disk_addr_t sector; struct grub_nv_super sb; int level; - int layout; grub_uint64_t disk_size; char *uuid; @@ -139,7 +138,6 @@ grub_dmraid_nv_detect (grub_disk_t disk, case NV_LEVEL_5: level = 5; - layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; disk_size = sb.capacity / (sb.array.total_volumes - 1); break; @@ -164,7 +162,8 @@ grub_dmraid_nv_detect (grub_disk_t disk, return grub_diskfilter_make_raid (sizeof (sb.array.signature), uuid, sb.array.total_volumes, NULL, disk_size, - sb.array.stripe_block_size, layout, + sb.array.stripe_block_size, + GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC, level); } diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 6db667cb5..3a7876329 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -175,39 +175,29 @@ find_parent_device (struct grub_efidisk_data *devices, } static int -iterate_child_devices (struct grub_efidisk_data *devices, - struct grub_efidisk_data *d, - int (*hook) (struct grub_efidisk_data *child)) +is_child (struct grub_efidisk_data *child, + struct grub_efidisk_data *parent) { - struct grub_efidisk_data *p; + grub_efi_device_path_t *dp, *ldp; + int ret; - for (p = devices; p; p = p->next) - { - grub_efi_device_path_t *dp, *ldp; + dp = duplicate_device_path (child->device_path); + if (! dp) + return 0; - dp = duplicate_device_path (p->device_path); - if (! dp) - return 0; + ldp = find_last_device_path (dp); + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + ldp->length[0] = sizeof (*ldp); + ldp->length[1] = 0; - ldp = find_last_device_path (dp); - ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - ldp->length[0] = sizeof (*ldp); - ldp->length[1] = 0; - - if (grub_efi_compare_device_paths (dp, d->device_path) == 0) - if (hook (p)) - { - grub_free (dp); - return 1; - } - - grub_free (dp); - } - - return 0; + ret = (grub_efi_compare_device_paths (dp, parent->device_path) == 0); + grub_free (dp); + return ret; } +#define FOR_CHILDREN(p, dev) for (p = dev; p; p = p->next) if (is_child (p, d)) + /* Add a device into a list of devices in an ascending order. */ static void add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) @@ -339,18 +329,28 @@ name_devices (struct grub_efidisk_data *devices) { grub_efi_device_path_t *dp; grub_efi_block_io_media_t *m; + int is_floppy = 0; dp = d->last_device_path; if (! dp) continue; m = d->block_io->media; - if (m->logical_partition) + if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_ACPI_DEVICE_PATH_TYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) + == GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE) + { + grub_efi_acpi_device_path_t *acpi + = (grub_efi_acpi_device_path_t *) dp; + /* Floppy EISA ID. */ + if (acpi->hid == 0x60441d0 || acpi->hid == 0x70041d0 + || acpi->hid == 0x70141d1) + is_floppy = 1; + } + if (is_floppy) { - /* Only one partition in a non-media device. Assume that this - is a floppy drive. */ #ifdef DEBUG_NAMES - grub_printf ("adding a floppy by guessing: "); + grub_printf ("adding a floppy: "); grub_efi_print_device_path (d->device_path); #endif add_device (&fd_devices, d); @@ -404,7 +404,7 @@ enumerate_disks (void) } static int -grub_efidisk_iterate (int (*hook) (const char *name), +grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { struct grub_efidisk_data *d; @@ -418,7 +418,7 @@ grub_efidisk_iterate (int (*hook) (const char *name), { grub_snprintf (buf, sizeof (buf), "hd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } break; @@ -427,7 +427,7 @@ grub_efidisk_iterate (int (*hook) (const char *name), { grub_snprintf (buf, sizeof (buf), "fd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } @@ -435,7 +435,7 @@ grub_efidisk_iterate (int (*hook) (const char *name), { grub_snprintf (buf, sizeof (buf), "cd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } break; @@ -511,13 +511,15 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) if (! d) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); - disk->id = ((num << 8) | name[0]); + disk->id = ((num << GRUB_CHAR_BIT) | name[0]); m = d->block_io->media; /* FIXME: Probably it is better to store the block size in the disk, and total sectors should be replaced with total blocks. */ grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); disk->total_sectors = m->last_block + 1; + /* Don't increase this value due to bug in some EFI. */ + disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); if (m->block_size & (m->block_size - 1) || !m->block_size) return grub_error (GRUB_ERR_IO, "invalid sector size %d", m->block_size); @@ -538,26 +540,35 @@ grub_efidisk_close (struct grub_disk *disk __attribute__ ((unused))) grub_dprintf ("efidisk", "closing %s\n", disk->name); } +static grub_efi_status_t +grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector, + grub_size_t size, char *buf, int wr) +{ + struct grub_efidisk_data *d; + grub_efi_block_io_t *bio; + + d = disk->data; + bio = d->block_io; + + return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio, + bio->media->media_id, + (grub_efi_uint64_t) sector, + (grub_efi_uintn_t) size << disk->log_sector_size, + buf); +} + static grub_err_t grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { - /* For now, use the disk io interface rather than the block io's. */ - struct grub_efidisk_data *d; - grub_efi_block_io_t *bio; grub_efi_status_t status; - d = disk->data; - bio = d->block_io; - grub_dprintf ("efidisk", "reading 0x%lx sectors at the sector 0x%llx from %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id, - (grub_efi_uint64_t) sector, - (grub_efi_uintn_t) size << disk->log_sector_size, - buf); + status = grub_efidisk_readwrite (disk, sector, size, buf, 0); + if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx from `%s'"), @@ -571,22 +582,14 @@ static grub_err_t grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, grub_size_t size, const char *buf) { - /* For now, use the disk io interface rather than the block io's. */ - struct grub_efidisk_data *d; - grub_efi_block_io_t *bio; grub_efi_status_t status; - d = disk->data; - bio = d->block_io; - grub_dprintf ("efidisk", "writing 0x%lx sectors at the sector 0x%llx to %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id, - (grub_efi_uint64_t) sector, - (grub_efi_uintn_t) size << disk->log_sector_size, - (void *) buf); + status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1); + if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx to `%s'"), @@ -607,22 +610,27 @@ static struct grub_disk_dev grub_efidisk_dev = .next = 0 }; -void -grub_efidisk_init (void) -{ - enumerate_disks (); - grub_disk_dev_register (&grub_efidisk_dev); -} - void grub_efidisk_fini (void) { free_devices (fd_devices); free_devices (hd_devices); free_devices (cd_devices); + fd_devices = 0; + hd_devices = 0; + cd_devices = 0; grub_disk_dev_unregister (&grub_efidisk_dev); } +void +grub_efidisk_init (void) +{ + grub_disk_firmware_fini = grub_efidisk_fini; + + enumerate_disks (); + grub_disk_dev_register (&grub_efidisk_dev); +} + /* Some utility functions to map GRUB devices with EFI devices. */ grub_efi_handle_t grub_efidisk_get_device_handle (grub_disk_t disk) @@ -655,9 +663,10 @@ grub_efidisk_get_device_handle (grub_disk_t disk) { struct grub_efidisk_data *devices; grub_efi_handle_t handle = 0; - auto int find_partition (struct grub_efidisk_data *c); + struct grub_efidisk_data *c; - int find_partition (struct grub_efidisk_data *c) + devices = make_devices (); + FOR_CHILDREN (c, devices) { grub_efi_hard_drive_device_path_t hd; @@ -667,7 +676,7 @@ grub_efidisk_get_device_handle (grub_disk_t disk) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) - && (grub_partition_get_start (disk->partition) + && (grub_partition_get_start (disk->partition) == (hd.partition_start << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) && (grub_partition_get_len (disk->partition) @@ -675,14 +684,10 @@ grub_efidisk_get_device_handle (grub_disk_t disk) - GRUB_DISK_SECTOR_BITS)))) { handle = c->handle; - return 1; + break; } - - return 0; } - devices = make_devices (); - iterate_child_devices (devices, d, find_partition); free_devices (devices); if (handle != 0) @@ -738,6 +743,35 @@ get_diskname_from_path (const grub_efi_device_path_t *path, return 0; } +/* Context for grub_efidisk_get_device_name. */ +struct grub_efidisk_get_device_name_ctx +{ + char *partition_name; + grub_efi_hard_drive_device_path_t hd; +}; + +/* Helper for grub_efidisk_get_device_name. + Find the identical partition. */ +static int +grub_efidisk_get_device_name_iter (grub_disk_t disk, + const grub_partition_t part, void *data) +{ + struct grub_efidisk_get_device_name_ctx *ctx = data; + + if (grub_partition_get_start (part) + == (ctx->hd.partition_start << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + && grub_partition_get_len (part) + == (ctx->hd.partition_size << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS))) + { + ctx->partition_name = grub_partition_get_name (part); + return 1; + } + + return 0; +} + char * grub_efidisk_get_device_name (grub_efi_handle_t *handle) { @@ -753,48 +787,45 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) return 0; if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) - == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { - char *partition_name = NULL; + int is_cdrom = 0; + struct grub_efidisk_get_device_name_ctx ctx; char *dev_name; - grub_efi_device_path_t *dup_dp, *dup_ldp; - grub_efi_hard_drive_device_path_t hd; + grub_efi_device_path_t *dup_dp; grub_disk_t parent = 0; - auto int find_partition (grub_disk_t disk, const grub_partition_t part); - - /* Find the identical partition. */ - int find_partition (grub_disk_t disk, const grub_partition_t part) - { - if (grub_partition_get_start (part) - == (hd.partition_start << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - && grub_partition_get_len (part) - == (hd.partition_size << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS))) - { - partition_name = grub_partition_get_name (part); - return 1; - } - - return 0; - } - /* It is necessary to duplicate the device path so that GRUB can overwrite it. */ dup_dp = duplicate_device_path (dp); if (! dup_dp) return 0; - dup_ldp = find_last_device_path (dup_dp); - dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - dup_ldp->length[0] = sizeof (*dup_ldp); - dup_ldp->length[1] = 0; + while (1) + { + grub_efi_device_path_t *dup_ldp; + dup_ldp = find_last_device_path (dup_dp); + if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))) + break; + + if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE) + is_cdrom = 1; + + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + dup_ldp->length[0] = sizeof (*dup_ldp); + dup_ldp->length[1] = 0; + } if (!get_diskname_from_path (dup_dp, device_name)) - return 0; + { + grub_free (dup_dp); + return 0; + } + parent = grub_disk_open (device_name); grub_free (dup_dp); @@ -802,36 +833,38 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) return 0; /* Find a partition which matches the hard drive device path. */ - grub_memcpy (&hd, ldp, sizeof (hd)); - if (hd.partition_start == 0 - && (hd.partition_size << (parent->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - == grub_disk_get_size (parent)) + ctx.partition_name = NULL; + grub_memcpy (&ctx.hd, ldp, sizeof (ctx.hd)); + if (ctx.hd.partition_start == 0 + && (ctx.hd.partition_size << (parent->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + == grub_disk_get_size (parent)) { dev_name = grub_strdup (parent->name); } else { - grub_partition_iterate (parent, find_partition); + grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, + &ctx); - if (! partition_name) + if (! ctx.partition_name) { grub_disk_close (parent); + if (is_cdrom) + return grub_strdup (device_name); return 0; } - dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name); - grub_free (partition_name); + dev_name = grub_xasprintf ("%s,%s", parent->name, + ctx.partition_name); + grub_free (ctx.partition_name); } grub_disk_close (parent); return dev_name; } - else - { - /* This should be an entire disk. */ - if (!get_diskname_from_path (dp, device_name)) - return 0; - return grub_strdup (device_name); - } + /* This may be guessed device - floppy, cdrom or entire disk. */ + if (!get_diskname_from_path (dp, device_name)) + return 0; + return grub_strdup (device_name); } diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index f9315df0d..73b325c94 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -146,40 +146,33 @@ geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) grub_uint64_t zone; } __attribute__ ((packed)) tohash = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) }; - grub_uint64_t key[(dev->hash->mdlen + 7) / 8]; + GRUB_PROPERLY_ALIGNED_ARRAY (key, GRUB_CRYPTO_MAX_MDLEN); + + if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return GPG_ERR_INV_ARG; grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n", zoneno, dev->rekey_derived_size); gcry_err = grub_crypto_hmac_buffer (dev->hash, dev->rekey_key, 64, &tohash, sizeof (tohash), key); if (gcry_err) - return grub_crypto_gcry_error (gcry_err); + return gcry_err; return grub_cryptodisk_setkey (dev, (grub_uint8_t *) key, dev->rekey_derived_size); } -static inline int -ascii2hex (char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; -} - static inline gcry_err_code_t make_uuid (const struct grub_geli_phdr *header, char *uuid) { - grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen]; + grub_uint8_t uuidbin[GRUB_CRYPTODISK_MAX_UUID_LENGTH]; gcry_err_code_t err; grub_uint8_t *iptr; char *optr; + if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH) + return GPG_ERR_TOO_LARGE; err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, header->salt, sizeof (header->salt), "uuid", sizeof ("uuid") - 1, uuidbin); @@ -187,7 +180,7 @@ make_uuid (const struct grub_geli_phdr *header, return err; optr = uuid; - for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++) + for (iptr = uuidbin; iptr < &uuidbin[GRUB_MD_SHA256->mdlen]; iptr++) { grub_snprintf (optr, 3, "%02x", *iptr); optr += 2; @@ -198,19 +191,13 @@ make_uuid (const struct grub_geli_phdr *header, #ifdef GRUB_UTIL -#include -#include -#include -#include #include -#include -#include #include char * grub_util_get_geli_uuid (const char *dev) { - int fd = open (dev, O_RDONLY); + grub_util_fd_t fd; grub_uint64_t s; unsigned log_secsize; grub_uint8_t hdr[512]; @@ -218,16 +205,20 @@ grub_util_get_geli_uuid (const char *dev) char *uuid; gcry_err_code_t err; - if (fd < 0) + fd = grub_util_fd_open (dev, GRUB_UTIL_FD_O_RDONLY); + + if (!GRUB_UTIL_FD_IS_VALID (fd)) return NULL; s = grub_util_get_fd_size (fd, dev, &log_secsize); s >>= log_secsize; - grub_util_fd_seek (fd, dev, (s << log_secsize) - 512); + grub_util_fd_seek (fd, (s << log_secsize) - 512); uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1); if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0) grub_util_error ("%s", _("couldn't read ELI metadata")); + + grub_util_fd_close (fd); COMPILE_TIME_ASSERT (sizeof (header) <= 512); header = (void *) &hdr; @@ -256,10 +247,13 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, const struct gcry_cipher_spec *ciph; const char *ciphername = NULL; gcry_err_code_t gcry_err; - char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; + char uuid[GRUB_CRYPTODISK_MAX_UUID_LENGTH]; grub_disk_addr_t sector; grub_err_t err; + if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH) + return NULL; + sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) return NULL; @@ -381,9 +375,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, newdev->rekey_shift = 20; } -#ifdef GRUB_UTIL newdev->modname = "geli"; -#endif newdev->total_length = grub_disk_get_size (disk) - 1; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); @@ -395,10 +387,10 @@ static grub_err_t recover_key (grub_disk_t source, grub_cryptodisk_t dev) { grub_size_t keysize; - grub_uint8_t digest[dev->hash->mdlen]; - grub_uint8_t geomkey[dev->hash->mdlen]; - grub_uint8_t verify_key[dev->hash->mdlen]; - grub_uint8_t zero[dev->cipher->cipher->blocksize]; + grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t geomkey[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; char passphrase[MAX_PASSPHRASE] = ""; unsigned i; gcry_err_code_t gcry_err; @@ -407,6 +399,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) grub_disk_addr_t sector; grub_err_t err; + if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return grub_error (GRUB_ERR_BUG, "cipher block is too long"); + + if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return grub_error (GRUB_ERR_BUG, "mdlen is too long"); + sector = grub_disk_get_size (source); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) return grub_error (GRUB_ERR_BUG, "not a geli"); @@ -416,7 +414,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) if (err) return err; - keysize = grub_le_to_cpu16 (header.keylen) / 8; + keysize = grub_le_to_cpu16 (header.keylen) / GRUB_CHAR_BIT; grub_memset (zero, 0, sizeof (zero)); grub_puts_ (N_("Attempting to decrypt master key...")); @@ -468,12 +466,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) } gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, - sizeof (geomkey), "\1", 1, digest); + dev->hash->mdlen, "\1", 1, digest); if (gcry_err) return grub_crypto_gcry_error (gcry_err); gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, - sizeof (geomkey), "\0", 1, verify_key); + dev->hash->mdlen, "\0", 1, verify_key); if (gcry_err) return grub_crypto_gcry_error (gcry_err); @@ -483,7 +481,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) for (i = 0; i < ARRAY_SIZE (header.keys); i++) { struct grub_geli_key candidate_key; - grub_uint8_t key_hmac[dev->hash->mdlen]; + grub_uint8_t key_hmac[GRUB_CRYPTO_MAX_MDLEN]; /* Check if keyslot is enabled. */ if (! (header.keys_used & (1 << i))) @@ -504,7 +502,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) return grub_crypto_gcry_error (gcry_err); gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key, - sizeof (verify_key), + dev->hash->mdlen, &candidate_key, (sizeof (candidate_key) - sizeof (candidate_key.hmac)), diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index 5ee0d2e56..69b6f0ea1 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -20,20 +20,24 @@ /* When using the disk, make a reference to this module. Otherwise the user will end up with a useless module :-). */ +#include +#include + #include #include #include +#include int grub_disk_host_i_want_a_reference; static int -grub_host_iterate (int (*hook) (const char *name), +grub_host_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { if (pull != GRUB_DISK_PULL_NONE) return 0; - if (hook ("host")) + if (hook ("host", hook_data)) return 1; return 0; } diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 7ca89e3f7..7458c7a0f 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -272,21 +272,22 @@ grub_biosdisk_get_drive (const char *name) } static int -grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) +grub_biosdisk_call_hook (grub_disk_dev_iterate_hook_t hook, void *hook_data, + int drive) { char name[10]; if (cd_drive && drive == cd_drive) - return hook ("cd"); + return hook ("cd", hook_data); grub_snprintf (name, sizeof (name), (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); - return hook (name); + return hook (name, hook_data); } static int -grub_biosdisk_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull __attribute__ ((unused))) +grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { int num_floppies; int drive; @@ -304,7 +305,7 @@ grub_biosdisk_iterate (int (*hook) (const char *name), break; } - if (grub_biosdisk_call_hook (hook, drive)) + if (grub_biosdisk_call_hook (hook, hook_data, drive)) return 1; } return 0; @@ -312,14 +313,14 @@ grub_biosdisk_iterate (int (*hook) (const char *name), case GRUB_DISK_PULL_REMOVABLE: if (cd_drive) { - if (grub_biosdisk_call_hook (hook, cd_drive)) + if (grub_biosdisk_call_hook (hook, hook_data, cd_drive)) return 1; } /* For floppy disks, we can get the number safely. */ num_floppies = grub_biosdisk_get_num_floppies (); for (drive = 0; drive < num_floppies; drive++) - if (grub_biosdisk_call_hook (hook, drive)) + if (grub_biosdisk_call_hook (hook, hook_data, drive)) return 1; return 0; default: @@ -423,6 +424,9 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) } disk->total_sectors = total_sectors; + /* Limit the max to 0x7f because of Phoenix EDD. */ + disk->max_agglomerate = 0x7f >> GRUB_DISK_CACHE_BITS; + disk->data = data; return GRUB_ERR_NONE; @@ -547,10 +551,6 @@ get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector) size = sectors - offset; - /* Limit the max to 0x7f because of Phoenix EDD. */ - if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size)) - size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size); - return size; } diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index ad30852ec..576e9ccc4 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -33,25 +33,32 @@ struct grub_nand_data }; static int -grub_nand_iterate (int (*hook) (const char *name), +grub_nand_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int dev_iterate (struct grub_ieee1275_devalias *alias); - int dev_iterate (struct grub_ieee1275_devalias *alias) - { - if (grub_strcmp (alias->name, "nand") == 0) - { - hook (alias->name); - return 1; - } - - return 0; - } + static int have_nand = -1; if (pull != GRUB_DISK_PULL_NONE) return 0; - return grub_devalias_iterate (dev_iterate); + if (have_nand == -1) + { + struct grub_ieee1275_devalias alias; + + have_nand = 0; + FOR_IEEE1275_DEVALIASES(alias) + if (grub_strcmp (alias.name, "nand") == 0) + { + have_nand = 1; + break; + } + grub_ieee1275_devalias_free (&alias); + } + + if (have_nand) + return hook ("nand", hook_data); + + return 0; } static grub_err_t @@ -203,7 +210,8 @@ grub_nand_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "nand write is not supported"); } static struct grub_disk_dev grub_nand_dev = diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index b0aa7ec7b..2a31ecdb1 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -31,6 +31,8 @@ static grub_ieee1275_ihandle_t last_ihandle; struct ofdisk_hash_ent { char *devpath; + int is_boot; + int is_cdrom; /* Pointer to shortest available name on nodes representing canonical names, otherwise NULL. */ const char *shortest; @@ -69,17 +71,28 @@ ofdisk_hash_add_real (char *devpath) struct ofdisk_hash_ent *p; struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)]; - p = grub_malloc(sizeof (*p)); + p = grub_zalloc (sizeof (*p)); if (!p) return NULL; p->devpath = devpath; p->next = *head; - p->shortest = 0; *head = p; return p; } +static int +check_string_cdrom (const char *str) +{ + const char *ptr = grub_strrchr (str, '/'); + + if (ptr) + ptr++; + else + ptr = str; + return (grub_strncmp (ptr, "cdrom", 5) == 0); +} + static struct ofdisk_hash_ent * ofdisk_hash_add (char *devpath, char *curcan) { @@ -92,6 +105,8 @@ ofdisk_hash_add (char *devpath, char *curcan) if (!curcan) { p->shortest = devpath; + if (check_string_cdrom (devpath)) + p->is_cdrom = 1; return p; } @@ -101,6 +116,9 @@ ofdisk_hash_add (char *devpath, char *curcan) else grub_free (curcan); + if (check_string_cdrom (devpath) || check_string_cdrom (curcan)) + pcan->is_cdrom = 1; + if (!pcan) grub_errno = GRUB_ERR_NONE; else @@ -114,111 +132,117 @@ ofdisk_hash_add (char *devpath, char *curcan) } static void -scan (void) +dev_iterate_real (const char *name, const char *path) { - auto int dev_iterate_real (const char *name, const char *path); + struct ofdisk_hash_ent *op; - int dev_iterate_real (const char *name, const char *path) + grub_dprintf ("disk", "disk name = %s, path = %s\n", name, + path); + + op = ofdisk_hash_find (path); + if (!op) { - struct ofdisk_hash_ent *op; - - grub_dprintf ("disk", "disk name = %s, path = %s\n", name, - path); - - op = ofdisk_hash_find (path); - if (!op) + char *name_dup = grub_strdup (name); + char *can = grub_strdup (path); + if (!name_dup || !can) { - char *name_dup = grub_strdup (name); - char *can = grub_strdup (path); - if (!name_dup || !can) - { - grub_errno = GRUB_ERR_NONE; - grub_free (name_dup); - grub_free (can); - return 0; - } - op = ofdisk_hash_add (name_dup, can); + grub_errno = GRUB_ERR_NONE; + grub_free (name_dup); + grub_free (can); + return; } - return 0; + op = ofdisk_hash_add (name_dup, can); + } + return; +} + +static void +dev_iterate (const struct grub_ieee1275_devalias *alias) +{ + if (grub_strcmp (alias->type, "vscsi") == 0) + { + static grub_ieee1275_ihandle_t ihandle; + struct set_color_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t nentries; + grub_ieee1275_cell_t table; + } + args; + char *buf, *bufptr; + unsigned i; + + if (grub_ieee1275_open (alias->path, &ihandle)) + return; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); + args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; + args.ihandle = ihandle; + args.table = 0; + args.nentries = 0; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result) + { + grub_ieee1275_close (ihandle); + return; + } + + buf = grub_malloc (grub_strlen (alias->path) + 32); + if (!buf) + return; + bufptr = grub_stpcpy (buf, alias->path); + + for (i = 0; i < args.nentries; i++) + { + grub_uint64_t *ptr; + + ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); + while (*ptr) + { + grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); + dev_iterate_real (buf, buf); + } + } + grub_ieee1275_close (ihandle); + grub_free (buf); + return; + } + + if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) + && grub_strcmp (alias->type, "block") == 0) + { + dev_iterate_real (alias->path, alias->path); + return; } - auto int dev_iterate_alias (struct grub_ieee1275_devalias *alias); - int dev_iterate_alias (struct grub_ieee1275_devalias *alias) { - if (grub_strcmp (alias->type, "block") != 0) - return 0; - return dev_iterate_real (alias->name, alias->path); + struct grub_ieee1275_devalias child; + + FOR_IEEE1275_DEVCHILDREN(alias->path, child) + dev_iterate (&child); } +} - auto int dev_iterate (struct grub_ieee1275_devalias *alias); - int dev_iterate (struct grub_ieee1275_devalias *alias) - { - if (grub_strcmp (alias->type, "vscsi") == 0) - { - static grub_ieee1275_ihandle_t ihandle; - struct set_color_args - { - struct grub_ieee1275_common_hdr common; - grub_ieee1275_cell_t method; - grub_ieee1275_cell_t ihandle; - grub_ieee1275_cell_t catch_result; - grub_ieee1275_cell_t nentries; - grub_ieee1275_cell_t table; - } - args; - char *buf, *bufptr; - unsigned i; +static void +scan (void) +{ + struct grub_ieee1275_devalias alias; + FOR_IEEE1275_DEVALIASES(alias) + { + if (grub_strcmp (alias.type, "block") != 0) + continue; + dev_iterate_real (alias.name, alias.path); + } - if (grub_ieee1275_open (alias->path, &ihandle)) - return 0; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); - args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; - args.ihandle = ihandle; - args.table = 0; - args.nentries = 0; - - if (IEEE1275_CALL_ENTRY_FN (&args) == -1) - { - grub_ieee1275_close (ihandle); - return 0; - } - - buf = grub_malloc (grub_strlen (alias->path) + 32); - if (!buf) - return 0; - bufptr = grub_stpcpy (buf, alias->path); - - for (i = 0; i < args.nentries; i++) - { - grub_uint64_t *ptr; - - ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); - while (*ptr) - { - grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); - if (dev_iterate_real (buf, buf)) - return 1; - } - } - grub_ieee1275_close (ihandle); - grub_free (buf); - return 0; - } - - if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) - && grub_strcmp (alias->type, "block") == 0) - return dev_iterate_real (alias->path, alias->path); - - return grub_children_iterate (alias->path, dev_iterate); - } - - grub_devalias_iterate (dev_iterate_alias); - grub_children_iterate ("/", dev_iterate); + FOR_IEEE1275_DEVCHILDREN("/", alias) + dev_iterate (&alias); } static int -grub_ofdisk_iterate (int (*hook) (const char *name), +grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { unsigned i; @@ -261,7 +285,7 @@ grub_ofdisk_iterate (int (*hook) (const char *name), } } - if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) + if (!ent->is_boot && ent->is_cdrom) continue; { @@ -276,7 +300,7 @@ grub_ofdisk_iterate (int (*hook) (const char *name), *optr++ = *iptr++; } *optr = 0; - if (hook (buffer)) + if (hook (buffer, hook_data)) return 1; } } @@ -349,6 +373,14 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device"); } + grub_uint32_t block_size = 0; + if (grub_ofdisk_get_block_size (devpath, &block_size) == 0) + { + for (disk->log_sector_size = 0; + (1U << disk->log_sector_size) < block_size; + disk->log_sector_size++); + } + /* 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. */ @@ -415,7 +447,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) last_devpath = disk->data; } - pos = sector << GRUB_DISK_SECTOR_BITS; + pos = sector << disk->log_sector_size; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) @@ -434,9 +466,9 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " "from `%s'"), (unsigned long long) sector, @@ -454,9 +486,9 @@ grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector, err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_write (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " "to `%s'"), (unsigned long long) sector, @@ -477,10 +509,44 @@ static struct grub_disk_dev grub_ofdisk_dev = .next = 0 }; -void -grub_ofdisk_init (void) +static void +insert_bootpath (void) { - grub_disk_dev_register (&grub_ofdisk_dev); + char *bootpath; + grub_ssize_t bootpath_size; + char *type; + + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath", + &bootpath_size) + || bootpath_size <= 0) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + return; + } + + bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64); + if (! bootpath) + { + grub_print_error (); + return; + } + grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath, + (grub_size_t) bootpath_size + 1, 0); + bootpath[bootpath_size] = '\0'; + + /* Transform an OF device path to a GRUB path. */ + + type = grub_ieee1275_get_device_type (bootpath); + if (!(type && grub_strcmp (type, "network") == 0)) + { + struct ofdisk_hash_ent *op; + char *device = grub_ieee1275_get_devname (bootpath); + op = ofdisk_hash_add (device, NULL); + op->is_boot = 1; + } + grub_free (type); + grub_free (bootpath); } void @@ -493,3 +559,54 @@ grub_ofdisk_fini (void) grub_disk_dev_unregister (&grub_ofdisk_dev); } + +void +grub_ofdisk_init (void) +{ + grub_disk_firmware_fini = grub_ofdisk_fini; + + insert_bootpath (); + + grub_disk_dev_register (&grub_ofdisk_dev); +} + +grub_err_t +grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size) +{ + struct size_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t result; + grub_ieee1275_cell_t size1; + grub_ieee1275_cell_t size2; + } args_ieee1275; + + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + + last_ihandle = 0; + last_devpath = NULL; + + grub_ieee1275_open (device, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + + INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2); + args_ieee1275.method = (grub_ieee1275_cell_t) "block-size"; + args_ieee1275.ihandle = last_ihandle; + args_ieee1275.result = 1; + + *block_size = GRUB_DISK_SECTOR_SIZE; + + if ((IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) || (args_ieee1275.result)) + grub_dprintf ("disk", "can't get block size\n"); + else + if (args_ieee1275.size1 + && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1)) + && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384) + *block_size = args_ieee1275.size1; + + return 0; +} diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c index 0e4761b5a..f681eea7f 100644 --- a/grub-core/disk/ldm.c +++ b/grub-core/disk/ldm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -103,37 +104,72 @@ read_int (grub_uint8_t *in, grub_size_t s) return ret; } +static int +check_ldm_partition (grub_disk_t disk __attribute__ ((unused)), const grub_partition_t p, void *data) +{ + int *has_ldm = data; + + if (p->number >= 4) + return 1; + if (p->msdostype == GRUB_PC_PARTITION_TYPE_LDM) + { + *has_ldm = 1; + return 1; + } + return 0; +} + +static int +msdos_has_ldm_partition (grub_disk_t dsk) +{ + grub_err_t err; + int has_ldm = 0; + + err = grub_partition_msdos_iterate (dsk, check_ldm_partition, &has_ldm); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + + return has_ldm; +} + static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM; +/* Helper for gpt_ldm_sector. */ +static int +gpt_ldm_sector_iter (grub_disk_t disk, const grub_partition_t p, void *data) +{ + grub_disk_addr_t *sector = data; + struct grub_gpt_partentry gptdata; + grub_partition_t p2; + + p2 = disk->partition; + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + { + disk->partition = p2; + return 0; + } + disk->partition = p2; + + if (! grub_memcmp (&gptdata.type, &ldm_type, 16)) + { + *sector = p->start + p->len - 1; + return 1; + } + return 0; +} + static grub_disk_addr_t gpt_ldm_sector (grub_disk_t dsk) { grub_disk_addr_t sector = 0; grub_err_t err; - auto int hook (grub_disk_t disk, const grub_partition_t p); - int hook (grub_disk_t disk, const grub_partition_t p) - { - struct grub_gpt_partentry gptdata; - grub_partition_t p2; - p2 = disk->partition; - disk->partition = p->parent; - if (grub_disk_read (disk, p->offset, p->index, - sizeof (gptdata), &gptdata)) - { - disk->partition = p2; - return 0; - } - disk->partition = p2; - - if (! grub_memcmp (&gptdata.type, &ldm_type, 16)) - { - sector = p->start + p->len - 1; - return 1; - } - return 0; - } - err = grub_gpt_partition_map_iterate (dsk, hook); + err = grub_gpt_partition_map_iterate (dsk, gpt_ldm_sector_iter, §or); if (err) { grub_errno = GRUB_ERR_NONE; @@ -671,16 +707,16 @@ make_vg (grub_disk_t disk, if (comp->segment_alloc == 1) { - unsigned index; + unsigned node_index; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } - index = read_int (ptr + 1, *ptr); - if (index < comp->segments->node_count) - comp->segments->nodes[index] = part; + node_index = read_int (ptr + 1, *ptr); + if (node_index < comp->segments->node_count) + comp->segments->nodes[node_index] = part; } else { @@ -756,17 +792,20 @@ grub_ldm_detect (grub_disk_t disk, { int i; + int has_ldm = msdos_has_ldm_partition (disk); for (i = 0; i < 3; i++) { grub_disk_addr_t sector = LDM_LABEL_SECTOR; switch (i) { case 0: + if (!has_ldm) + continue; sector = LDM_LABEL_SECTOR; break; case 1: /* LDM is never inside a partition. */ - if (disk->partition) + if (!has_ldm || disk->partition) continue; sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) @@ -867,6 +906,7 @@ int grub_util_is_ldm (grub_disk_t disk) { int i; + int has_ldm = msdos_has_ldm_partition (disk); for (i = 0; i < 3; i++) { grub_disk_addr_t sector = LDM_LABEL_SECTOR; @@ -876,11 +916,13 @@ grub_util_is_ldm (grub_disk_t disk) switch (i) { case 0: + if (!has_ldm) + continue; sector = LDM_LABEL_SECTOR; break; case 1: /* LDM is never inside a partition. */ - if (disk->partition) + if (!has_ldm || disk->partition) continue; sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index f3b19eff7..d9fa1f3c5 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -135,15 +135,15 @@ fail: static int -grub_loopback_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +grub_loopback_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { struct grub_loopback *d; if (pull != GRUB_DISK_PULL_NONE) return 0; for (d = loopback_list; d; d = d->next) { - if (hook (d->devname)) + if (hook (d->devname, hook_data)) return 1; } return 0; @@ -167,6 +167,10 @@ grub_loopback_open (const char *name, grub_disk_t disk) / GRUB_DISK_SECTOR_SIZE); else disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; + /* Avoid reading more than 512M. */ + disk->max_agglomerate = 1 << (29 - GRUB_DISK_SECTOR_BITS + - GRUB_DISK_CACHE_BITS); + disk->id = (unsigned long) dev; disk->data = dev; @@ -206,7 +210,8 @@ grub_loopback_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "loopback write is not supported"); } static struct grub_disk_dev grub_loopback_dev = diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 44f3cacb7..46f47c2b6 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -82,7 +82,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; const struct gcry_cipher_spec *ciph; grub_cryptodisk_mode_t mode; - grub_cryptodisk_mode_iv_t mode_iv; + grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64; int benbi_log = 0; grub_err_t err; @@ -290,9 +290,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, newdev->log_sector_size = 9; newdev->total_length = grub_disk_get_size (disk) - newdev->offset; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); -#ifdef GRUB_UTIL newdev->modname = "luks"; -#endif COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid)); return newdev; } @@ -318,6 +316,8 @@ luks_recover_key (grub_disk_t source, grub_puts_ (N_("Attempting to decrypt master key...")); keysize = grub_be_to_cpu32 (header.keyBytes); + if (keysize > GRUB_CRYPTODISK_MAX_KEYLEN) + return grub_error (GRUB_ERR_BAD_FS, "key is too long"); for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED @@ -346,8 +346,8 @@ luks_recover_key (grub_disk_t source, for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) { gcry_err_code_t gcry_err; - grub_uint8_t candidate_key[keysize]; - grub_uint8_t digest[keysize]; + grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN]; /* Check if keyslot is enabled. */ if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 508e94af0..4025532c4 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -387,6 +387,29 @@ grub_lvm_detect (grub_disk_t disk, *optr++ = '-'; } *optr++ = 0; + lv->idname = grub_malloc (sizeof ("lvmid/") + + 2 * GRUB_LVM_ID_STRLEN + 1); + if (!lv->idname) + goto lvs_fail; + grub_memcpy (lv->idname, "lvmid/", + sizeof ("lvmid/") - 1); + grub_memcpy (lv->idname + sizeof ("lvmid/") - 1, + vg_id, GRUB_LVM_ID_STRLEN); + lv->idname[sizeof ("lvmid/") - 1 + GRUB_LVM_ID_STRLEN] = '/'; + + p = grub_strstr (q, "id = \""); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("couldn't find ID\n"); +#endif + goto lvs_fail; + } + p += sizeof ("id = \"") - 1; + grub_memcpy (lv->idname + sizeof ("lvmid/") - 1 + + GRUB_LVM_ID_STRLEN + 1, + p, GRUB_LVM_ID_STRLEN); + lv->idname[sizeof ("lvmid/") - 1 + 2 * GRUB_LVM_ID_STRLEN + 1] = '\0'; } lv->size = 0; diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 4de0971ae..20c3f02ba 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -30,13 +30,13 @@ static char *memdisk_addr; static grub_off_t memdisk_size = 0; static int -grub_memdisk_iterate (int (*hook) (const char *name), +grub_memdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { if (pull != GRUB_DISK_PULL_NONE) return 0; - return hook ("memdisk"); + return hook ("memdisk", hook_data); } static grub_err_t @@ -46,6 +46,7 @@ grub_memdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk"); disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; disk->id = (unsigned long) "mdsk"; return GRUB_ERR_NONE; diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 00b04e2d4..8c4b27b7e 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -338,9 +338,10 @@ grub_pata_device_initialize (int port, int device, int addr) } #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS -static int NESTED_FUNC_ATTR +static int grub_pata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid) + grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { static int compat_use[2] = { 0 }; grub_pci_address_t addr; @@ -446,7 +447,7 @@ grub_pata_pciinit (grub_pci_device_t dev, static grub_err_t grub_pata_initialize (void) { - grub_pci_iterate (grub_pata_pciinit); + grub_pci_iterate (grub_pata_pciinit, NULL); return 0; } #else @@ -500,7 +501,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) } static int -grub_pata_iterate (int (*hook) (int id, int bus), +grub_pata_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { struct grub_pata_device *dev; @@ -509,7 +510,8 @@ grub_pata_iterate (int (*hook) (int id, int bus), return 0; for (dev = grub_pata_devices; dev; dev = dev->next) - if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device)) + if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device, + hook_data)) return 1; return 0; @@ -528,13 +530,7 @@ static struct grub_ata_dev grub_pata_dev = GRUB_MOD_INIT(ata_pthru) { - /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) - { - grub_disk_firmware_fini (); - grub_disk_firmware_fini = NULL; - } + grub_stop_disk_firmware (); /* ATA initialization. */ grub_pata_initialize (); diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index ba889ba3d..61a8ba666 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -30,11 +30,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* x**y. */ static grub_uint8_t powx[255 * 2]; /* Such an s that x**s = y */ -static int powx_inv[256]; +static unsigned powx_inv[256]; static const grub_uint8_t poly = 0x1d; static void -grub_raid_block_mulx (int mul, char *buf, int size) +grub_raid_block_mulx (unsigned mul, char *buf, int size) { int i; grub_uint8_t *p; @@ -48,7 +48,7 @@ grub_raid_block_mulx (int mul, char *buf, int size) static void grub_raid6_init_table (void) { - int i; + unsigned i; grub_uint8_t cur = 1; for (i = 0; i < 255; i++) @@ -148,7 +148,7 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, else { /* Two bad devices */ - int c; + unsigned c; if (grub_diskfilter_read_node (&array->nodes[p], sector, size >> GRUB_DISK_SECTOR_BITS, buf)) @@ -162,10 +162,11 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, grub_crypto_xor (qbuf, qbuf, buf, size); - c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255; + c = ((255 ^ bad1) + + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)])) % 255; grub_raid_block_mulx (c, qbuf, size); - c = (bad2 + c) % 255; + c = ((unsigned) bad2 + c) % 255; grub_raid_block_mulx (c, pbuf, size); grub_crypto_xor (pbuf, pbuf, qbuf, size); diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 29dd0d3b8..b6cb2f421 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -423,50 +423,59 @@ grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector, -static int -grub_scsi_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +/* Context for grub_scsi_iterate. */ +struct grub_scsi_iterate_ctx { - grub_scsi_dev_t p; + grub_disk_dev_iterate_hook_t hook; + void *hook_data; +}; - auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns); +/* Helper for grub_scsi_iterate. */ +static int +scsi_iterate (int id, int bus, int luns, void *data) +{ + struct grub_scsi_iterate_ctx *ctx = data; + int i; - int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns) + /* In case of a single LUN, just return `usbX'. */ + if (luns == 1) { - int i; - - /* In case of a single LUN, just return `usbX'. */ - if (luns == 1) - { - char *sname; - int ret; - sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); - if (!sname) - return 1; - ret = hook (sname); - grub_free (sname); - return ret; - } - - /* In case of multiple LUNs, every LUN will get a prefix to - distinguish it. */ - for (i = 0; i < luns; i++) - { - char *sname; - int ret; - sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i); - if (!sname) - return 1; - ret = hook (sname); - grub_free (sname); - if (ret) - return 1; - } - return 0; + char *sname; + int ret; + sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); + if (!sname) + return 1; + ret = ctx->hook (sname, ctx->hook_data); + grub_free (sname); + return ret; } + /* In case of multiple LUNs, every LUN will get a prefix to + distinguish it. */ + for (i = 0; i < luns; i++) + { + char *sname; + int ret; + sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i); + if (!sname) + return 1; + ret = ctx->hook (sname, ctx->hook_data); + grub_free (sname); + if (ret) + return 1; + } + return 0; +} + +static int +grub_scsi_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + struct grub_scsi_iterate_ctx ctx = { hook, hook_data }; + grub_scsi_dev_t p; + for (p = grub_scsi_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (scsi_iterate, pull)) + if (p->iterate && (p->iterate) (scsi_iterate, &ctx, pull)) return 1; return 0; @@ -597,6 +606,13 @@ grub_scsi_open (const char *name, grub_disk_t disk) } disk->total_sectors = scsi->last_block + 1; + /* PATA doesn't support more than 32K reads. + Not sure about AHCI and USB. If it's confirmed that either of + them can do bigger reads reliably this value can be moved to 'scsi' + structure. */ + disk->max_agglomerate = 32768 >> (GRUB_DISK_SECTOR_BITS + + GRUB_DISK_CACHE_BITS); + if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) { grub_free (scsi); @@ -638,40 +654,27 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - while (size) + grub_err_t err; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) { - /* PATA doesn't support more than 32K reads. - Not sure about AHCI and USB. If it's confirmed that either of - them can do bigger reads reliably this value can be moved to 'scsi' - structure. */ - grub_size_t len = 32768 >> disk->log_sector_size; - grub_err_t err; - if (len > size) - len = size; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) - { - case grub_scsi_devtype_direct: - if (sector >> 32) - err = grub_scsi_read16 (disk, sector, len, buf); - else - err = grub_scsi_read10 (disk, sector, len, buf); - if (err) - return err; - break; + case grub_scsi_devtype_direct: + if (sector >> 32) + err = grub_scsi_read16 (disk, sector, size, buf); + else + err = grub_scsi_read10 (disk, sector, size, buf); + if (err) + return err; + break; - case grub_scsi_devtype_cdrom: - if (sector >> 32) - err = grub_scsi_read16 (disk, sector, len, buf); - else - err = grub_scsi_read12 (disk, sector, len, buf); - if (err) - return err; - break; - } - size -= len; - sector += len; - buf += len << disk->log_sector_size; + case grub_scsi_devtype_cdrom: + if (sector >> 32) + err = grub_scsi_read16 (disk, sector, size, buf); + else + err = grub_scsi_read12 (disk, sector, size, buf); + if (err) + return err; + break; } return GRUB_ERR_NONE; @@ -709,10 +712,10 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, } static grub_err_t -grub_scsi_write (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - const char *buf __attribute((unused))) +grub_scsi_write (grub_disk_t disk, + grub_disk_addr_t sector, + grub_size_t size, + const char *buf) { grub_scsi_t scsi; @@ -721,31 +724,18 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)), if (scsi->devtype == grub_scsi_devtype_cdrom) return grub_error (GRUB_ERR_IO, N_("cannot write to CD-ROM")); - while (size) + grub_err_t err; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) { - /* PATA doesn't support more than 32K reads. - Not sure about AHCI and USB. If it's confirmed that either of - them can do bigger reads reliably this value can be moved to 'scsi' - structure. */ - grub_size_t len = 32768 >> disk->log_sector_size; - grub_err_t err; - if (len > size) - len = size; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) - { - case grub_scsi_devtype_direct: - if (sector >> 32) - err = grub_scsi_write16 (disk, sector, len, buf); - else - err = grub_scsi_write10 (disk, sector, len, buf); - if (err) - return err; - break; - } - size -= len; - sector += len; - buf += len << disk->log_sector_size; + case grub_scsi_devtype_direct: + if (sector >> 32) + err = grub_scsi_write16 (disk, sector, size, buf); + else + err = grub_scsi_write10 (disk, sector, size, buf); + if (err) + return err; + break; } return GRUB_ERR_NONE; diff --git a/grub-core/disk/uboot/ubootdisk.c b/grub-core/disk/uboot/ubootdisk.c new file mode 100644 index 000000000..f2c7a6acd --- /dev/null +++ b/grub-core/disk/uboot/ubootdisk.c @@ -0,0 +1,296 @@ +/* ubootdisk.c - disk subsystem support for U-Boot platforms */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct ubootdisk_data *hd_devices; +static int hd_num; +static int hd_max; + +/* + * grub_ubootdisk_register(): + * Called for each disk device enumerated as part of U-Boot initialization + * code. + */ +grub_err_t +grub_ubootdisk_register (struct device_info *newdev) +{ + struct ubootdisk_data *d; + +#define STOR_TYPE(x) ((x) & 0x0ff0) + switch (STOR_TYPE (newdev->type)) + { + case DT_STOR_IDE: + case DT_STOR_SATA: + case DT_STOR_MMC: + case DT_STOR_USB: + /* hd */ + if (hd_num == hd_max) + { + int new_num; + new_num = (hd_max ? hd_max * 2 : 1); + d = grub_realloc(hd_devices, + sizeof (struct ubootdisk_data) * new_num); + if (!d) + return grub_errno; + hd_devices = d; + hd_max = new_num; + } + + d = &hd_devices[hd_num]; + hd_num++; + break; + default: + return GRUB_ERR_BAD_DEVICE; + break; + } + + d->dev = newdev; + d->cookie = newdev->cookie; + d->opencount = 0; + + return 0; +} + +/* + * uboot_disk_iterate(): + * Iterator over enumerated disk devices. + */ +static int +uboot_disk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + char buf[16]; + int count; + + switch (pull) + { + case GRUB_DISK_PULL_NONE: + /* "hd" - built-in mass-storage */ + for (count = 0 ; count < hd_num; count++) + { + grub_snprintf (buf, sizeof (buf) - 1, "hd%d", count); + grub_dprintf ("ubootdisk", "iterating %s\n", buf); + if (hook (buf, hook_data)) + return 1; + } + break; + default: + return 0; + } + + return 0; +} + +/* Helper function for uboot_disk_open. */ +static struct ubootdisk_data * +get_hd_device (int num) +{ + if (num < hd_num) + return &hd_devices[num]; + + return NULL; +} + +/* + * uboot_disk_open(): + * Opens a disk device already enumerated. + */ +static grub_err_t +uboot_disk_open (const char *name, struct grub_disk *disk) +{ + struct ubootdisk_data *d; + struct device_info *devinfo; + int num; + int retval; + + grub_dprintf ("ubootdisk", "Opening '%s'\n", name); + + num = grub_strtoul (name + 2, 0, 10); + if (grub_errno != GRUB_ERR_NONE) + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid number\n", + name); + goto fail; + } + + if (name[1] != 'd') + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid name\n", name); + goto fail; + } + + switch (name[0]) + { + case 'h': + d = get_hd_device (num); + break; + default: + goto fail; + } + + if (!d) + goto fail; + + /* + * Subsystems may call open on the same device recursively - but U-Boot + * does not deal with this. So simply keep track of number of calls and + * return success if already open. + */ + if (d->opencount > 0) + { + grub_dprintf ("ubootdisk", "(%s) already open\n", disk->name); + d->opencount++; + retval = 0; + } + else + { + retval = grub_uboot_dev_open (d->dev); + if (retval != 0) + goto fail; + d->opencount = 1; + } + + grub_dprintf ("ubootdisk", "cookie: 0x%08x\n", (grub_addr_t) d->cookie); + disk->id = (grub_addr_t) d->cookie; + + devinfo = d->dev; + + d->block_size = devinfo->di_stor.block_size; + if (d->block_size == 0) + return grub_error (GRUB_ERR_IO, "no block size"); + + for (disk->log_sector_size = 0; + (1U << disk->log_sector_size) < d->block_size; + disk->log_sector_size++); + + grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n", + disk->name, d->block_size, disk->log_sector_size); + + if (devinfo->di_stor.block_count) + disk->total_sectors = devinfo->di_stor.block_count; + else + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; + + disk->data = d; + + return GRUB_ERR_NONE; + +fail: + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); +} + +static void +uboot_disk_close (struct grub_disk *disk) +{ + struct ubootdisk_data *d; + int retval; + + d = disk->data; + + /* + * In mirror of open function, keep track of number of calls to close and + * send on to U-Boot only when opencount would decrease to 0. + */ + if (d->opencount > 1) + { + grub_dprintf ("ubootdisk", "Closed (%s)\n", disk->name); + + d->opencount--; + } + else if (d->opencount == 1) + { + retval = grub_uboot_dev_close (d->dev); + d->opencount--; + grub_dprintf ("ubootdisk", "closed %s (%d)\n", disk->name, retval); + } + else + { + grub_dprintf ("ubootdisk", "device %s not open!\n", disk->name); + } +} + +/* + * uboot_disk_read(): + * Called from within disk subsystem to read a sequence of blocks into the + * disk cache. Maps directly on top of U-Boot API, only wrap in some error + * handling. + */ +static grub_err_t +uboot_disk_read (struct grub_disk *disk, + grub_disk_addr_t offset, grub_size_t numblocks, char *buf) +{ + struct ubootdisk_data *d; + grub_size_t real_size; + int retval; + + d = disk->data; + + retval = grub_uboot_dev_read (d->dev, buf, numblocks, offset, &real_size); + grub_dprintf ("ubootdisk", + "retval=%d, numblocks=%d, real_size=%llu, sector=%llu\n", + retval, numblocks, (grub_uint64_t) real_size, + (grub_uint64_t) offset); + if (retval != 0) + return grub_error (GRUB_ERR_IO, "U-Boot disk read error"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +uboot_disk_write (struct grub_disk *disk __attribute__ ((unused)), + grub_disk_addr_t sector __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused)), + const char *buf __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "attempt to write (not supported)"); +} + +static struct grub_disk_dev grub_ubootdisk_dev = { + .name = "ubootdisk", + .id = GRUB_DISK_DEVICE_UBOOTDISK_ID, + .iterate = uboot_disk_iterate, + .open = uboot_disk_open, + .close = uboot_disk_close, + .read = uboot_disk_read, + .write = uboot_disk_write, + .next = 0 +}; + +void +grub_ubootdisk_init (void) +{ + grub_disk_dev_register (&grub_ubootdisk_dev); +} + +void +grub_ubootdisk_fini (void) +{ + grub_disk_dev_unregister (&grub_ubootdisk_dev); +} diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index 52cc33e93..af92243d2 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -76,7 +76,7 @@ typedef struct grub_usbms_dev *grub_usbms_dev_t; static grub_usbms_dev_t grub_usbms_devices[MAX_USBMS_DEVICES]; static int first_available_slot = 0; -static grub_err_t +static grub_usb_err_t grub_usbms_cbi_cmd (grub_usb_device_t dev, int interface, grub_uint8_t *cbicb) { @@ -86,7 +86,7 @@ grub_usbms_cbi_cmd (grub_usb_device_t dev, int interface, GRUB_USBMS_CBI_CMD_SIZE, (char*)cbicb); } -static grub_err_t +static grub_usb_err_t grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) { /* Prepare array with Command Block Reset (=CBR) */ @@ -108,17 +108,13 @@ grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) return grub_usbms_cbi_cmd (dev, interface, (grub_uint8_t *)&cbicb); } -static grub_err_t +static grub_usb_err_t grub_usbms_bo_reset (grub_usb_device_t dev, int interface) { - grub_usb_err_t u; - u = grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0); - if (u) - return grub_error (GRUB_ERR_IO, "USB error %d", u); - return GRUB_ERR_NONE; + return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0); } -static grub_err_t +static grub_usb_err_t grub_usbms_reset (grub_usbms_dev_t dev) { if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK) @@ -149,7 +145,9 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) int j; grub_uint8_t luns = 0; unsigned curnum; - grub_usb_err_t err = GRUB_ERR_NONE; + grub_usb_err_t err = GRUB_USB_ERR_NONE; + + grub_boot_time ("Attaching USB mass storage"); if (first_available_slot == ARRAY_SIZE (grub_usbms_devices)) return 0; @@ -246,6 +244,8 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) usbdev->config[configno].interf[interfno].detach_hook = grub_usbms_detach; + grub_boot_time ("Attached USB mass storage"); + #if 0 /* All this part should be probably deleted. * This make trouble on some devices if they are not in * Phase Error state - and there they should be not in such state... @@ -265,7 +265,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) static int -grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), +grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { unsigned i; @@ -273,12 +273,13 @@ grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), if (pull != GRUB_DISK_PULL_NONE) return 0; - grub_usb_poll_devices (); + grub_usb_poll_devices (1); for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) if (grub_usbms_devices[i]) { - if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns)) + if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns, + hook_data)) return 1; } @@ -325,7 +326,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Write the request. * XXX: Error recovery is maybe still not fully correct. */ - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, + err = grub_usb_bulk_write (dev->dev, dev->out, sizeof (cbw), (char *) &cbw); if (err) { @@ -340,7 +341,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); + err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL); if (err) { @@ -361,7 +362,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } else if (size) { - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out, size, buf); grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL); grub_dprintf ("usb", "First 16 bytes of sent data:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[ 0], buf[ 1], buf[ 2], buf[ 3], @@ -387,12 +388,12 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read the status - (maybe) according to specification. */ CheckCSW: - errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in, sizeof (status), (char *) &status); if (errCSW) { grub_usb_clear_halt (dev->dev, dev->in->endp_addr); - errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in, sizeof (status), (char *) &status); if (errCSW) { /* Bulk-only reset device. */ @@ -475,7 +476,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, else if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI) { /* Try to get status from interrupt pipe */ - err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, + err = grub_usb_bulk_read (dev->dev, dev->intrpt, 2, (char*)&status); grub_dprintf ("usb", "CBI cmdcb setup status: err=%d, status=0x%x\n", err, status); } @@ -486,7 +487,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); + err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); grub_dprintf ("usb", "read: %d\n", err); if (err) { @@ -497,7 +498,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } else if (size) { - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out, size, buf); grub_dprintf ("usb", "write: %d\n", err); if (err) { @@ -516,7 +517,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, * (we do not it yet) - ? */ if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI) { /* Check status in interrupt pipe */ - err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, + err = grub_usb_bulk_read (dev->dev, dev->intrpt, 2, (char*)&status); grub_dprintf ("usb", "read status: %d\n", err); if (err) @@ -566,8 +567,11 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } } } + + if (err) + return grub_error (GRUB_ERR_IO, "USB error %d", err); - return err; + return GRUB_ERR_NONE; } @@ -606,7 +610,8 @@ grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not USB Mass Storage device"); - grub_usb_poll_devices (); + if (!grub_usbms_devices[devnum]) + grub_usb_poll_devices (1); if (!grub_usbms_devices[devnum]) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, diff --git a/grub-core/disk/xen/xendisk.c b/grub-core/disk/xen/xendisk.c new file mode 100644 index 000000000..c44984807 --- /dev/null +++ b/grub-core/disk/xen/xendisk.c @@ -0,0 +1,453 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct virtdisk +{ + int handle; + char *fullname; + char *backend_dir; + char *frontend_dir; + struct blkif_sring *shared_page; + struct blkif_front_ring ring; + grub_xen_grant_t grant; + grub_xen_evtchn_t evtchn; + void *dma_page; + grub_xen_grant_t dma_grant; +}; + +#define xen_wmb() mb() +#define xen_mb() mb() + +static struct virtdisk *virtdisks; +static grub_size_t vdiskcnt; + +static int +grub_virtdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + grub_size_t i; + + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + for (i = 0; i < vdiskcnt; i++) + if (hook (virtdisks[i].fullname, hook_data)) + return 1; + return 0; +} + +static grub_err_t +grub_virtdisk_open (const char *name, grub_disk_t disk) +{ + grub_size_t i; + grub_uint32_t secsize; + char fdir[200]; + char *buf; + + for (i = 0; i < vdiskcnt; i++) + if (grub_strcmp (name, virtdisks[i].fullname) == 0) + break; + if (i == vdiskcnt) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a virtdisk"); + disk->data = &virtdisks[i]; + disk->id = i; + + grub_snprintf (fdir, sizeof (fdir), "%s/sectors", virtdisks[i].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + return grub_errno; + disk->total_sectors = grub_strtoull (buf, 0, 10); + if (grub_errno) + return grub_errno; + + grub_snprintf (fdir, sizeof (fdir), "%s/sector-size", + virtdisks[i].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + return grub_errno; + secsize = grub_strtoull (buf, 0, 10); + if (grub_errno) + return grub_errno; + + if ((secsize & (secsize - 1)) || !secsize || secsize < 512 + || secsize > GRUB_XEN_PAGE_SIZE) + return grub_error (GRUB_ERR_IO, "unsupported sector size %d", secsize); + + for (disk->log_sector_size = 0; + (1U << disk->log_sector_size) < secsize; disk->log_sector_size++); + + disk->total_sectors >>= disk->log_sector_size - 9; + + return GRUB_ERR_NONE; +} + +static void +grub_virtdisk_close (grub_disk_t disk __attribute__ ((unused))) +{ +} + +static grub_err_t +grub_virtdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + struct virtdisk *data = disk->data; + + while (size) + { + grub_size_t cur; + struct blkif_request *req; + struct blkif_response *resp; + int sta = 0; + struct evtchn_send send; + cur = size; + if (cur > (unsigned) (GRUB_XEN_PAGE_SIZE >> disk->log_sector_size)) + cur = GRUB_XEN_PAGE_SIZE >> disk->log_sector_size; + while (RING_FULL (&data->ring)) + grub_xen_sched_op (SCHEDOP_yield, 0); + req = RING_GET_REQUEST (&data->ring, data->ring.req_prod_pvt); + req->operation = BLKIF_OP_READ; + req->nr_segments = 1; + req->handle = data->handle; + req->id = 0; + req->sector_number = sector << (disk->log_sector_size - 9); + req->seg[0].gref = data->dma_grant; + req->seg[0].first_sect = 0; + req->seg[0].last_sect = (cur << (disk->log_sector_size - 9)) - 1; + data->ring.req_prod_pvt++; + RING_PUSH_REQUESTS (&data->ring); + mb (); + send.port = data->evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + + while (!RING_HAS_UNCONSUMED_RESPONSES (&data->ring)) + { + grub_xen_sched_op (SCHEDOP_yield, 0); + mb (); + } + while (1) + { + int wtd; + RING_FINAL_CHECK_FOR_RESPONSES (&data->ring, wtd); + if (!wtd) + break; + resp = RING_GET_RESPONSE (&data->ring, data->ring.rsp_cons); + data->ring.rsp_cons++; + if (resp->status) + sta = resp->status; + } + if (sta) + return grub_error (GRUB_ERR_IO, "read failed"); + grub_memcpy (buf, data->dma_page, cur << disk->log_sector_size); + size -= cur; + sector += cur; + buf += cur << disk->log_sector_size; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_virtdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) +{ + struct virtdisk *data = disk->data; + + while (size) + { + grub_size_t cur; + struct blkif_request *req; + struct blkif_response *resp; + int sta = 0; + struct evtchn_send send; + cur = size; + if (cur > (unsigned) (GRUB_XEN_PAGE_SIZE >> disk->log_sector_size)) + cur = GRUB_XEN_PAGE_SIZE >> disk->log_sector_size; + + grub_memcpy (data->dma_page, buf, cur << disk->log_sector_size); + + while (RING_FULL (&data->ring)) + grub_xen_sched_op (SCHEDOP_yield, 0); + req = RING_GET_REQUEST (&data->ring, data->ring.req_prod_pvt); + req->operation = BLKIF_OP_WRITE; + req->nr_segments = 1; + req->handle = data->handle; + req->id = 0; + req->sector_number = sector << (disk->log_sector_size - 9); + req->seg[0].gref = data->dma_grant; + req->seg[0].first_sect = 0; + req->seg[0].last_sect = (cur << (disk->log_sector_size - 9)) - 1; + data->ring.req_prod_pvt++; + RING_PUSH_REQUESTS (&data->ring); + mb (); + send.port = data->evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + + while (!RING_HAS_UNCONSUMED_RESPONSES (&data->ring)) + { + grub_xen_sched_op (SCHEDOP_yield, 0); + mb (); + } + while (1) + { + int wtd; + RING_FINAL_CHECK_FOR_RESPONSES (&data->ring, wtd); + if (!wtd) + break; + resp = RING_GET_RESPONSE (&data->ring, data->ring.rsp_cons); + data->ring.rsp_cons++; + if (resp->status) + sta = resp->status; + } + if (sta) + return grub_error (GRUB_ERR_IO, "write failed"); + size -= cur; + sector += cur; + buf += cur << disk->log_sector_size; + } + return GRUB_ERR_NONE; +} + +static struct grub_disk_dev grub_virtdisk_dev = { + .name = "xen", + .id = GRUB_DISK_DEVICE_XEN, + .iterate = grub_virtdisk_iterate, + .open = grub_virtdisk_open, + .close = grub_virtdisk_close, + .read = grub_virtdisk_read, + .write = grub_virtdisk_write, + .next = 0 +}; + +static int +count (const char *dir __attribute__ ((unused)), void *data) +{ + grub_size_t *ctr = data; + (*ctr)++; + + return 0; +} + +static int +fill (const char *dir, void *data) +{ + grub_size_t *ctr = data; + domid_t dom; + /* "dir" is just a number, at most 19 characters. */ + char fdir[200]; + char num[20]; + grub_err_t err; + void *buf; + struct evtchn_alloc_unbound alloc_unbound; + + /* Shouldn't happen unles some hotplug happened. */ + if (vdiskcnt >= *ctr) + return 1; + virtdisks[vdiskcnt].handle = grub_strtoul (dir, 0, 10); + if (grub_errno) + { + grub_errno = 0; + return 0; + } + virtdisks[vdiskcnt].fullname = 0; + virtdisks[vdiskcnt].backend_dir = 0; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/backend", dir); + virtdisks[vdiskcnt].backend_dir = grub_xenstore_get_file (fdir, NULL); + if (!virtdisks[vdiskcnt].backend_dir) + goto out_fail_1; + + grub_snprintf (fdir, sizeof (fdir), "%s/dev", + virtdisks[vdiskcnt].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + { + grub_errno = 0; + virtdisks[vdiskcnt].fullname = grub_xasprintf ("xenid/%s", dir); + } + else + { + virtdisks[vdiskcnt].fullname = grub_xasprintf ("xen/%s", (char *) buf); + grub_free (buf); + } + if (!virtdisks[vdiskcnt].fullname) + goto out_fail_1; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/backend-id", dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + goto out_fail_1; + + dom = grub_strtoul (buf, 0, 10); + grub_free (buf); + if (grub_errno) + goto out_fail_1; + + virtdisks[vdiskcnt].shared_page = + grub_xen_alloc_shared_page (dom, &virtdisks[vdiskcnt].grant); + if (!virtdisks[vdiskcnt].shared_page) + goto out_fail_1; + + virtdisks[vdiskcnt].dma_page = + grub_xen_alloc_shared_page (dom, &virtdisks[vdiskcnt].dma_grant); + if (!virtdisks[vdiskcnt].dma_page) + goto out_fail_2; + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = dom; + + grub_xen_event_channel_op (EVTCHNOP_alloc_unbound, &alloc_unbound); + virtdisks[vdiskcnt].evtchn = alloc_unbound.port; + + SHARED_RING_INIT (virtdisks[vdiskcnt].shared_page); + FRONT_RING_INIT (&virtdisks[vdiskcnt].ring, virtdisks[vdiskcnt].shared_page, + GRUB_XEN_PAGE_SIZE); + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/ring-ref", dir); + grub_snprintf (num, sizeof (num), "%u", virtdisks[vdiskcnt].grant); + err = grub_xenstore_write_file (fdir, num, grub_strlen (num)); + if (err) + goto out_fail_3; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/event-channel", dir); + grub_snprintf (num, sizeof (num), "%u", virtdisks[vdiskcnt].evtchn); + err = grub_xenstore_write_file (fdir, num, grub_strlen (num)); + if (err) + goto out_fail_3; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/protocol", dir); + err = grub_xenstore_write_file (fdir, XEN_IO_PROTO_ABI_NATIVE, + grub_strlen (XEN_IO_PROTO_ABI_NATIVE)); + if (err) + goto out_fail_3; + + struct gnttab_dump_table dt; + dt.dom = DOMID_SELF; + grub_xen_grant_table_op (GNTTABOP_dump_table, (void *) &dt, 1); + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/state", dir); + err = grub_xenstore_write_file (fdir, "3", 1); + if (err) + goto out_fail_3; + + while (1) + { + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[vdiskcnt].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + goto out_fail_3; + if (grub_strcmp (buf, "2") != 0) + break; + grub_free (buf); + grub_xen_sched_op (SCHEDOP_yield, 0); + } + grub_dprintf ("xen", "state=%s\n", (char *) buf); + grub_free (buf); + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s", dir); + + virtdisks[vdiskcnt].frontend_dir = grub_strdup (fdir); + + vdiskcnt++; + return 0; + +out_fail_3: + grub_xen_free_shared_page (virtdisks[vdiskcnt].dma_page); +out_fail_2: + grub_xen_free_shared_page (virtdisks[vdiskcnt].shared_page); +out_fail_1: + grub_free (virtdisks[vdiskcnt].backend_dir); + grub_free (virtdisks[vdiskcnt].fullname); + + grub_errno = 0; + return 0; +} + +void +grub_xendisk_init (void) +{ + grub_size_t ctr = 0; + if (grub_xenstore_dir ("device/vbd", count, &ctr)) + grub_errno = 0; + + if (!ctr) + return; + + virtdisks = grub_malloc (ctr * sizeof (virtdisks[0])); + if (!virtdisks) + return; + if (grub_xenstore_dir ("device/vbd", fill, &ctr)) + grub_errno = 0; + + grub_disk_dev_register (&grub_virtdisk_dev); +} + +void +grub_xendisk_fini (void) +{ + char fdir[200]; + unsigned i; + + for (i = 0; i < vdiskcnt; i++) + { + char *buf; + struct evtchn_close close_op = {.port = virtdisks[i].evtchn }; + + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, "6", 1); + + while (1) + { + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[i].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + grub_dprintf ("xen", "state=%s\n", (char *) buf); + + if (!buf || grub_strcmp (buf, "6") == 0) + break; + grub_free (buf); + grub_xen_sched_op (SCHEDOP_yield, 0); + } + grub_free (buf); + + grub_snprintf (fdir, sizeof (fdir), "%s/ring-ref", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, NULL, 0); + + grub_snprintf (fdir, sizeof (fdir), "%s/event-channel", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, NULL, 0); + + grub_xen_free_shared_page (virtdisks[i].dma_page); + grub_xen_free_shared_page (virtdisks[i].shared_page); + + grub_xen_event_channel_op (EVTCHNOP_close, &close_op); + } +} diff --git a/grub-core/efiemu/i386/coredetect.c b/grub-core/efiemu/i386/coredetect.c index c3782fda9..a262b5328 100644 --- a/grub-core/efiemu/i386/coredetect.c +++ b/grub-core/efiemu/i386/coredetect.c @@ -18,42 +18,10 @@ #include #include - -#define cpuid(num,a,b,c,d) \ - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ - : "0" (num)) - -#define bit_LM (1 << 29) +#include const char * grub_efiemu_get_default_core_name (void) { - - unsigned int eax, ebx, ecx, edx; - unsigned int max_level; - unsigned int ext_level; - - /* See if we can use cpuid. */ - asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" - "pushl %0; popfl; pushfl; popl %0; popfl" - : "=&r" (eax), "=&r" (ebx) - : "i" (0x00200000)); - if (((eax ^ ebx) & 0x00200000) == 0) - return "efiemu32.o"; - - /* Check the highest input value for eax. */ - cpuid (0, eax, ebx, ecx, edx); - /* We only look at the first four characters. */ - max_level = eax; - if (max_level == 0) - return "efiemu32.o"; - - cpuid (0x80000000, eax, ebx, ecx, edx); - ext_level = eax; - if (ext_level < 0x80000000) - return "efiemu32.o"; - - cpuid (0x80000001, eax, ebx, ecx, edx); - return (edx & bit_LM) ? "efiemu64.o" : "efiemu32.o"; + return grub_cpuid_has_longmode ? "efiemu64.o" : "efiemu32.o"; } diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index 10cbc68cc..d4a4f3aad 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -268,26 +268,26 @@ grub_efiemu_mm_return_request (int handle) } } +/* Helper for grub_efiemu_mmap_init. */ +static int +bounds_hook (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + mmap_reserved_size++; + return 0; +} + /* Reserve space for memory map */ static grub_err_t grub_efiemu_mmap_init (void) { - auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - grub_memory_type_t type - __attribute__ ((unused))) - { - mmap_reserved_size++; - return 0; - } - // the place for memory used by efiemu itself mmap_reserved_size = GRUB_EFI_MAX_MEMORY_TYPE + 1; #ifndef GRUB_MACHINE_EMU - grub_machine_mmap_iterate (bounds_hook); + grub_machine_mmap_iterate (bounds_hook, NULL); #endif return GRUB_ERR_NONE; @@ -383,48 +383,47 @@ grub_efiemu_mm_init (void) return GRUB_ERR_NONE; } +/* Helper for grub_efiemu_mmap_fill. */ +static int +fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) + { + switch (type) + { + case GRUB_MEMORY_AVAILABLE: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_CONVENTIONAL_MEMORY); + + case GRUB_MEMORY_ACPI: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_ACPI_RECLAIM_MEMORY); + + case GRUB_MEMORY_NVS: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_ACPI_MEMORY_NVS); + + default: + grub_dprintf ("efiemu", + "Unknown memory type %d. Assuming unusable\n", type); + case GRUB_MEMORY_RESERVED: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_UNUSABLE_MEMORY); + } + } + /* Copy host memory map */ static grub_err_t grub_efiemu_mmap_fill (void) { - auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, - grub_uint64_t size, - grub_memory_type_t type) - { - switch (type) - { - case GRUB_MEMORY_AVAILABLE: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_CONVENTIONAL_MEMORY); - - case GRUB_MEMORY_ACPI: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_ACPI_RECLAIM_MEMORY); - - case GRUB_MEMORY_NVS: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_ACPI_MEMORY_NVS); - - default: - grub_dprintf ("efiemu", - "Unknown memory type %d. Assuming unusable\n", type); - case GRUB_MEMORY_RESERVED: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_UNUSABLE_MEMORY); - } - } - #ifndef GRUB_MACHINE_EMU - grub_machine_mmap_iterate (fill_hook); + grub_machine_mmap_iterate (fill_hook, NULL); #endif return GRUB_ERR_NONE; } grub_err_t -grub_efiemu_mmap_iterate (grub_memory_hook_t hook) +grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { unsigned i; @@ -433,12 +432,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook) { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_CODE); + GRUB_MEMORY_CODE, hook_data); break; case GRUB_EFI_UNUSABLE_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_BADRAM); + GRUB_MEMORY_BADRAM, hook_data); break; case GRUB_EFI_RESERVED_MEMORY_TYPE: @@ -448,7 +447,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook) case GRUB_EFI_PAL_CODE: case GRUB_EFI_MAX_MEMORY_TYPE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED, hook_data); break; case GRUB_EFI_LOADER_CODE: @@ -457,17 +456,17 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook) case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_ACPI); + GRUB_MEMORY_ACPI, hook_data); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_NVS); + GRUB_MEMORY_NVS, hook_data); break; } diff --git a/grub-core/efiemu/pnvram.c b/grub-core/efiemu/pnvram.c index 28d005044..c5c3d4bd3 100644 --- a/grub-core/efiemu/pnvram.c +++ b/grub-core/efiemu/pnvram.c @@ -102,92 +102,7 @@ nvram_set (void * data __attribute__ ((unused))) grub_uint32_t *accuracy = grub_efiemu_mm_obtain_request (accuracy_handle); char *nvramptr; - - auto int iterate_env (struct grub_env_var *var); - int iterate_env (struct grub_env_var *var) - { - char *guid, *attr, *name, *varname; - struct efi_variable *efivar; - int len = 0; - int i; - grub_uint64_t guidcomp; - - if (grub_memcmp (var->name, "EfiEmu.pnvram.", - sizeof ("EfiEmu.pnvram.") - 1) != 0) - return 0; - - guid = var->name + sizeof ("EfiEmu.pnvram.") - 1; - - attr = grub_strchr (guid, '.'); - if (!attr) - return 0; - attr++; - - name = grub_strchr (attr, '.'); - if (!name) - return 0; - name++; - - efivar = (struct efi_variable *) nvramptr; - if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, - "too many NVRAM variables for reserved variable space." - " Try increasing EfiEmu.pnvram.size"); - return 1; - } - - nvramptr += sizeof (struct efi_variable); - - efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16)); - if (*guid != '-') - return 0; - guid++; - - efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); - if (*guid != '-') - return 0; - guid++; - - efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); - if (*guid != '-') - return 0; - guid++; - - guidcomp = grub_strtoull (guid, 0, 16); - for (i = 0; i < 8; i++) - efivar->guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff; - - efivar->attributes = grub_strtoull (attr, 0, 16); - - varname = grub_malloc (grub_strlen (name) + 1); - if (! varname) - return 1; - - if (unescape (name, varname, varname + grub_strlen (name) + 1, &len)) - return 1; - - len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr, - (nvramsize - (nvramptr - nvram)) / 2, - (grub_uint8_t *) varname, len, NULL); - - nvramptr += 2 * len; - *((grub_uint16_t *) nvramptr) = 0; - nvramptr += 2; - efivar->namelen = 2 * len + 2; - - if (unescape (var->value, nvramptr, nvram + nvramsize, &len)) - { - efivar->namelen = 0; - return 1; - } - - nvramptr += len; - - efivar->size = len; - - return 0; - } + struct grub_env_var *var; /* Copy to definitive loaction */ grub_dprintf ("efiemu", "preparing pnvram\n"); @@ -203,9 +118,88 @@ nvram_set (void * data __attribute__ ((unused))) nvramptr = nvram; grub_memset (nvram, 0, nvramsize); - grub_env_iterate (iterate_env); + FOR_SORTED_ENV (var) + { + char *guid, *attr, *name, *varname; + struct efi_variable *efivar; + int len = 0; + int i; + grub_uint64_t guidcomp; + + if (grub_memcmp (var->name, "EfiEmu.pnvram.", + sizeof ("EfiEmu.pnvram.") - 1) != 0) + continue; + + guid = var->name + sizeof ("EfiEmu.pnvram.") - 1; + + attr = grub_strchr (guid, '.'); + if (!attr) + continue; + attr++; + + name = grub_strchr (attr, '.'); + if (!name) + continue; + name++; + + efivar = (struct efi_variable *) nvramptr; + if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "too many NVRAM variables for reserved variable space." + " Try increasing EfiEmu.pnvram.size"); + + nvramptr += sizeof (struct efi_variable); + + efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16)); + if (*guid != '-') + continue; + guid++; + + efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); + if (*guid != '-') + continue; + guid++; + + efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); + if (*guid != '-') + continue; + guid++; + + guidcomp = grub_strtoull (guid, 0, 16); + for (i = 0; i < 8; i++) + efivar->guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff; + + efivar->attributes = grub_strtoull (attr, 0, 16); + + varname = grub_malloc (grub_strlen (name) + 1); + if (! varname) + return grub_errno; + + if (unescape (name, varname, varname + grub_strlen (name) + 1, &len)) + break; + + len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr, + (nvramsize - (nvramptr - nvram)) / 2, + (grub_uint8_t *) varname, len, NULL); + + nvramptr += 2 * len; + *((grub_uint16_t *) nvramptr) = 0; + nvramptr += 2; + efivar->namelen = 2 * len + 2; + + if (unescape (var->value, nvramptr, nvram + nvramsize, &len)) + { + efivar->namelen = 0; + break; + } + + nvramptr += len; + + efivar->size = len; + } if (grub_errno) return grub_errno; + *nvramsize_def = nvramsize; /* Register symbols */ diff --git a/grub-core/efiemu/prepare.c b/grub-core/efiemu/prepare.c index 2aef8634d..fb1b25d17 100644 --- a/grub-core/efiemu/prepare.c +++ b/grub-core/efiemu/prepare.c @@ -122,7 +122,10 @@ SUFFIX (grub_efiemu_crc) (void) int handle; grub_off_t off; struct SUFFIX (grub_efiemu_runtime_services) *runtime_services; - grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + grub_uint32_t crc32_val; + + if (GRUB_MD_CRC32->mdlen != 4) + return grub_error (GRUB_ERR_BUG, "incorrect mdlen"); /* compute CRC32 of runtime_services */ err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", @@ -134,12 +137,11 @@ SUFFIX (grub_efiemu_crc) (void) ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off); runtime_services->hdr.crc32 = 0; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, runtime_services, runtime_services->hdr.header_size); - GRUB_MD_CRC32->final(crc32_context); + grub_crypto_hash (GRUB_MD_CRC32, &crc32_val, + runtime_services, runtime_services->hdr.header_size); runtime_services->hdr.crc32 = - grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)); + grub_be_to_cpu32(crc32_val); err = grub_efiemu_resolve_symbol ("efiemu_system_table", &handle, &off); if (err) @@ -147,12 +149,11 @@ SUFFIX (grub_efiemu_crc) (void) /* compute CRC32 of system table */ SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, SUFFIX (grub_efiemu_system_table), - SUFFIX (grub_efiemu_system_table)->hdr.header_size); - GRUB_MD_CRC32->final(crc32_context); + grub_crypto_hash (GRUB_MD_CRC32, &crc32_val, + SUFFIX (grub_efiemu_system_table), + SUFFIX (grub_efiemu_system_table)->hdr.header_size); SUFFIX (grub_efiemu_system_table)->hdr.crc32 = - grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)); + grub_be_to_cpu32(crc32_val); grub_dprintf ("efiemu","system_table = %p, runtime_services = %p\n", SUFFIX (grub_efiemu_system_table), runtime_services); diff --git a/grub-core/efiemu/runtime/config.h b/grub-core/efiemu/runtime/config.h index 26fb2ff08..c9fe02716 100644 --- a/grub-core/efiemu/runtime/config.h +++ b/grub-core/efiemu/runtime/config.h @@ -19,16 +19,18 @@ #define GRUB_TYPES_CPU_HEADER 1 -#ifdef ELF32 +#ifdef __i386__ # define SIZEOF_VOID_P 4 # define SIZEOF_LONG 4 # define GRUB_TARGET_SIZEOF_VOID_P 4 # define GRUB_TARGET_SIZEOF_LONG 4 # define EFI_FUNC(x) x -#else +#elif defined (__x86_64__) # define SIZEOF_VOID_P 8 # define SIZEOF_LONG 8 # define GRUB_TARGET_SIZEOF_VOID_P 8 # define GRUB_TARGET_SIZEOF_LONG 8 # define EFI_FUNC(x) x ## _real +#else +#error "Unknown architecture" #endif diff --git a/grub-core/font/font.c b/grub-core/font/font.c index fca8c8d00..d603dbe04 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -33,7 +33,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); -#ifdef USE_ASCII_FAILBACK +#ifdef USE_ASCII_FALLBACK #include "ascii.h" #endif @@ -55,23 +55,6 @@ struct char_index_entry #define FONT_WEIGHT_BOLD 200 #define ASCII_BITMAP_SIZE 16 -struct grub_font -{ - char *name; - grub_file_t file; - char *family; - short point_size; - short weight; - short max_char_width; - short max_char_height; - short ascent; - short descent; - short leading; - grub_uint32_t num_chars; - struct char_index_entry *char_index; - grub_uint16_t *bmp_idx; -}; - /* Definition of font registry. */ struct grub_font_node *grub_font_list; @@ -127,14 +110,14 @@ static struct grub_font null_font; /* Flag to ensure module is initialized only once. */ static grub_uint8_t font_loader_initialized; -#ifdef USE_ASCII_FAILBACK +#ifdef USE_ASCII_FALLBACK static struct grub_font_glyph *ascii_font_glyph[0x80]; #endif static struct grub_font_glyph * ascii_glyph_lookup (grub_uint32_t code) { -#ifdef USE_ASCII_FAILBACK +#ifdef USE_ASCII_FALLBACK static int ascii_failback_initialized = 0; if (code >= 0x80) @@ -293,7 +276,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct grub_uint32_t last_code; #if FONT_DEBUG >= 2 - grub_printf ("load_font_index(sect_length=%d)\n", sect_length); + grub_dprintf ("font", "load_font_index(sect_length=%d)\n", sect_length); #endif /* Sanity check: ensure section length is divisible by the entry size. */ @@ -321,7 +304,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct #if FONT_DEBUG >= 2 - grub_printf ("num_chars=%d)\n", font->num_chars); + grub_dprintf ("font", "num_chars=%d)\n", font->num_chars); #endif last_code = 0; @@ -365,7 +348,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct #if FONT_DEBUG >= 5 /* Print the 1st 10 characters. */ if (i < 10) - grub_printf ("c=%d o=%d\n", entry->code, entry->offset); + grub_dprintf ("font", "c=%d o=%d\n", entry->code, entry->offset); #endif } @@ -422,7 +405,7 @@ read_section_as_short (struct font_file_section *section, /* Load a font and add it to the beginning of the global font list. Returns 0 upon success, nonzero upon failure. */ -int +grub_font_t grub_font_load (const char *filename) { grub_file_t file = 0; @@ -431,7 +414,7 @@ grub_font_load (const char *filename) grub_font_t font = 0; #if FONT_DEBUG >= 1 - grub_printf ("add_font(%s)\n", filename); + grub_dprintf ("font", "add_font(%s)\n", filename); #endif if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+') @@ -462,7 +445,7 @@ grub_font_load (const char *filename) goto fail; #if FONT_DEBUG >= 3 - grub_printf ("file opened\n"); + grub_dprintf ("font", "file opened\n"); #endif /* Read the FILE section. It indicates the file format. */ @@ -470,7 +453,7 @@ grub_font_load (const char *filename) goto fail; #if FONT_DEBUG >= 3 - grub_printf ("opened FILE section\n"); + grub_dprintf ("font", "opened FILE section\n"); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE, sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0) @@ -481,7 +464,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_printf ("section name ok\n"); + grub_dprintf ("font", "section name ok\n"); #endif if (section.length != 4) { @@ -492,14 +475,14 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_printf ("section length ok\n"); + grub_dprintf ("font", "section length ok\n"); #endif /* Check the file format type code. */ if (grub_file_read (file, magic, 4) != 4) goto fail; #if FONT_DEBUG >= 3 - grub_printf ("read magic ok\n"); + grub_dprintf ("font", "read magic ok\n"); #endif if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0) @@ -510,7 +493,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_printf ("compare magic ok\n"); + grub_dprintf ("font", "compare magic ok\n"); #endif /* Allocate the font object. */ @@ -522,7 +505,7 @@ grub_font_load (const char *filename) font->file = file; #if FONT_DEBUG >= 3 - grub_printf ("allocate font ok; loading font info\n"); + grub_dprintf ("font", "allocate font ok; loading font info\n"); #endif /* Load the font information. */ @@ -537,7 +520,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 2 - grub_printf ("opened section %c%c%c%c ok\n", + grub_dprintf ("font", "opened section %c%c%c%c ok\n", section.name[0], section.name[1], section.name[2], section.name[3]); #endif @@ -621,7 +604,7 @@ grub_font_load (const char *filename) { /* Unhandled section type, simply skip past it. */ #if FONT_DEBUG >= 3 - grub_printf ("Unhandled section type, skipping.\n"); + grub_dprintf ("font", "Unhandled section type, skipping.\n"); #endif grub_off_t section_end = grub_file_tell (file) + section.length; if ((int) grub_file_seek (file, section_end) == -1) @@ -636,7 +619,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 1 - grub_printf ("Loaded font `%s'.\n" + grub_dprintf ("font", "Loaded font `%s'.\n" "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n", font->name, font->ascent, font->descent, @@ -657,7 +640,7 @@ grub_font_load (const char *filename) if (register_font (font) != 0) goto fail; - return 0; + return font; fail: if (file) @@ -666,7 +649,7 @@ fail: font->file = 0; free_font (font); - return 1; + return 0; } /* Read a 16-bit big-endian integer from FILE, convert it to native byte @@ -909,20 +892,6 @@ grub_font_get_max_char_width (grub_font_t font) return font->max_char_width; } -/* Get the maximum height of any character in the font in pixels. */ -int -grub_font_get_max_char_height (grub_font_t font) -{ - return font->max_char_height; -} - -/* Get the distance in pixels from the top of characters to the baseline. */ -int -grub_font_get_ascent (grub_font_t font) -{ - return font->ascent; -} - /* Get the distance in pixels from the baseline to the lowest descenders (for instance, in a lowercase 'y', 'g', etc.). */ int @@ -1064,6 +1033,7 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) return best_glyph; } +#if 0 static struct grub_font_glyph * grub_font_dup_glyph (struct grub_font_glyph *glyph) { @@ -1075,6 +1045,7 @@ grub_font_dup_glyph (struct grub_font_glyph *glyph) + (glyph->width * glyph->height + 7) / 8); return ret; } +#endif /* FIXME: suboptimal. */ static void @@ -1143,6 +1114,49 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, } } +/* Context for blit_comb. */ +struct blit_comb_ctx +{ + struct grub_font_glyph *glyph; + int *device_width; + struct grub_video_signed_rect bounds; +}; + +/* Helper for blit_comb. */ +static void +do_blit (struct grub_font_glyph *src, signed dx, signed dy, + struct blit_comb_ctx *ctx) +{ + if (ctx->glyph) + grub_font_blit_glyph (ctx->glyph, src, dx - ctx->glyph->offset_x, + (ctx->glyph->height + ctx->glyph->offset_y) + dy); + if (dx < ctx->bounds.x) + { + ctx->bounds.width += ctx->bounds.x - dx; + ctx->bounds.x = dx; + } + if (ctx->bounds.y > -src->height - dy) + { + ctx->bounds.height += ctx->bounds.y - (-src->height - dy); + ctx->bounds.y = (-src->height - dy); + } + if (dx + src->width - ctx->bounds.x >= (signed) ctx->bounds.width) + ctx->bounds.width = dx + src->width - ctx->bounds.x + 1; + if ((signed) ctx->bounds.height < src->height + (-src->height - dy) + - ctx->bounds.y) + ctx->bounds.height = src->height + (-src->height - dy) - ctx->bounds.y; +} + +/* Helper for blit_comb. */ +static inline void +add_device_width (int val, struct blit_comb_ctx *ctx) +{ + if (ctx->glyph) + ctx->glyph->device_width += val; + if (ctx->device_width) + *ctx->device_width += val; +} + static void blit_comb (const struct grub_unicode_glyph *glyph_id, struct grub_font_glyph *glyph, @@ -1150,63 +1164,37 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, struct grub_font_glyph *main_glyph, struct grub_font_glyph **combining_glyphs, int *device_width) { - struct grub_video_signed_rect bounds; + struct blit_comb_ctx ctx = { + .glyph = glyph, + .device_width = device_width + }; unsigned i; signed above_rightx, above_righty; signed above_leftx, above_lefty; signed below_rightx, below_righty; signed min_devwidth = 0; - auto void NESTED_FUNC_ATTR do_blit (struct grub_font_glyph *src, - signed dx, signed dy); - void NESTED_FUNC_ATTR do_blit (struct grub_font_glyph *src, - signed dx, signed dy) - { - if (glyph) - grub_font_blit_glyph (glyph, src, dx - glyph->offset_x, - (glyph->height + glyph->offset_y) + dy); - if (dx < bounds.x) - { - bounds.width += bounds.x - dx; - bounds.x = dx; - } - if (bounds.y > -src->height - dy) - { - bounds.height += bounds.y - (-src->height - dy); - bounds.y = (-src->height - dy); - } - if (dx + src->width - bounds.x >= (signed) bounds.width) - bounds.width = dx + src->width - bounds.x + 1; - if ((signed) bounds.height < src->height + (-src->height - dy) - bounds.y) - bounds.height = src->height + (-src->height - dy) - bounds.y; - } - - auto void add_device_width (int val); - void add_device_width (int val) - { - if (glyph) - glyph->device_width += val; - if (device_width) - *device_width += val; - } + const struct grub_unicode_combining *comb; if (glyph) glyph->device_width = main_glyph->device_width; if (device_width) *device_width = main_glyph->device_width; - bounds.x = main_glyph->offset_x; - bounds.y = main_glyph->offset_y; - bounds.width = main_glyph->width; - bounds.height = main_glyph->height; + ctx.bounds.x = main_glyph->offset_x; + ctx.bounds.y = main_glyph->offset_y; + ctx.bounds.width = main_glyph->width; + ctx.bounds.height = main_glyph->height; above_rightx = main_glyph->offset_x + main_glyph->width; - above_righty = bounds.y + bounds.height; + above_righty = ctx.bounds.y + ctx.bounds.height; above_leftx = main_glyph->offset_x; - above_lefty = bounds.y + bounds.height; + above_lefty = ctx.bounds.y + ctx.bounds.height; - below_rightx = bounds.x + bounds.width; - below_righty = bounds.y; + below_rightx = ctx.bounds.x + ctx.bounds.width; + below_righty = ctx.bounds.y; + + comb = grub_unicode_get_comb (glyph_id); for (i = 0; i < glyph_id->ncomb; i++) { @@ -1216,41 +1204,41 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, if (!combining_glyphs[i]) continue; - targetx = (bounds.width - combining_glyphs[i]->width) / 2 + bounds.x; + targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; /* CGJ is to avoid diacritics reordering. */ - if (glyph_id->combining[i].code + if (comb[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) continue; - switch (glyph_id->combining[i].type) + switch (comb[i].type) { case GRUB_UNICODE_COMB_OVERLAY: do_blit (combining_glyphs[i], targetx, - (bounds.height - combining_glyphs[i]->height) / 2 - - (bounds.height + bounds.y)); + (ctx.bounds.height - combining_glyphs[i]->height) / 2 + - (ctx.bounds.height + ctx.bounds.y), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_ATTACHED_ABOVE_RIGHT: - do_blit (combining_glyphs[i], above_rightx, -above_righty); + do_blit (combining_glyphs[i], above_rightx, -above_righty, &ctx); above_rightx += combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_ABOVE_RIGHT: do_blit (combining_glyphs[i], above_rightx, - -(above_righty + combining_glyphs[i]->height)); + -(above_righty + combining_glyphs[i]->height), &ctx); above_rightx += combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_ABOVE_LEFT: above_leftx -= combining_glyphs[i]->width; do_blit (combining_glyphs[i], above_leftx, - -(above_lefty + combining_glyphs[i]->height)); + -(above_lefty + combining_glyphs[i]->height), &ctx); break; case GRUB_UNICODE_COMB_BELOW_RIGHT: - do_blit (combining_glyphs[i], below_rightx, below_righty); + do_blit (combining_glyphs[i], below_rightx, below_righty, &ctx); below_rightx += combining_glyphs[i]->width; break; @@ -1276,7 +1264,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8; do_blit (combining_glyphs[i], targetx, -(main_glyph->height + main_glyph->offset_y + space - + combining_glyphs[i]->height)); + + combining_glyphs[i]->height), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1300,16 +1288,16 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, case GRUB_UNICODE_STACK_ATTACHED_ABOVE: do_blit (combining_glyphs[i], targetx, - -(bounds.height + bounds.y + space - + combining_glyphs[i]->height)); + -(ctx.bounds.height + ctx.bounds.y + space + + combining_glyphs[i]->height), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_HEBREW_DAGESH: do_blit (combining_glyphs[i], targetx, - -(bounds.height / 2 + bounds.y - + combining_glyphs[i]->height / 2)); + -(ctx.bounds.height / 2 + ctx.bounds.y + + combining_glyphs[i]->height / 2), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1340,13 +1328,14 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8; case GRUB_UNICODE_STACK_ATTACHED_BELOW: - do_blit (combining_glyphs[i], targetx, -(bounds.y - space)); + do_blit (combining_glyphs[i], targetx, -(ctx.bounds.y - space), + &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_MN: - switch (glyph_id->combining[i].code) + switch (comb[i].code) { case GRUB_UNICODE_THAANA_ABAFILI: case GRUB_UNICODE_THAANA_AABAAFILI: @@ -1373,39 +1362,36 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, main_glyph->device_width + combining_glyphs[i]->offset_x, -(combining_glyphs[i]->height - + combining_glyphs[i]->offset_y)); - add_device_width (combining_glyphs[i]->device_width); + + combining_glyphs[i]->offset_y), &ctx); + add_device_width (combining_glyphs[i]->device_width, &ctx); } } } add_device_width ((above_rightx > below_rightx ? above_rightx : below_rightx) - - (main_glyph->offset_x + main_glyph->width)); - add_device_width (above_leftx - main_glyph->offset_x); + (main_glyph->offset_x + main_glyph->width), &ctx); + add_device_width (above_leftx - main_glyph->offset_x, &ctx); if (glyph && glyph->device_width < min_devwidth) glyph->device_width = min_devwidth; if (device_width && *device_width < min_devwidth) *device_width = min_devwidth; if (bounds_out) - *bounds_out = bounds; + *bounds_out = ctx.bounds; } static struct grub_font_glyph * grub_font_construct_dry_run (grub_font_t hinted_font, const struct grub_unicode_glyph *glyph_id, struct grub_video_signed_rect *bounds, - struct grub_font_glyph ***combining_glyphs_out, + struct grub_font_glyph **combining_glyphs, int *device_width) { struct grub_font_glyph *main_glyph = NULL; - struct grub_font_glyph **combining_glyphs; grub_uint32_t desired_attributes = 0; unsigned i; grub_uint32_t base = glyph_id->base; - - if (combining_glyphs_out) - *combining_glyphs_out = NULL; + const struct grub_unicode_combining *comb; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED) desired_attributes |= GRUB_FONT_CODE_RIGHT_JOINED; @@ -1413,11 +1399,12 @@ grub_font_construct_dry_run (grub_font_t hinted_font, if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED) desired_attributes |= GRUB_FONT_CODE_LEFT_JOINED; + comb = grub_unicode_get_comb (glyph_id); if (base == 'i' || base == 'j') { for (i = 0; i < glyph_id->ncomb; i++) - if (glyph_id->combining[i].type == GRUB_UNICODE_STACK_ABOVE) + if (comb[i].type == GRUB_UNICODE_STACK_ABOVE) break; if (i < glyph_id->ncomb && base == 'i') base = GRUB_UNICODE_DOTLESS_LOWERCASE_I; @@ -1446,8 +1433,6 @@ grub_font_construct_dry_run (grub_font_t hinted_font, if (!glyph_id->ncomb && !glyph_id->attributes) return main_glyph; - combining_glyphs = grub_malloc (sizeof (combining_glyphs[0]) - * glyph_id->ncomb); if (glyph_id->ncomb && !combining_glyphs) { grub_errno = GRUB_ERR_NONE; @@ -1457,18 +1442,33 @@ grub_font_construct_dry_run (grub_font_t hinted_font, for (i = 0; i < glyph_id->ncomb; i++) combining_glyphs[i] = grub_font_get_glyph_with_fallback (main_glyph->font, - glyph_id->combining[i].code); + comb[i].code); blit_comb (glyph_id, NULL, bounds, main_glyph, combining_glyphs, device_width); - if (combining_glyphs_out) - *combining_glyphs_out = combining_glyphs; - else - grub_free (combining_glyphs); return main_glyph; } +static struct grub_font_glyph **render_combining_glyphs = 0; +static grub_size_t render_max_comb_glyphs = 0; + +static void +ensure_comb_space (const struct grub_unicode_glyph *glyph_id) +{ + if (glyph_id->ncomb <= render_max_comb_glyphs) + return; + + render_max_comb_glyphs = 2 * glyph_id->ncomb; + if (render_max_comb_glyphs < 8) + render_max_comb_glyphs = 8; + grub_free (render_combining_glyphs); + render_combining_glyphs = grub_malloc (render_max_comb_glyphs + * sizeof (render_combining_glyphs[0])); + if (!render_combining_glyphs) + grub_errno = 0; +} + int grub_font_get_constructed_device_width (grub_font_t hinted_font, const struct grub_unicode_glyph @@ -1476,8 +1476,11 @@ grub_font_get_constructed_device_width (grub_font_t hinted_font, { int ret; struct grub_font_glyph *main_glyph; + + ensure_comb_space (glyph_id); + main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, NULL, - NULL, &ret); + render_combining_glyphs, &ret); if (!main_glyph) return unknown_glyph->device_width; return ret; @@ -1489,26 +1492,42 @@ grub_font_construct_glyph (grub_font_t hinted_font, { struct grub_font_glyph *main_glyph; struct grub_video_signed_rect bounds; - struct grub_font_glyph *glyph; - struct grub_font_glyph **combining_glyphs; + static struct grub_font_glyph *glyph = 0; + static grub_size_t max_glyph_size = 0; + + ensure_comb_space (glyph_id); main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, - &bounds, &combining_glyphs, NULL); + &bounds, render_combining_glyphs, + NULL); if (!main_glyph) - return grub_font_dup_glyph (unknown_glyph); + return unknown_glyph; - if (!combining_glyphs) - return grub_font_dup_glyph (main_glyph); + if (!render_combining_glyphs && glyph_id->ncomb) + return main_glyph; - glyph = - grub_zalloc (sizeof (*glyph) + (bounds.width * bounds.height + 7) / 8); + if (!glyph_id->ncomb && !glyph_id->attributes) + return main_glyph; + + if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) + { + grub_free (glyph); + max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; + if (max_glyph_size < 8) + max_glyph_size = 8; + glyph = grub_malloc (max_glyph_size); + } if (!glyph) { grub_errno = GRUB_ERR_NONE; - return grub_font_dup_glyph (main_glyph); + return main_glyph; } + grub_memset (glyph, 0, sizeof (*glyph) + + (bounds.width * bounds.height + + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); + glyph->font = main_glyph->font; glyph->width = bounds.width; glyph->height = bounds.height; @@ -1527,7 +1546,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); - blit_comb (glyph_id, glyph, NULL, main_glyph, combining_glyphs, NULL); + blit_comb (glyph_id, glyph, NULL, main_glyph, render_combining_glyphs, NULL); return glyph; } diff --git a/grub-core/font/font_cmd.c b/grub-core/font/font_cmd.c index 90f605d2f..f3b36f2d6 100644 --- a/grub-core/font/font_cmd.c +++ b/grub-core/font/font_cmd.c @@ -32,7 +32,7 @@ loadfont_command (grub_command_t cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); while (argc--) - if (grub_font_load (*args++) != 0) + if (grub_font_load (*args++) == 0) { if (!grub_errno) return grub_error (GRUB_ERR_BAD_FONT, "invalid font"); @@ -61,7 +61,7 @@ lsfonts_command (grub_command_t cmd __attribute__ ((unused)), static grub_command_t cmd_loadfont, cmd_lsfonts; -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_COREBOOT) void grub_font_init (void) #else GRUB_MOD_INIT(font) @@ -78,7 +78,7 @@ GRUB_MOD_INIT(font) 0, N_("List the loaded fonts.")); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_COREBOOT) void grub_font_fini (void) #else GRUB_MOD_FINI(font) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index ef654791c..15f7d9dc6 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -97,6 +97,7 @@ enum }; #define AFFS_MAX_LOG_BLOCK_SIZE 4 +#define AFFS_MAX_SUPERBLOCK 1 @@ -184,94 +185,92 @@ grub_affs_mount (grub_disk_t disk) { struct grub_affs_data *data; grub_uint32_t *rootblock = 0; - struct grub_affs_rblock *rblock; + struct grub_affs_rblock *rblock = 0; int log_blocksize = 0; + int bsnum = 0; data = grub_zalloc (sizeof (struct grub_affs_data)); if (!data) return 0; - /* Read the bootblock. */ - grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock), - &data->bblock); - if (grub_errno) - goto fail; - - /* Make sure this is an affs filesystem. */ - if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3)) + for (bsnum = 0; bsnum < AFFS_MAX_SUPERBLOCK + 1; bsnum++) { - grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem"); - goto fail; - } - - /* Test if the filesystem is a OFS filesystem. */ - if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS)) - { - grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported"); - goto fail; - } - - /* No sane person uses more than 8KB for a block. At least I hope - for that person because in that case this won't work. */ - rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << AFFS_MAX_LOG_BLOCK_SIZE); - if (!rootblock) - goto fail; - - rblock = (struct grub_affs_rblock *) rootblock; - - /* The filesystem blocksize is not stored anywhere in the filesystem - itself. One way to determine it is try reading blocks for the - rootblock until the checksum is correct. */ - for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE; - log_blocksize++) - { - grub_uint32_t *currblock = rootblock; - unsigned int i; - grub_uint32_t checksum = 0; - - /* Read the rootblock. */ - grub_disk_read (disk, - (grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock) - << log_blocksize, 0, - GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock); + /* Read the bootblock. */ + grub_disk_read (disk, bsnum, 0, sizeof (struct grub_affs_bblock), + &data->bblock); if (grub_errno) goto fail; - if (rblock->type != grub_cpu_to_be32_compile_time (2) - || rblock->htsize == 0 - || currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize) - / sizeof (*currblock) - 1] - != grub_cpu_to_be32_compile_time (1)) + /* Make sure this is an affs filesystem. */ + if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3) != 0 + /* Test if the filesystem is a OFS filesystem. */ + || !(data->bblock.flags & GRUB_AFFS_FLAG_FFS)) continue; - for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize) - / sizeof (*currblock); - i++) - checksum += grub_be_to_cpu32 (currblock[i]); + /* No sane person uses more than 8KB for a block. At least I hope + for that person because in that case this won't work. */ + if (!rootblock) + rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE + << AFFS_MAX_LOG_BLOCK_SIZE); + if (!rootblock) + goto fail; - if (checksum == 0) - break; + rblock = (struct grub_affs_rblock *) rootblock; + + /* The filesystem blocksize is not stored anywhere in the filesystem + itself. One way to determine it is try reading blocks for the + rootblock until the checksum is correct. */ + for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE; + log_blocksize++) + { + grub_uint32_t *currblock = rootblock; + unsigned int i; + grub_uint32_t checksum = 0; + + /* Read the rootblock. */ + grub_disk_read (disk, + (grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock) + << log_blocksize, 0, + GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + { + grub_errno = 0; + break; + } + if (grub_errno) + goto fail; + + if (rblock->type != grub_cpu_to_be32_compile_time (2) + || rblock->htsize == 0 + || currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize) + / sizeof (*currblock) - 1] + != grub_cpu_to_be32_compile_time (1)) + continue; + + for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize) + / sizeof (*currblock); + i++) + checksum += grub_be_to_cpu32 (currblock[i]); + + if (checksum == 0) + { + data->log_blocksize = log_blocksize; + data->disk = disk; + data->htsize = grub_be_to_cpu32 (rblock->htsize); + data->diropen.data = data; + data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); + data->diropen.parent = NULL; + grub_memcpy (&data->diropen.di, rootblock, + sizeof (data->diropen.di)); + grub_free (rootblock); + + return data; + } + } } - if (log_blocksize > AFFS_MAX_LOG_BLOCK_SIZE) - { - grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined"); - goto fail; - } - - data->log_blocksize = log_blocksize; - data->disk = disk; - data->htsize = grub_be_to_cpu32 (rblock->htsize); - data->diropen.data = data; - data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); - data->diropen.parent = NULL; - grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di)); - - grub_free (rootblock); - - return data; fail: - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + if (grub_errno == GRUB_ERR_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem"); grub_free (data); @@ -317,12 +316,87 @@ grub_affs_read_symlink (grub_fshelp_node_t node) } +/* Helper for grub_affs_iterate_dir. */ +static int +grub_affs_create_node (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data, + struct grub_fshelp_node **node, + grub_uint32_t **hashtable, + grub_uint32_t block, const struct grub_affs_file *fil) +{ + struct grub_affs_data *data = dir->data; + int type = GRUB_FSHELP_REG; + grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1]; + grub_size_t len; + unsigned int nest; + + *node = grub_zalloc (sizeof (**node)); + if (!*node) + { + grub_free (*hashtable); + return 1; + } + + (*node)->data = data; + (*node)->block = block; + (*node)->parent = dir; + + len = fil->namelen; + if (len > sizeof (fil->name)) + len = sizeof (fil->name); + *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; + + (*node)->di = *fil; + for (nest = 0; nest < 8; nest++) + { + switch ((*node)->di.type) + { + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG): + type = GRUB_FSHELP_REG; + break; + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR): + type = GRUB_FSHELP_DIR; + break; + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK): + type = GRUB_FSHELP_SYMLINK; + break; + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK): + { + grub_err_t err; + (*node)->block = grub_be_to_cpu32 ((*node)->di.hardlink); + err = grub_disk_read (data->disk, + (((grub_uint64_t) (*node)->block + 1) << data->log_blocksize) + - 1, + GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION, + sizeof ((*node)->di), (char *) &(*node)->di); + if (err) + return 1; + continue; + } + default: + return 0; + } + break; + } + + if (nest == 8) + return 0; + + type |= GRUB_FSHELP_CASE_INSENSITIVE; + + if (hook ((char *) name_u8, type, *node, hook_data)) + { + grub_free (*hashtable); + *node = 0; + return 1; + } + *node = 0; + return 0; +} + static int grub_affs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { unsigned int i; struct grub_affs_file file; @@ -330,88 +404,13 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, struct grub_affs_data *data = dir->data; grub_uint32_t *hashtable; - auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, - const struct grub_affs_file *fil); - - int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, - const struct grub_affs_file *fil) - { - int type; - grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1]; - grub_size_t len; - unsigned int nest; - - node = grub_zalloc (sizeof (*node)); - if (!node) - { - grub_free (hashtable); - return 1; - } - - node->data = data; - node->block = block; - node->parent = dir; - - len = fil->namelen; - if (len > sizeof (fil->name)) - len = sizeof (fil->name); - *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; - - node->di = *fil; - for (nest = 0; nest < 8; nest++) - { - switch (node->di.type) - { - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG): - type = GRUB_FSHELP_REG; - break; - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR): - type = GRUB_FSHELP_DIR; - break; - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK): - type = GRUB_FSHELP_SYMLINK; - break; - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK): - { - grub_err_t err; - node->block = grub_be_to_cpu32 (node->di.hardlink); - err = grub_disk_read (data->disk, - (((grub_uint64_t) node->block + 1) << data->log_blocksize) - - 1, - GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION, - sizeof (node->di), (char *) &node->di); - if (err) - return 1; - continue; - } - default: - return 0; - } - break; - } - - if (nest == 8) - return 0; - - type |= GRUB_FSHELP_CASE_INSENSITIVE; - - if (hook ((char *) name_u8, type, node)) - { - grub_free (hashtable); - node = 0; - return 1; - } - node = 0; - return 0; - } - /* Create the directory entries for `.' and `..'. */ node = grub_zalloc (sizeof (*node)); if (!node) return 1; *node = *dir; - if (hook (".", GRUB_FSHELP_DIR, node)) + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) return 1; if (dir->parent) { @@ -419,7 +418,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (!node) return 1; *node = *dir->parent; - if (hook ("..", GRUB_FSHELP_DIR, node)) + if (hook ("..", GRUB_FSHELP_DIR, node, hook_data)) return 1; } @@ -455,7 +454,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - if (grub_affs_create_node (next, &file)) + if (grub_affs_create_node (dir, hook, hook_data, &node, &hashtable, + next, &file)) return 1; next = grub_be_to_cpu32 (file.next); @@ -531,7 +531,7 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len) (struct grub_affs_data *) file->data; return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen, - file->read_hook, + file->read_hook, file->read_hook_data, file->offset, len, buf, grub_affs_read_block, grub_be_to_cpu32 (data->diropen.di.size), data->log_blocksize, 0); @@ -546,31 +546,37 @@ aftime2ctime (const struct grub_affs_time *t) + 8 * 365 * 86400 + 86400 * 2; } +/* Context for grub_affs_dir. */ +struct grub_affs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_affs_dir. */ +static int +grub_affs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_affs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = aftime2ctime (&node->di.mtime); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_affs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_affs_dir_ctx ctx = { hook, hook_data }; struct grub_affs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = aftime2ctime (&node->di.mtime); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_affs_mount (device->disk); @@ -582,7 +588,7 @@ grub_affs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_affs_iterate_dir (fdiro, iterate); + grub_affs_iterate_dir (fdiro, grub_affs_dir_iter, &ctx); fail: if (data && fdiro != &data->diropen) diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c new file mode 100644 index 000000000..c85cbfac2 --- /dev/null +++ b/grub-core/fs/archelp.c @@ -0,0 +1,300 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static inline void +canonicalize (char *name) +{ + char *iptr, *optr; + for (iptr = name, optr = name; *iptr; ) + { + while (*iptr == '/') + iptr++; + if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) + { + iptr += 2; + continue; + } + if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0)) + { + iptr += 3; + if (optr == name) + continue; + for (optr -= 2; optr >= name && *optr != '/'; optr--); + optr++; + continue; + } + while (*iptr && *iptr != '/') + *optr++ = *iptr++; + if (*iptr) + *optr++ = *iptr++; + } + *optr = 0; +} + +static grub_err_t +handle_symlink (struct grub_archelp_data *data, + struct grub_archelp_ops *arcops, + const char *fn, char **name, + grub_uint32_t mode, int *restart) +{ + grub_size_t flen; + char *target; + char *ptr; + char *lastslash; + grub_size_t prefixlen; + char *rest; + char *linktarget; + grub_size_t linktarget_len; + + *restart = 0; + + if ((mode & GRUB_ARCHELP_ATTR_TYPE) != GRUB_ARCHELP_ATTR_LNK + || !arcops->get_link_target) + return GRUB_ERR_NONE; + flen = grub_strlen (fn); + if (grub_memcmp (*name, fn, flen) != 0 + || ((*name)[flen] != 0 && (*name)[flen] != '/')) + return GRUB_ERR_NONE; + rest = *name + flen; + lastslash = rest; + if (*rest) + rest++; + while (lastslash >= *name && *lastslash != '/') + lastslash--; + if (lastslash >= *name) + prefixlen = lastslash - *name; + else + prefixlen = 0; + + if (prefixlen) + prefixlen++; + + linktarget = arcops->get_link_target (data); + if (!linktarget) + return grub_errno; + if (linktarget[0] == '\0') + return GRUB_ERR_NONE; + linktarget_len = grub_strlen (linktarget); + target = grub_malloc (linktarget_len + grub_strlen (*name) + 2); + if (!target) + return grub_errno; + + grub_strcpy (target + prefixlen, linktarget); + grub_free (linktarget); + if (target[prefixlen] == '/') + { + ptr = grub_stpcpy (target, target + prefixlen); + ptr = grub_stpcpy (ptr, rest); + *ptr = 0; + grub_dprintf ("archelp", "symlink redirected %s to %s\n", + *name, target); + grub_free (*name); + + canonicalize (target); + *name = target; + *restart = 1; + return GRUB_ERR_NONE; + } + if (prefixlen) + { + grub_memcpy (target, *name, prefixlen); + target[prefixlen-1] = '/'; + } + grub_strcpy (target + prefixlen + linktarget_len, rest); + grub_dprintf ("archelp", "symlink redirected %s to %s\n", + *name, target); + grub_free (*name); + canonicalize (target); + *name = target; + *restart = 1; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_archelp_dir (struct grub_archelp_data *data, + struct grub_archelp_ops *arcops, + const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + char *prev, *name, *path, *ptr; + grub_size_t len; + int symlinknest = 0; + + path = grub_strdup (path_in + 1); + if (!path) + return grub_errno; + canonicalize (path); + for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) + *ptr = 0; + + prev = 0; + + len = grub_strlen (path); + while (1) + { + grub_int32_t mtime; + grub_uint32_t mode; + grub_err_t err; + + if (arcops->find_file (data, &name, &mtime, &mode)) + goto fail; + + if (mode == GRUB_ARCHELP_ATTR_END) + break; + + canonicalize (name); + + if (grub_memcmp (path, name, len) == 0 + && (name[len] == 0 || name[len] == '/' || len == 0)) + { + char *p, *n; + + n = name + len; + while (*n == '/') + n++; + + p = grub_strchr (n, '/'); + if (p) + *p = 0; + + if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0) + { + struct grub_dirhook_info info; + grub_memset (&info, 0, sizeof (info)); + info.dir = (p != NULL) || ((mode & GRUB_ARCHELP_ATTR_TYPE) + == GRUB_ARCHELP_ATTR_DIR); + if (!(mode & GRUB_ARCHELP_ATTR_NOTIME)) + { + info.mtime = mtime; + info.mtimeset = 1; + } + if (hook (n, &info, hook_data)) + { + grub_free (name); + goto fail; + } + grub_free (prev); + prev = name; + } + else + { + int restart = 0; + err = handle_symlink (data, arcops, name, + &path, mode, &restart); + grub_free (name); + if (err) + goto fail; + if (restart) + { + len = grub_strlen (path); + if (++symlinknest == 8) + { + grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); + goto fail; + } + arcops->rewind (data); + } + } + } + else + grub_free (name); + } + +fail: + + grub_free (path); + grub_free (prev); + + return grub_errno; +} + +grub_err_t +grub_archelp_open (struct grub_archelp_data *data, + struct grub_archelp_ops *arcops, + const char *name_in) +{ + char *fn; + char *name = grub_strdup (name_in + 1); + int symlinknest = 0; + + if (!name) + return grub_errno; + + canonicalize (name); + + while (1) + { + grub_uint32_t mode; + int restart; + + if (arcops->find_file (data, &fn, NULL, &mode)) + goto fail; + + if (mode == GRUB_ARCHELP_ATTR_END) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in); + break; + } + + canonicalize (fn); + + if (handle_symlink (data, arcops, fn, &name, mode, &restart)) + { + grub_free (fn); + goto fail; + } + + if (restart) + { + arcops->rewind (data); + if (++symlinknest == 8) + { + grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); + goto fail; + } + goto no_match; + } + + if (grub_strcmp (name, fn) != 0) + goto no_match; + + grub_free (fn); + grub_free (name); + + return GRUB_ERR_NONE; + + no_match: + + grub_free (fn); + } + +fail: + grub_free (name); + + return grub_errno; +} diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 318dc3eec..36b01efc8 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -170,7 +170,16 @@ struct grub_bfs_btree_node struct grub_bfs_data { struct grub_bfs_superblock sb; - struct grub_bfs_inode ino[0]; + struct grub_bfs_inode ino; +}; + +/* Context for grub_bfs_dir. */ +struct grub_bfs_dir_ctx +{ + grub_device_t device; + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_bfs_superblock sb; }; static grub_err_t @@ -208,9 +217,7 @@ read_bfs_file (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, grub_off_t off, void *buf, grub_size_t len, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { if (len == 0) return GRUB_ERR_NONE; @@ -236,6 +243,7 @@ read_bfs_file (grub_disk_t disk, if (read_size > len) read_size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; err = read_extent (disk, sb, &ino->direct[i], 0, off - pos, buf, read_size); disk->read_hook = 0; @@ -281,6 +289,7 @@ read_bfs_file (grub_disk_t disk, if (read_size > len) read_size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; err = read_extent (disk, sb, &entries[i], 0, off - pos, buf, read_size); disk->read_hook = 0; @@ -392,6 +401,7 @@ read_bfs_file (grub_disk_t disk, if (read_size > len) read_size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; err = read_extent (disk, sb, &l2_entries[l2n], 0, boff, buf, read_size); disk->read_hook = 0; @@ -409,18 +419,77 @@ read_bfs_file (grub_disk_t disk, } } +static grub_err_t +read_b_node (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_inode *ino, + grub_uint64_t node_off, + struct grub_bfs_btree_node **node, + char **key_data, grub_uint16_t **keylen_idx, + grub_unaligned_uint64_t **key_values) +{ + void *ret; + struct grub_bfs_btree_node node_head; + grub_size_t total_size; + grub_err_t err; + + *node = NULL; + *key_data = NULL; + *keylen_idx = NULL; + *key_values = NULL; + + err = read_bfs_file (disk, sb, ino, node_off, &node_head, sizeof (node_head), + 0, 0); + if (err) + return err; + + total_size = ALIGN_UP (sizeof (node_head) + + grub_bfs_to_cpu_treehead + (node_head.total_key_len), + BTREE_ALIGN) + + grub_bfs_to_cpu_treehead (node_head.count_keys) * + sizeof (grub_uint16_t) + + grub_bfs_to_cpu_treehead (node_head.count_keys) * + sizeof (grub_uint64_t); + + ret = grub_malloc (total_size); + if (!ret) + return grub_errno; + + err = read_bfs_file (disk, sb, ino, node_off, ret, total_size, 0, 0); + if (err) + { + grub_free (ret); + return err; + } + + *node = ret; + *key_data = (char *) ret + sizeof (node_head); + *keylen_idx = (grub_uint16_t *) ret + + ALIGN_UP (sizeof (node_head) + + grub_bfs_to_cpu_treehead (node_head.total_key_len), + BTREE_ALIGN) / 2; + *key_values = (grub_unaligned_uint64_t *) + (*keylen_idx + + grub_bfs_to_cpu_treehead (node_head.count_keys)); + + return GRUB_ERR_NONE; +} + static int iterate_in_b_tree (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, - int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t value)) + int (*hook) (const char *name, grub_uint64_t value, + struct grub_bfs_dir_ctx *ctx), + struct grub_bfs_dir_ctx *ctx) { struct grub_bfs_btree_header head; grub_err_t err; int level; grub_uint64_t node_off; - err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0); if (err) return 0; node_off = grub_bfs_to_cpu64 (head.root); @@ -430,7 +499,8 @@ iterate_in_b_tree (grub_disk_t disk, { struct grub_bfs_btree_node node; grub_uint64_t key_value; - err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), + 0, 0); if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off @@ -440,7 +510,7 @@ iterate_in_b_tree (grub_disk_t disk, BTREE_ALIGN) + grub_bfs_to_cpu_treehead (node.count_keys) * sizeof (grub_uint16_t), &key_value, - sizeof (grub_uint64_t), 0); + sizeof (grub_uint64_t), 0, 0); if (err) return 0; @@ -449,68 +519,52 @@ iterate_in_b_tree (grub_disk_t disk, while (1) { - struct grub_bfs_btree_node node; - err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + struct grub_bfs_btree_node *node; + char *key_data; + grub_uint16_t *keylen_idx; + grub_unaligned_uint64_t *key_values; + unsigned i; + grub_uint16_t start = 0, end = 0; + + err = read_b_node (disk, sb, ino, + node_off, + &node, + &key_data, + &keylen_idx, + &key_values); + if (err) return 0; - { - char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; - grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; - grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; - unsigned i; - grub_uint16_t start = 0, end = 0; - - err = - read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu_treehead (node.total_key_len), 0); - if (err) - return 0; - key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead - (node.total_key_len), BTREE_ALIGN), - keylen_idx, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), 0); - if (err) - return 0; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead - (node.total_key_len), - BTREE_ALIGN) + - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), key_values, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint64_t), 0); - if (err) - return 0; - - for (i = 0; i < grub_bfs_to_cpu_treehead (node.count_keys); i++) - { - char c; - start = end; - end = grub_bfs_to_cpu16 (keylen_idx[i]); - if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) - end = grub_bfs_to_cpu_treehead (node.total_key_len); - c = key_data[end]; - key_data[end] = 0; - if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]))) + + for (i = 0; i < grub_bfs_to_cpu_treehead (node->count_keys); i++) + { + char c; + start = end; + end = grub_bfs_to_cpu16 (keylen_idx[i]); + if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node->total_key_len); + c = key_data[end]; + key_data[end] = 0; + if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i].val), + ctx)) + { + grub_free (node); return 1; + } key_data[end] = c; } - node_off = grub_bfs_to_cpu64 (node.right); + node_off = grub_bfs_to_cpu64 (node->right); + grub_free (node); if (node_off == POINTER_INVALID) return 0; - } } } static int -bfs_strcmp (const char *a, const char *b, grub_size_t alen) +bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen) { - while (*b && alen) + char ac, bc; + while (blen && alen) { if (*a != *b) break; @@ -518,18 +572,16 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen) a++; b++; alen--; + blen--; } + ac = alen ? *a : 0; + bc = blen ? *b : 0; + #ifdef MODE_AFS - if (!alen) - return - (int) (grub_int8_t) *b; - - return (int) (grub_int8_t) *a - (int) (grub_int8_t) *b; + return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc; #else - if (!alen) - return - (int) (grub_uint8_t) *b; - - return (int) (grub_uint8_t) *a - (int) (grub_uint8_t) *b; + return (int) (grub_uint8_t) ac - (int) (grub_uint8_t) bc; #endif } @@ -537,6 +589,7 @@ static grub_err_t find_in_b_tree (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, const char *name, + grub_size_t name_len, grub_uint64_t * res) { struct grub_bfs_btree_header head; @@ -544,7 +597,7 @@ find_in_b_tree (grub_disk_t disk, int level; grub_uint64_t node_off; - err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0); if (err) return err; node_off = grub_bfs_to_cpu64 (head.root); @@ -552,130 +605,113 @@ find_in_b_tree (grub_disk_t disk, level = grub_bfs_to_cpu32 (head.level) - 1; while (1) { - struct grub_bfs_btree_node node; - err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + struct grub_bfs_btree_node *node; + char *key_data; + grub_uint16_t *keylen_idx; + grub_unaligned_uint64_t *key_values; + int lg, j; + unsigned i; + + err = read_b_node (disk, sb, ino, node_off, &node, &key_data, &keylen_idx, &key_values); if (err) return err; - if (node.count_keys == 0) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), - name); - { - char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; - grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; - grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; - unsigned i; - err = - read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu_treehead (node.total_key_len), 0); - if (err) - return err; - key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; - err = read_bfs_file (disk, sb, ino, node_off - + - ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead (node. - total_key_len), - BTREE_ALIGN), keylen_idx, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), 0); - if (err) - return err; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead - (node.total_key_len), - BTREE_ALIGN) + - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), key_values, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint64_t), 0); - if (err) - return err; - int lg, j; + if (node->count_keys == 0) + { + grub_free (node); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), + name); + } - for (lg = 0; grub_bfs_to_cpu_treehead (node.count_keys) >> lg; lg++); + for (lg = 0; grub_bfs_to_cpu_treehead (node->count_keys) >> lg; lg++); - i = 0; + i = 0; - for (j = lg - 1; j >= 0; j--) - { - int cmp; - grub_uint16_t start = 0, end = 0; - if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node.count_keys)) - continue; - start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); - end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); - if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) - end = grub_bfs_to_cpu_treehead (node.total_key_len); - cmp = bfs_strcmp (key_data + start, name, end - start); - if (cmp == 0 && level == 0) - { - *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)]); - return GRUB_ERR_NONE; - } + for (j = lg - 1; j >= 0; j--) + { + int cmp; + grub_uint16_t start = 0, end = 0; + if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node->count_keys)) + continue; + start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); + end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); + if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node->total_key_len); + cmp = bfs_strcmp (key_data + start, name, end - start, name_len); + if (cmp == 0 && level == 0) + { + *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val); + grub_free (node); + return GRUB_ERR_NONE; + } #ifdef MODE_AFS - if (cmp <= 0) + if (cmp <= 0) #else - if (cmp < 0) + if (cmp < 0) #endif - i |= (1 << j); - } - if (i == 0) - { - grub_uint16_t end = 0; - int cmp; - end = grub_bfs_to_cpu16 (keylen_idx[0]); - if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) - end = grub_bfs_to_cpu_treehead (node.total_key_len); - cmp = bfs_strcmp (key_data, name, end); - if (cmp == 0 && level == 0) - { - *res = grub_bfs_to_cpu64 (key_values[0]); - return GRUB_ERR_NONE; - } + i |= (1 << j); + } + if (i == 0) + { + grub_uint16_t end = 0; + int cmp; + end = grub_bfs_to_cpu16 (keylen_idx[0]); + if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node->total_key_len); + cmp = bfs_strcmp (key_data, name, end, name_len); + if (cmp == 0 && level == 0) + { + *res = grub_bfs_to_cpu64 (key_values[0].val); + grub_free (node); + return GRUB_ERR_NONE; + } #ifdef MODE_AFS - if (cmp > 0 && level != 0) + if (cmp > 0 && level != 0) #else if (cmp >= 0 && level != 0) #endif { - node_off = grub_bfs_to_cpu64 (key_values[0]); + node_off = grub_bfs_to_cpu64 (key_values[0].val); level--; + grub_free (node); continue; } else if (level != 0 - && grub_bfs_to_cpu_treehead (node.count_keys) >= 2) + && grub_bfs_to_cpu_treehead (node->count_keys) >= 2) { - node_off = grub_bfs_to_cpu64 (key_values[1]); + node_off = grub_bfs_to_cpu64 (key_values[1].val); level--; + grub_free (node); continue; } } else if (level != 0 - && i + 1 < grub_bfs_to_cpu_treehead (node.count_keys)) + && i + 1 < grub_bfs_to_cpu_treehead (node->count_keys)) { - node_off = grub_bfs_to_cpu64 (key_values[i + 1]); + node_off = grub_bfs_to_cpu64 (key_values[i + 1].val); level--; + grub_free (node); continue; } - if (node.overflow != POINTER_INVALID) + if (node->overflow != POINTER_INVALID) { - node_off = grub_bfs_to_cpu64 (node.overflow); + node_off = grub_bfs_to_cpu64 (node->overflow); /* This level-- isn't specified but is needed. */ level--; + grub_free (node); continue; } + grub_free (node); return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name); - } } } static grub_err_t hop_level (grub_disk_t disk, const struct grub_bfs_superblock *sb, - struct grub_bfs_inode *ino, const char *name) + struct grub_bfs_inode *ino, const char *name, + const char *name_end) { grub_err_t err; grub_uint64_t res = 0; @@ -683,38 +719,35 @@ hop_level (grub_disk_t disk, if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - err = find_in_b_tree (disk, sb, ino, name, &res); + err = find_in_b_tree (disk, sb, ino, name, name_end - name, &res); if (err) return err; return grub_disk_read (disk, res << (grub_bfs_to_cpu32 (sb->log2_bsize) - GRUB_DISK_SECTOR_BITS), 0, - grub_bfs_to_cpu32 (sb->bsize), (char *) ino); + sizeof (*ino), (char *) ino); } static grub_err_t find_file (const char *path, grub_disk_t disk, const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) { - char *ptr, *ptr2; + const char *ptr, *next = path; char *alloc = NULL; + char *wptr; grub_err_t err; - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; - } old_ino; + struct grub_bfs_inode old_ino; unsigned symlinks_max = 32; err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - grub_bfs_to_cpu32 (sb->bsize)); + sizeof (*ino)); if (err) return err; - ptr = (char *) path; while (1) { + ptr = next; while (*ptr == '/') ptr++; if (*ptr == 0) @@ -722,17 +755,9 @@ find_file (const char *path, grub_disk_t disk, grub_free (alloc); return GRUB_ERR_NONE; } - ptr2 = grub_strchr (ptr, '/'); - grub_memcpy (&old_ino, ino, grub_bfs_to_cpu32 (sb->bsize)); - if (ptr2) - { - char component[ptr2 - ptr + 1]; - grub_memcpy (component, ptr, ptr2 - ptr); - component[ptr2 - ptr] = 0; - err = hop_level (disk, sb, ino, component); - } - else - err = hop_level (disk, sb, ino, ptr); + for (next = ptr; *next && *next != '/'; next++); + grub_memcpy (&old_ino, ino, sizeof (old_ino)); + err = hop_level (disk, sb, ino, ptr, next); if (err) return err; @@ -751,7 +776,7 @@ find_file (const char *path, grub_disk_t disk, #endif { grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); - alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) + alloc = grub_malloc (grub_strlen (next) + symsize + 1); if (!alloc) { @@ -759,7 +784,7 @@ find_file (const char *path, grub_disk_t disk, return grub_errno; } grub_free (old_alloc); - err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0); + err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0, 0); if (err) { grub_free (alloc); @@ -770,7 +795,7 @@ find_file (const char *path, grub_disk_t disk, #ifndef MODE_AFS else { - alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) + alloc = grub_malloc (grub_strlen (next) + sizeof (ino->inplace_link) + 1); if (!alloc) { @@ -786,7 +811,7 @@ find_file (const char *path, grub_disk_t disk, if (alloc[0] == '/') { err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - grub_bfs_to_cpu32 (sb->bsize)); + sizeof (*ino)); if (err) { grub_free (alloc); @@ -794,21 +819,14 @@ find_file (const char *path, grub_disk_t disk, } } else - grub_memcpy (ino, &old_ino, grub_bfs_to_cpu32 (sb->bsize)); - ptr = alloc + grub_strlen (alloc); - if (ptr2) - ptr = grub_stpcpy (ptr, ptr2); - *ptr = 0; - ptr = ptr2 = alloc; + grub_memcpy (ino, &old_ino, sizeof (old_ino)); + wptr = alloc + grub_strlen (alloc); + if (next) + wptr = grub_stpcpy (wptr, next); + *wptr = 0; + next = alloc; continue; } - - if (!ptr2) - { - grub_free (alloc); - return GRUB_ERR_NONE; - } - ptr = ptr2 + 1; } } @@ -844,61 +862,60 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) return GRUB_ERR_NONE; } +/* Helper for grub_bfs_dir. */ +static int +grub_bfs_dir_iter (const char *name, grub_uint64_t value, + struct grub_bfs_dir_ctx *ctx) +{ + grub_err_t err2; + struct grub_bfs_inode ino; + struct grub_dirhook_info info; + + err2 = grub_disk_read (ctx->device->disk, value + << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, + sizeof (ino), (char *) &ino); + if (err2) + { + grub_print_error (); + return 0; + } + + info.mtimeset = 1; +#ifdef MODE_AFS + info.mtime = + grub_divmod64 (grub_bfs_to_cpu64 (ino.mtime), 1000000, 0); +#else + info.mtime = grub_bfs_to_cpu64 (ino.mtime) >> 16; +#endif + info.dir = ((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) == ATTR_DIR); + return ctx->hook (name, &info, ctx->hook_data); +} + static grub_err_t grub_bfs_dir (grub_device_t device, const char *path, - int (*hook_in) (const char *filename, - const struct grub_dirhook_info * info)) + grub_fs_dir_hook_t hook, void *hook_data) { - struct grub_bfs_superblock sb; + struct grub_bfs_dir_ctx ctx = { + .device = device, + .hook = hook, + .hook_data = hook_data + }; grub_err_t err; - auto int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value); - int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value) - { - grub_err_t err2; - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; - struct grub_dirhook_info info; - - err2 = grub_disk_read (device->disk, value - << (grub_bfs_to_cpu32 (sb.log2_bsize) - - GRUB_DISK_SECTOR_BITS), 0, - grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw); - if (err2) - { - grub_print_error (); - return 0; - } - - info.mtimeset = 1; -#ifdef MODE_AFS - info.mtime = - grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0); -#else - info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; -#endif - info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); - return hook_in (name, &info); - } - err = mount (device->disk, &sb); + err = mount (device->disk, &ctx.sb); if (err) return err; { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; - err = find_file (path, device->disk, &sb, &ino.ino); + struct grub_bfs_inode ino; + err = find_file (path, device->disk, &ctx.sb, &ino); if (err) return err; - if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) + if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_DIR)) return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - iterate_in_b_tree (device->disk, &sb, &ino.ino, hook); + iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter, + &ctx); } return grub_errno; @@ -915,26 +932,21 @@ grub_bfs_open (struct grub_file *file, const char *name) return err; { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; + struct grub_bfs_inode ino; struct grub_bfs_data *data; - err = find_file (name, file->device->disk, &sb, &ino.ino); + err = find_file (name, file->device->disk, &sb, &ino); if (err) return err; - if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) + if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_REG)) return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - data = grub_zalloc (sizeof (struct grub_bfs_data) - + grub_bfs_to_cpu32 (sb.bsize)); + data = grub_zalloc (sizeof (struct grub_bfs_data)); if (!data) return grub_errno; data->sb = sb; - grub_memcpy (&data->ino, &ino, grub_bfs_to_cpu32 (sb.bsize)); + grub_memcpy (&data->ino, &ino, sizeof (data->ino)); file->data = data; - file->size = grub_bfs_to_cpu64 (ino.ino.size); + file->size = grub_bfs_to_cpu64 (ino.size); } return GRUB_ERR_NONE; @@ -955,7 +967,8 @@ grub_bfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_bfs_data *data = file->data; err = read_bfs_file (file->device->disk, &data->sb, - data->ino, file->offset, buf, len, file->read_hook); + &data->ino, file->offset, buf, len, + file->read_hook, file->read_hook_data); if (err) return -1; return len; @@ -981,7 +994,7 @@ grub_bfs_label (grub_device_t device, char **label) static grub_ssize_t read_bfs_attr (grub_disk_t disk, const struct grub_bfs_superblock *sb, - const struct grub_bfs_inode *ino, + struct grub_bfs_inode *ino, const char *name, void *buf, grub_size_t len) { grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; @@ -1012,32 +1025,27 @@ read_bfs_attr (grub_disk_t disk, if (ino->attr.len != 0) { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; - } ino2; grub_size_t read; grub_err_t err; grub_uint64_t res; - err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, + err = read_extent (disk, sb, &ino->attr, 0, 0, ino, grub_bfs_to_cpu32 (sb->bsize)); if (err) return -1; - err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); + err = find_in_b_tree (disk, sb, ino, name, grub_strlen (name), &res); if (err) return -1; grub_disk_read (disk, res << (grub_bfs_to_cpu32 (sb->log2_bsize) - GRUB_DISK_SECTOR_BITS), 0, - grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); - read = grub_bfs_to_cpu64 (ino2.ino.size); + grub_bfs_to_cpu32 (sb->bsize), (char *) ino); + read = grub_bfs_to_cpu64 (ino->size); if (read > len) read = len; - err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0); + err = read_bfs_file (disk, sb, ino, 0, buf, read, 0, 0); if (err) return -1; return read; @@ -1050,6 +1058,8 @@ grub_bfs_uuid (grub_device_t device, char **uuid) { struct grub_bfs_superblock sb; grub_err_t err; + struct grub_bfs_inode *ino; + grub_uint64_t vid; *uuid = 0; @@ -1057,23 +1067,24 @@ grub_bfs_uuid (grub_device_t device, char **uuid) if (err) return err; - { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; - grub_uint64_t vid; + ino = grub_malloc (grub_bfs_to_cpu32 (sb.bsize)); + if (!ino) + return grub_errno; - err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, - &ino, grub_bfs_to_cpu32 (sb.bsize)); - if (err) + err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, + ino, grub_bfs_to_cpu32 (sb.bsize)); + if (err) + { + grub_free (ino); return err; - if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", - &vid, sizeof (vid)) == sizeof (vid)) - *uuid = - grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); - } + } + if (read_bfs_attr (device->disk, &sb, ino, "be:volume_id", + &vid, sizeof (vid)) == sizeof (vid)) + *uuid = + grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); + + grub_free (ino); + return GRUB_ERR_NONE; } #endif diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index a993f0747..49f11cc3c 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1,7 +1,7 @@ /* btrfs.c - B-tree file system. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -106,24 +107,6 @@ struct grub_btrfs_data struct grub_btrfs_extent_data *extent; }; -enum - { - GRUB_BTRFS_ITEM_TYPE_INODE_ITEM = 0x01, - GRUB_BTRFS_ITEM_TYPE_INODE_REF = 0x0c, - GRUB_BTRFS_ITEM_TYPE_DIR_ITEM = 0x54, - GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM = 0x6c, - GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84, - GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8, - GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4 - }; - -struct grub_btrfs_key -{ - grub_uint64_t object_id; - grub_uint8_t type; - grub_uint64_t offset; -} __attribute__ ((packed)); - struct grub_btrfs_chunk_item { grub_uint64_t size; @@ -188,13 +171,6 @@ struct grub_btrfs_leaf_descriptor } *data; }; -struct grub_btrfs_root_item -{ - grub_uint8_t dummy[0xb0]; - grub_uint64_t tree; - grub_uint64_t inode; -}; - struct grub_btrfs_time { grub_int64_t sec; @@ -538,56 +514,71 @@ lower_bound (struct grub_btrfs_data *data, } } +/* Context for find_device. */ +struct find_device_ctx +{ + struct grub_btrfs_data *data; + grub_uint64_t id; + grub_device_t dev_found; +}; + +/* Helper for find_device. */ +static int +find_device_iter (const char *name, void *data) +{ + struct find_device_ctx *ctx = data; + grub_device_t dev; + grub_err_t err; + struct grub_btrfs_superblock sb; + + dev = grub_device_open (name); + if (!dev) + return 0; + if (!dev->disk) + { + grub_device_close (dev); + return 0; + } + err = read_sblock (dev->disk, &sb); + if (err == GRUB_ERR_BAD_FS) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (err) + { + grub_device_close (dev); + grub_print_error (); + return 0; + } + if (grub_memcmp (ctx->data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0 + || sb.this_device.device_id != ctx->id) + { + grub_device_close (dev); + return 0; + } + + ctx->dev_found = dev; + return 1; +} + static grub_device_t find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) { - grub_device_t dev_found = NULL; - auto int hook (const char *name); - int hook (const char *name) - { - grub_device_t dev; - grub_err_t err; - struct grub_btrfs_superblock sb; - dev = grub_device_open (name); - if (!dev) - return 0; - if (!dev->disk) - { - grub_device_close (dev); - return 0; - } - err = read_sblock (dev->disk, &sb); - if (err == GRUB_ERR_BAD_FS) - { - grub_device_close (dev); - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (err) - { - grub_device_close (dev); - grub_print_error (); - return 0; - } - if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0 - || sb.this_device.device_id != id) - { - grub_device_close (dev); - return 0; - } - - dev_found = dev; - return 1; - } - + struct find_device_ctx ctx = { + .data = data, + .id = id, + .dev_found = NULL + }; unsigned i; for (i = 0; i < data->n_devices_attached; i++) if (id == data->devices_attached[i].id) return data->devices_attached[i].dev; if (do_rescan) - grub_device_iterate (hook); - if (!dev_found) + grub_device_iterate (find_device_iter, &ctx); + if (!ctx.dev_found) { grub_error (GRUB_ERR_BAD_FS, N_("couldn't find a necessary member device " @@ -605,14 +596,14 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) * sizeof (data->devices_attached[0])); if (!data->devices_attached) { - grub_device_close (dev_found); + grub_device_close (ctx.dev_found); data->devices_attached = tmp; return NULL; } } data->devices_attached[data->n_devices_attached - 1].id = id; - data->devices_attached[data->n_devices_attached - 1].dev = dev_found; - return dev_found; + data->devices_attached[data->n_devices_attached - 1].dev = ctx.dev_found; + return ctx.dev_found; } static grub_err_t @@ -1181,6 +1172,40 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, return pos - pos0; } +static grub_err_t +get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, + grub_uint64_t *tree, grub_uint8_t *type) +{ + grub_err_t err; + grub_disk_addr_t elemaddr; + grub_size_t elemsize; + struct grub_btrfs_key key_out, key_in; + struct grub_btrfs_root_item ri; + + key_in.object_id = GRUB_BTRFS_ROOT_VOL_OBJECTID; + key_in.offset = 0; + key_in.type = GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM; + err = lower_bound (data, &key_in, &key_out, + data->sblock.root_tree, + &elemaddr, &elemsize, NULL, 0); + if (err) + return err; + if (key_in.object_id != key_out.object_id + || key_in.type != key_out.type + || key_in.offset != key_out.offset) + return grub_error (GRUB_ERR_BAD_FS, "no root"); + err = grub_btrfs_read_logical (data, elemaddr, &ri, + sizeof (ri), 0); + if (err) + return err; + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); + *tree = ri.tree; + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + return GRUB_ERR_NONE; +} + static grub_err_t find_path (struct grub_btrfs_data *data, const char *path, struct grub_btrfs_key *key, @@ -1193,42 +1218,31 @@ find_path (struct grub_btrfs_data *data, grub_size_t allocated = 0; struct grub_btrfs_dir_item *direl = NULL; struct grub_btrfs_key key_out; - int skip_default; const char *ctoken; grub_size_t ctokenlen; char *path_alloc = NULL; char *origpath = NULL; unsigned symlinks_max = 32; - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - *tree = data->sblock.root_tree; - key->object_id = data->sblock.root_dir_objectid; - key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; - key->offset = 0; - skip_default = 1; + err = get_root (data, key, tree, type); + if (err) + return err; + origpath = grub_strdup (path); if (!origpath) return grub_errno; while (1) { - if (!skip_default) - { - while (path[0] == '/') - path++; - if (!path[0]) - break; - slash = grub_strchr (path, '/'); - if (!slash) - slash = path + grub_strlen (path); - ctoken = path; - ctokenlen = slash - path; - } - else - { - ctoken = "default"; - ctokenlen = sizeof ("default") - 1; - } + while (path[0] == '/') + path++; + if (!path[0]) + break; + slash = grub_strchr (path, '/'); + if (!slash) + slash = path + grub_strlen (path); + ctoken = path; + ctokenlen = slash - path; if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { @@ -1239,10 +1253,8 @@ find_path (struct grub_btrfs_data *data, if (ctokenlen == 1 && ctoken[0] == '.') { - if (!skip_default) - path = slash; - skip_default = 0; - continue; + path = slash; + continue; } if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.') { @@ -1272,9 +1284,7 @@ find_path (struct grub_btrfs_data *data, *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; key->object_id = key_out.offset; - if (!skip_default) - path = slash; - skip_default = 0; + path = slash; continue; } @@ -1344,9 +1354,7 @@ find_path (struct grub_btrfs_data *data, return err; } - if (!skip_default) - path = slash; - skip_default = 0; + path = slash; if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) { struct grub_btrfs_inode inode; @@ -1396,12 +1404,9 @@ find_path (struct grub_btrfs_data *data, path = path_alloc = tmp; if (path[0] == '/') { - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - *tree = data->sblock.root_tree; - key->object_id = data->sblock.root_dir_objectid; - key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; - key->offset = 0; - skip_default = 1; + err = get_root (data, key, tree, type); + if (err) + return err; } continue; } @@ -1476,8 +1481,7 @@ find_path (struct grub_btrfs_data *data, static grub_err_t grub_btrfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_key key_in, key_out; @@ -1571,7 +1575,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, c = cdirel->name[grub_le_to_cpu16 (cdirel->n)]; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0; info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY); - if (hook (cdirel->name, &info)) + if (hook (cdirel->name, &info, hook_data)) goto out; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c; } diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c new file mode 100644 index 000000000..93a38003e --- /dev/null +++ b/grub-core/fs/cbfs.c @@ -0,0 +1,391 @@ +/* cbfs.c - cbfs and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +struct grub_archelp_data +{ + grub_disk_t disk; + grub_off_t hofs, next_hofs; + grub_off_t dofs; + grub_off_t size; + grub_off_t cbfs_start; + grub_off_t cbfs_end; + grub_off_t cbfs_align; +}; + +static grub_err_t +grub_cbfs_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, + grub_uint32_t *mode) +{ + grub_size_t offset; + for (;; + data->dofs = data->hofs + offset, + data->next_hofs = ALIGN_UP (data->dofs + data->size, data->cbfs_align)) + { + struct cbfs_file hd; + grub_size_t namesize; + + data->hofs = data->next_hofs; + + if (data->hofs >= data->cbfs_end) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (hd.magic)) != 0) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + data->size = grub_be_to_cpu32 (hd.len); + (void) mtime; + offset = grub_be_to_cpu32 (hd.offset); + + if (mode) + *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME; + + namesize = offset; + if (namesize >= sizeof (hd)) + namesize -= sizeof (hd); + if (namesize == 0) + continue; + *name = grub_malloc (namesize + 1); + if (*name == NULL) + return grub_errno; + + if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), + namesize, *name)) + { + grub_free (*name); + return grub_errno; + } + + if ((*name)[0] == '\0') + { + grub_free (*name); + *name = NULL; + continue; + } + + (*name)[namesize] = 0; + + data->dofs = data->hofs + offset; + data->next_hofs = ALIGN_UP (data->dofs + data->size, data->cbfs_align); + return GRUB_ERR_NONE; + } +} + +static void +grub_cbfs_rewind (struct grub_archelp_data *data) +{ + data->next_hofs = data->cbfs_start; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_cbfs_find_file, + .rewind = grub_cbfs_rewind + }; + +static int +validate_head (struct cbfs_header *head) +{ + return (head->magic == grub_cpu_to_be32_compile_time (CBFS_HEADER_MAGIC) + && (head->version + == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION1) + || head->version + == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION2)) + && (grub_be_to_cpu32 (head->bootblocksize) + < grub_be_to_cpu32 (head->romsize)) + && (grub_be_to_cpu32 (head->offset) + < grub_be_to_cpu32 (head->romsize)) + && (grub_be_to_cpu32 (head->offset) + + grub_be_to_cpu32 (head->bootblocksize) + < grub_be_to_cpu32 (head->romsize)) + && head->align != 0 + && (head->align & (head->align - 1)) == 0 + && head->romsize != 0); +} + +static struct grub_archelp_data * +grub_cbfs_mount (grub_disk_t disk) +{ + struct cbfs_file hd; + struct grub_archelp_data *data; + grub_uint32_t ptr; + grub_off_t header_off; + struct cbfs_header head; + + if (grub_disk_read (disk, grub_disk_get_size (disk) - 1, + GRUB_DISK_SECTOR_SIZE - sizeof (ptr), + sizeof (ptr), &ptr)) + goto fail; + + ptr = grub_cpu_to_le32 (ptr); + header_off = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS) + + (grub_int32_t) ptr; + + if (grub_disk_read (disk, 0, header_off, + sizeof (head), &head)) + goto fail; + + if (!validate_head (&head)) + goto fail; + + data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data)); + if (!data) + goto fail; + + data->cbfs_start = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS) + - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset)); + data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS) + - grub_be_to_cpu32 (head.bootblocksize); + data->cbfs_align = grub_be_to_cpu32 (head.align); + + if (data->cbfs_start >= (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)) + goto fail; + if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)) + data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS); + + data->next_hofs = data->cbfs_start; + + if (grub_disk_read (disk, 0, data->cbfs_start, sizeof (hd), &hd)) + goto fail; + + if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (CBFS_FILE_MAGIC) - 1)) + goto fail; + + data->disk = disk; + + return data; + +fail: + grub_error (GRUB_ERR_BAD_FS, "not a cbfs filesystem"); + return 0; +} + +static grub_err_t +grub_cbfs_dir (grub_device_t device, const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cbfs_mount (device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_dir (data, &arcops, + path_in, hook, hook_data); + + grub_free (data); + + return err; +} + +static grub_err_t +grub_cbfs_open (grub_file_t file, const char *name_in) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cbfs_mount (file->device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_open (data, &arcops, name_in); + if (err) + { + grub_free (data); + } + else + { + file->data = data; + file->size = data->size; + } + return err; +} + +static grub_ssize_t +grub_cbfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_archelp_data *data; + grub_ssize_t ret; + + data = file->data; + data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; + + ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : (grub_ssize_t) len; + data->disk->read_hook = 0; + + return ret; +} + +static grub_err_t +grub_cbfs_close (grub_file_t file) +{ + struct grub_archelp_data *data; + + data = file->data; + grub_free (data); + + return grub_errno; +} + +#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) \ + && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN) + +static char *cbfsdisk_addr; +static grub_off_t cbfsdisk_size = 0; + +static int +grub_cbfsdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + return hook ("cbfsdisk", hook_data); +} + +static grub_err_t +grub_cbfsdisk_open (const char *name, grub_disk_t disk) +{ + if (grub_strcmp (name, "cbfsdisk")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a cbfsdisk"); + + disk->total_sectors = cbfsdisk_size / GRUB_DISK_SECTOR_SIZE; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; + disk->id = (unsigned long) "cbfs"; + + return GRUB_ERR_NONE; +} + +static void +grub_cbfsdisk_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_cbfsdisk_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_memcpy (buf, cbfsdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), + size << GRUB_DISK_SECTOR_BITS); + return 0; +} + +static grub_err_t +grub_cbfsdisk_write (grub_disk_t disk __attribute__ ((unused)), + grub_disk_addr_t sector __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused)), + const char *buf __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "rom flashing isn't implemented yet"); +} + +static struct grub_disk_dev grub_cbfsdisk_dev = + { + .name = "cbfsdisk", + .id = GRUB_DISK_DEVICE_CBFSDISK_ID, + .iterate = grub_cbfsdisk_iterate, + .open = grub_cbfsdisk_open, + .close = grub_cbfsdisk_close, + .read = grub_cbfsdisk_read, + .write = grub_cbfsdisk_write, + .next = 0 + }; + +static void +init_cbfsdisk (void) +{ + grub_uint32_t ptr; + struct cbfs_header *head; + + ptr = *(grub_uint32_t *) 0xfffffffc; + head = (struct cbfs_header *) (grub_addr_t) ptr; + + if (!validate_head (head)) + return; + + cbfsdisk_size = ALIGN_UP (grub_be_to_cpu32 (head->romsize), + GRUB_DISK_SECTOR_SIZE); + cbfsdisk_addr = (void *) (grub_addr_t) (0x100000000ULL - cbfsdisk_size); + + grub_disk_dev_register (&grub_cbfsdisk_dev); +} + +static void +fini_cbfsdisk (void) +{ + if (! cbfsdisk_size) + return; + grub_disk_dev_unregister (&grub_cbfsdisk_dev); +} + +#endif + +static struct grub_fs grub_cbfs_fs = { + .name = "cbfs", + .dir = grub_cbfs_dir, + .open = grub_cbfs_open, + .read = grub_cbfs_read, + .close = grub_cbfs_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, + .blocklist_install = 0, +#endif +}; + +GRUB_MOD_INIT (cbfs) +{ +#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN) + init_cbfsdisk (); +#endif + grub_fs_register (&grub_cbfs_fs); +} + +GRUB_MOD_FINI (cbfs) +{ + grub_fs_unregister (&grub_cbfs_fs); +#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN) + fini_cbfsdisk (); +#endif +} diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index e9236cd97..b14e190f9 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -1,7 +1,7 @@ /* cpio.c - cpio and tar filesystem. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,66 +17,11 @@ * along with this program. If not, see . */ -#include -#include #include -#include -#include -#include -GRUB_MOD_LICENSE ("GPLv3+"); - -#define ATTR_TYPE 0160000 -#define ATTR_FILE 0100000 -#define ATTR_DIR 0040000 -#define ATTR_LNK 0120000 - -#ifdef MODE_ODC -#define ALIGN_CPIO(x) x -#define MAGIC "070707" -struct head -{ - char magic[6]; - char dev[6]; - char ino[6]; - char mode[6]; - char uid[6]; - char gid[6]; - char nlink[6]; - char rdev[6]; - char mtime[11]; - char namesize[6]; - char filesize[11]; -} __attribute__ ((packed)); -#elif defined (MODE_NEWC) -#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4)) -#define MAGIC "070701" -#define MAGIC2 "070702" -struct head -{ - char magic[6]; - char ino[8]; - char mode[8]; - char uid[8]; - char gid[8]; - char nlink[8]; - char mtime[8]; - char filesize[8]; - char devmajor[8]; - char devminor[8]; - char rdevmajor[8]; - char rdevminor[8]; - char namesize[8]; - char check[8]; -} __attribute__ ((packed)); -#elif !defined (MODE_USTAR) /* cpio support */ #define ALIGN_CPIO(x) (ALIGN_UP ((x), 2)) -#ifdef MODE_BIGENDIAN -#define MAGIC "\x71\xc7" -#else #define MAGIC "\xc7\x71" -#endif struct head { grub_uint16_t magic[1]; @@ -91,694 +36,26 @@ struct head grub_uint16_t namesize[1]; grub_uint16_t filesize[2]; } __attribute__ ((packed)); -#else -/* tar support */ -#define MAGIC "ustar" -struct head -{ - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char chksum[8]; - char typeflag; - char linkname[100]; - char magic[6]; - char version[2]; - char uname[32]; - char gname[32]; - char devmajor[8]; - char devminor[8]; - char prefix[155]; -} __attribute__ ((packed)); -#endif -struct grub_cpio_data -{ - grub_disk_t disk; - grub_off_t hofs; - grub_off_t dofs; - grub_off_t size; -#ifdef MODE_USTAR - char *linkname; - grub_size_t linkname_alloc; -#endif -}; - -static grub_dl_t my_mod; - -static inline void -canonicalize (char *name) -{ - char *iptr, *optr; - for (iptr = name, optr = name; *iptr; ) - { - while (*iptr == '/') - iptr++; - if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) - { - iptr += 2; - continue; - } - if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0)) - { - iptr += 3; - if (optr == name) - continue; - for (optr -= 2; optr >= name && *optr != '/'; optr--); - optr++; - continue; - } - while (*iptr && *iptr != '/') - *optr++ = *iptr++; - if (*iptr) - *optr++ = *iptr++; - } - *optr = 0; -} - -#if defined (MODE_ODC) || defined (MODE_USTAR) -static inline unsigned long long -read_number (const char *str, grub_size_t size) -{ - unsigned long long ret = 0; - while (size-- && *str >= '0' && *str <= '7') - ret = (ret << 3) | (*str++ & 0xf); - return ret; -} -#elif defined (MODE_NEWC) -static inline unsigned long long -read_number (const char *str, grub_size_t size) -{ - unsigned long long ret = 0; - while (size-- && grub_isxdigit (*str)) - { - char dig = *str++; - if (dig >= '0' && dig <= '9') - dig &= 0xf; - else if (dig >= 'a' && dig <= 'f') - dig -= 'a' - 10; - else - dig -= 'A' - 10; - ret = (ret << 4) | (dig); - } - return ret; -} -#else static inline unsigned long long read_number (const grub_uint16_t *arr, grub_size_t size) { long long ret = 0; -#ifdef MODE_BIGENDIAN - while (size--) - ret = (ret << 16) | grub_be_to_cpu16 (*arr++); -#else while (size--) ret = (ret << 16) | grub_le_to_cpu16 (*arr++); -#endif return ret; } -#endif -static grub_err_t -grub_cpio_find_file (struct grub_cpio_data *data, char **name, - grub_int32_t *mtime, grub_disk_addr_t *ofs, - grub_uint32_t *mode) -{ -#ifndef MODE_USTAR - struct head hd; - grub_size_t namesize; - grub_uint32_t modeval; +#define FSNAME "cpiofs" - if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; +#include "cpio_common.c" - if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0 -#ifdef MAGIC2 - && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0 -#endif - ) - return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); - data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize)); - if (mtime) - *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime)); - modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode)); - namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize)); - - if (mode) - *mode = modeval; - - *name = grub_malloc (namesize + 1); - if (*name == NULL) - return grub_errno; - - if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), - namesize, *name)) - { - grub_free (*name); - return grub_errno; - } - (*name)[namesize] = 0; - - if (data->size == 0 && modeval == 0 && namesize == 11 - && grub_memcmp(*name, "TRAILER!!!", 11) == 0) - { - *ofs = 0; - grub_free (*name); - return GRUB_ERR_NONE; - } - - canonicalize (*name); - - data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize); - *ofs = data->dofs + ALIGN_CPIO (data->size); -#else - struct head hd; - int reread = 0, have_longname = 0, have_longlink = 0; - - for (reread = 0; reread < 3; reread++) - { - if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; - - if (!hd.name[0] && !hd.prefix[0]) - { - *ofs = 0; - return GRUB_ERR_NONE; - } - - if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) - return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); - - if (hd.typeflag == 'L') - { - grub_err_t err; - grub_size_t namesize = read_number (hd.size, sizeof (hd.size)); - *name = grub_malloc (namesize + 1); - if (*name == NULL) - return grub_errno; - err = grub_disk_read (data->disk, 0, - data->hofs + GRUB_DISK_SECTOR_SIZE, namesize, - *name); - (*name)[namesize] = 0; - if (err) - return err; - data->hofs += GRUB_DISK_SECTOR_SIZE - + ((namesize + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - have_longname = 1; - continue; - } - - if (hd.typeflag == 'K') - { - grub_err_t err; - grub_size_t linksize = read_number (hd.size, sizeof (hd.size)); - if (data->linkname_alloc < linksize + 1) - { - char *n; - n = grub_malloc (2 * (linksize + 1)); - if (!n) - return grub_errno; - grub_free (data->linkname); - data->linkname = n; - data->linkname_alloc = 2 * (linksize + 1); - } - - err = grub_disk_read (data->disk, 0, - data->hofs + GRUB_DISK_SECTOR_SIZE, linksize, - data->linkname); - if (err) - return err; - data->linkname[linksize] = 0; - data->hofs += GRUB_DISK_SECTOR_SIZE - + ((linksize + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - have_longlink = 1; - continue; - } - - if (!have_longname) - { - grub_size_t extra_size = 0; - - while (extra_size < sizeof (hd.prefix) - && hd.prefix[extra_size]) - extra_size++; - *name = grub_malloc (sizeof (hd.name) + extra_size + 2); - if (*name == NULL) - return grub_errno; - if (hd.prefix[0]) - { - grub_memcpy (*name, hd.prefix, extra_size); - (*name)[extra_size++] = '/'; - } - grub_memcpy (*name + extra_size, hd.name, sizeof (hd.name)); - (*name)[extra_size + sizeof (hd.name)] = 0; - } - - data->size = read_number (hd.size, sizeof (hd.size)); - data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; - *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - if (mtime) - *mtime = read_number (hd.mtime, sizeof (hd.mtime)); - if (mode) - { - *mode = read_number (hd.mode, sizeof (hd.mode)); - switch (hd.typeflag) - { - /* Hardlink. */ - case '1': - /* Symlink. */ - case '2': - *mode |= ATTR_LNK; - break; - case '0': - *mode |= ATTR_FILE; - break; - case '5': - *mode |= ATTR_DIR; - break; - } - } - if (!have_longlink) - { - if (data->linkname_alloc < 101) - { - char *n; - n = grub_malloc (101); - if (!n) - return grub_errno; - grub_free (data->linkname); - data->linkname = n; - data->linkname_alloc = 101; - } - grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname)); - data->linkname[100] = 0; - } - - canonicalize (*name); - return GRUB_ERR_NONE; - } -#endif - return GRUB_ERR_NONE; -} - -static struct grub_cpio_data * -grub_cpio_mount (grub_disk_t disk) -{ - struct head hd; - struct grub_cpio_data *data; - - if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) - goto fail; - - if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1) -#ifdef MAGIC2 - && grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1) -#endif - ) - goto fail; - - data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data)); - if (!data) - goto fail; - - data->disk = disk; - - return data; - -fail: - grub_error (GRUB_ERR_BAD_FS, "not a " -#ifdef MODE_USTAR - "tar" -#else - "cpio" -#endif - " filesystem"); - return 0; -} - -static grub_err_t -handle_symlink (struct grub_cpio_data *data, - const char *fn, char **name, - grub_uint32_t mode, int *restart) -{ - grub_size_t flen; - char *target; -#ifndef MODE_USTAR - grub_err_t err; -#endif - char *ptr; - char *lastslash; - grub_size_t prefixlen; - char *rest; - grub_size_t size; - - *restart = 0; - - if ((mode & ATTR_TYPE) != ATTR_LNK) - return GRUB_ERR_NONE; - flen = grub_strlen (fn); - if (grub_memcmp (*name, fn, flen) != 0 - || ((*name)[flen] != 0 && (*name)[flen] != '/')) - return GRUB_ERR_NONE; - rest = *name + flen; - lastslash = rest; - if (*rest) - rest++; - while (lastslash >= *name && *lastslash != '/') - lastslash--; - if (lastslash >= *name) - prefixlen = lastslash - *name; - else - prefixlen = 0; - - if (prefixlen) - prefixlen++; - -#ifdef MODE_USTAR - size = grub_strlen (data->linkname); -#else - size = data->size; -#endif - if (size == 0) - return GRUB_ERR_NONE; - target = grub_malloc (size + grub_strlen (*name) + 2); - if (!target) - return grub_errno; - -#ifdef MODE_USTAR - grub_memcpy (target + prefixlen, data->linkname, size); -#else - err = grub_disk_read (data->disk, 0, data->dofs, data->size, - target + prefixlen); - if (err) - return err; -#endif - if (target[prefixlen] == '/') - { - grub_memmove (target, target + prefixlen, size); - ptr = target + size; - ptr = grub_stpcpy (ptr, rest); - *ptr = 0; - grub_dprintf ("cpio", "symlink redirected %s to %s\n", - *name, target); - grub_free (*name); - - canonicalize (target); - *name = target; - *restart = 1; - return GRUB_ERR_NONE; - } - if (prefixlen) - { - grub_memcpy (target, *name, prefixlen); - target[prefixlen-1] = '/'; - } - ptr = target + prefixlen + size; - ptr = grub_stpcpy (ptr, rest); - *ptr = 0; - grub_dprintf ("cpio", "symlink redirected %s to %s\n", - *name, target); - grub_free (*name); - canonicalize (target); - *name = target; - *restart = 1; - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_cpio_dir (grub_device_t device, const char *path_in, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) -{ - struct grub_cpio_data *data; - grub_disk_addr_t ofs; - char *prev, *name, *path, *ptr; - grub_size_t len; - int symlinknest = 0; - - path = grub_strdup (path_in + 1); - if (!path) - return grub_errno; - canonicalize (path); - for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) - *ptr = 0; - - grub_dl_ref (my_mod); - - prev = 0; - - data = grub_cpio_mount (device->disk); - if (!data) - { - grub_free (path); - return grub_errno; - } - - len = grub_strlen (path); - data->hofs = 0; - while (1) - { - grub_int32_t mtime; - grub_uint32_t mode; - grub_err_t err; - - if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode)) - goto fail; - - if (!ofs) - break; - - if (grub_memcmp (path, name, len) == 0 - && (name[len] == 0 || name[len] == '/' || len == 0)) - { - char *p, *n; - - n = name + len; - while (*n == '/') - n++; - - p = grub_strchr (n, '/'); - if (p) - *p = 0; - - if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = (p != NULL) || ((mode & ATTR_TYPE) == ATTR_DIR); - info.mtime = mtime; - info.mtimeset = 1; - - if (hook (n, &info)) - { - grub_free (name); - goto fail; - } - grub_free (prev); - prev = name; - } - else - { - int restart = 0; - err = handle_symlink (data, name, &path, mode, &restart); - grub_free (name); - if (err) - goto fail; - if (restart) - { - len = grub_strlen (path); - if (++symlinknest == 8) - { - grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - goto fail; - } - ofs = 0; - } - } - } - else - grub_free (name); - data->hofs = ofs; - } - -fail: - - grub_free (path); - grub_free (prev); -#ifdef MODE_USTAR - grub_free (data->linkname); -#endif - grub_free (data); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_err_t -grub_cpio_open (grub_file_t file, const char *name_in) -{ - struct grub_cpio_data *data; - grub_disk_addr_t ofs; - char *fn; - char *name = grub_strdup (name_in + 1); - int symlinknest = 0; - - if (!name) - return grub_errno; - - canonicalize (name); - - grub_dl_ref (my_mod); - - data = grub_cpio_mount (file->device->disk); - if (!data) - { - grub_free (name); - return grub_errno; - } - - data->hofs = 0; - while (1) - { - grub_uint32_t mode; - int restart; - - if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode)) - goto fail; - - if (!ofs) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in); - break; - } - - if (handle_symlink (data, fn, &name, mode, &restart)) - { - grub_free (fn); - goto fail; - } - - if (restart) - { - ofs = 0; - if (++symlinknest == 8) - { - grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - goto fail; - } - goto no_match; - } - - if (grub_strcmp (name, fn) != 0) - goto no_match; - - file->data = data; - file->size = data->size; - grub_free (fn); - grub_free (name); - - return GRUB_ERR_NONE; - - no_match: - - grub_free (fn); - data->hofs = ofs; - } - -fail: -#ifdef MODE_USTAR - grub_free (data->linkname); -#endif - grub_free (data); - grub_free (name); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_ssize_t -grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) -{ - struct grub_cpio_data *data; - - data = file->data; - return (grub_disk_read (data->disk, 0, data->dofs + file->offset, - len, buf)) ? -1 : (grub_ssize_t) len; -} - -static grub_err_t -grub_cpio_close (grub_file_t file) -{ - struct grub_cpio_data *data; - - data = file->data; -#ifdef MODE_USTAR - grub_free (data->linkname); -#endif - grub_free (data); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static struct grub_fs grub_cpio_fs = { -#ifdef MODE_USTAR - .name = "tarfs", -#elif defined (MODE_ODC) - .name = "odc", -#elif defined (MODE_NEWC) - .name = "newc", -#else - .name = "cpiofs", -#endif - .dir = grub_cpio_dir, - .open = grub_cpio_open, - .read = grub_cpio_read, - .close = grub_cpio_close, -#ifdef GRUB_UTIL - .reserved_first_sector = 0, - .blocklist_install = 0, -#endif -}; - -#ifdef MODE_USTAR -GRUB_MOD_INIT (tar) -#elif defined (MODE_ODC) -GRUB_MOD_INIT (odc) -#elif defined (MODE_NEWC) -GRUB_MOD_INIT (newc) -#elif defined (MODE_BIGENDIAN) -GRUB_MOD_INIT (cpio_be) -#else GRUB_MOD_INIT (cpio) -#endif { grub_fs_register (&grub_cpio_fs); - my_mod = mod; } -#ifdef MODE_USTAR -GRUB_MOD_FINI (tar) -#elif defined (MODE_ODC) -GRUB_MOD_FINI (odc) -#elif defined (MODE_NEWC) -GRUB_MOD_FINI (newc) -#elif defined (MODE_BIGENDIAN) -GRUB_MOD_FINI (cpio_be) -#else GRUB_MOD_FINI (cpio) -#endif { grub_fs_unregister (&grub_cpio_fs); } diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c index 8bad314cd..83df8195b 100644 --- a/grub-core/fs/cpio_be.c +++ b/grub-core/fs/cpio_be.c @@ -1,2 +1,61 @@ -#define MODE_BIGENDIAN 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define ALIGN_CPIO(x) (ALIGN_UP ((x), 2)) +#define MAGIC "\x71\xc7" + +struct head +{ + grub_uint16_t magic[1]; + grub_uint16_t dev; + grub_uint16_t ino; + grub_uint16_t mode[1]; + grub_uint16_t uid; + grub_uint16_t gid; + grub_uint16_t nlink; + grub_uint16_t rdev; + grub_uint16_t mtime[2]; + grub_uint16_t namesize[1]; + grub_uint16_t filesize[2]; +} __attribute__ ((packed)); + +static inline unsigned long long +read_number (const grub_uint16_t *arr, grub_size_t size) +{ + long long ret = 0; + while (size--) + ret = (ret << 16) | grub_be_to_cpu16 (*arr++); + return ret; +} + +#define FSNAME "cpiofs_be" + +#include "cpio_common.c" + +GRUB_MOD_INIT (cpio_be) +{ + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (cpio_be) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c new file mode 100644 index 000000000..b0ae9f445 --- /dev/null +++ b/grub-core/fs/cpio_common.c @@ -0,0 +1,237 @@ +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_archelp_data +{ + grub_disk_t disk; + grub_off_t hofs; + grub_off_t next_hofs; + grub_off_t dofs; + grub_off_t size; +}; + +static grub_err_t +grub_cpio_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, grub_uint32_t *mode) +{ + struct head hd; + grub_size_t namesize; + grub_uint32_t modeval; + + data->hofs = data->next_hofs; + + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0 +#ifdef MAGIC2 + && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0 +#endif + ) + return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); + data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize)); + if (mtime) + *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime)); + modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode)); + namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize)); + + if (mode) + *mode = modeval; + + *name = grub_malloc (namesize + 1); + if (*name == NULL) + return grub_errno; + + if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), + namesize, *name)) + { + grub_free (*name); + return grub_errno; + } + (*name)[namesize] = 0; + + if (data->size == 0 && modeval == 0 && namesize == 11 + && grub_memcmp(*name, "TRAILER!!!", 11) == 0) + { + *mode = GRUB_ARCHELP_ATTR_END; + grub_free (*name); + return GRUB_ERR_NONE; + } + + data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize); + data->next_hofs = data->dofs + ALIGN_CPIO (data->size); + return GRUB_ERR_NONE; +} + +static char * +grub_cpio_get_link_target (struct grub_archelp_data *data) +{ + char *ret; + grub_err_t err; + + if (data->size == 0) + return grub_strdup (""); + ret = grub_malloc (data->size + 1); + if (!ret) + return NULL; + + err = grub_disk_read (data->disk, 0, data->dofs, data->size, + ret); + if (err) + { + grub_free (ret); + return NULL; + } + ret[data->size] = '\0'; + return ret; +} + +static void +grub_cpio_rewind (struct grub_archelp_data *data) +{ + data->next_hofs = 0; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_cpio_find_file, + .get_link_target = grub_cpio_get_link_target, + .rewind = grub_cpio_rewind + }; + +static struct grub_archelp_data * +grub_cpio_mount (grub_disk_t disk) +{ + struct head hd; + struct grub_archelp_data *data; + + if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) + goto fail; + + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1) +#ifdef MAGIC2 + && grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1) +#endif + ) + goto fail; + + data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data)); + if (!data) + goto fail; + + data->disk = disk; + + return data; + +fail: + grub_error (GRUB_ERR_BAD_FS, "not a " FSNAME " filesystem"); + return 0; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_dir (data, &arcops, + path_in, hook, hook_data); + + grub_free (data); + + return err; +} + +static grub_err_t +grub_cpio_open (grub_file_t file, const char *name_in) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (file->device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_open (data, &arcops, name_in); + if (err) + { + grub_free (data); + } + else + { + file->data = data; + file->size = data->size; + } + return err; +} + +static grub_ssize_t +grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_archelp_data *data; + grub_ssize_t ret; + + data = file->data; + data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; + + ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : (grub_ssize_t) len; + data->disk->read_hook = 0; + + return ret; +} + +static grub_err_t +grub_cpio_close (grub_file_t file) +{ + struct grub_archelp_data *data; + + data = file->data; + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_cpio_fs = { + .name = FSNAME, + .dir = grub_cpio_dir, + .open = grub_cpio_open, + .read = grub_cpio_read, + .close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, + .blocklist_install = 0, +#endif +}; diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index c50e379d6..5f7a2b9d5 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -58,14 +58,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); (grub_le_to_cpu32 (data->sblock.log2_block_size) + 10) /* The size of an ext2 block in bytes. */ -#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE (data)) +#define EXT2_BLOCK_SIZE(data) (1U << LOG2_BLOCK_SIZE (data)) /* The revision level. */ #define EXT2_REVISION(data) grub_le_to_cpu32 (data->sblock.revision_level) /* The inode size. */ #define EXT2_INODE_SIZE(data) \ - (EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \ + (data->sblock.revision_level \ + == grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) \ ? EXT2_GOOD_OLD_INODE_SIZE \ : grub_le_to_cpu16 (data->sblock.inode_size)) @@ -105,7 +106,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); * flags here as the related features are implemented into the driver. */ #define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \ | EXT4_FEATURE_INCOMPAT_EXTENTS \ - | EXT4_FEATURE_INCOMPAT_FLEX_BG ) + | EXT4_FEATURE_INCOMPAT_FLEX_BG \ + | EXT4_FEATURE_INCOMPAT_64BIT) /* List of rationales for the ignored "incompatible" features: * needs_recovery: Not really back-incompatible - was added as such to forbid * ext2 drivers from mounting an ext3 volume with a dirty @@ -179,7 +181,7 @@ struct grub_ext2_sblock grub_uint32_t hash_seed[4]; grub_uint8_t def_hash_version; grub_uint8_t jnl_backup_type; - grub_uint16_t reserved_word_pad; + grub_uint16_t group_desc_size; grub_uint32_t default_mount_opts; grub_uint32_t first_meta_bg; grub_uint32_t mkfs_time; @@ -197,6 +199,14 @@ struct grub_ext2_block_group grub_uint16_t used_dirs; grub_uint16_t pad; grub_uint32_t reserved[3]; + grub_uint32_t block_id_hi; + grub_uint32_t inode_id_hi; + grub_uint32_t inode_table_id_hi; + grub_uint16_t free_blocks_hi; + grub_uint16_t free_inodes_hi; + grub_uint16_t used_dirs_hi; + grub_uint16_t pad2; + grub_uint32_t reserved2[3]; }; /* The ext2 inode. */ @@ -237,6 +247,7 @@ struct ext2_dirent { grub_uint32_t inode; grub_uint16_t direntlen; +#define MAX_NAMELEN 255 grub_uint8_t namelen; grub_uint8_t filetype; }; @@ -310,6 +321,7 @@ struct grub_fshelp_node struct grub_ext2_data { struct grub_ext2_sblock sblock; + int log_group_desc_size; grub_disk_t disk; struct grub_ext2_inode *inode; struct grub_fshelp_node diropen; @@ -328,16 +340,17 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group, return grub_disk_read (data->disk, ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1) << LOG2_EXT2_BLOCK_SIZE (data)), - group * sizeof (struct grub_ext2_block_group), + group << data->log_group_desc_size, sizeof (struct grub_ext2_block_group), blkgrp); } static struct grub_ext4_extent_header * -grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, +grub_ext4_find_leaf (struct grub_ext2_data *data, struct grub_ext4_extent_header *ext_block, grub_uint32_t fileblock) { struct grub_ext4_extent_idx *index; + void *buf = NULL; while (1) { @@ -346,8 +359,8 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, index = (struct grub_ext4_extent_idx *) (ext_block + 1); - if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC) - return 0; + if (ext_block->magic != grub_cpu_to_le16_compile_time (EXT4_EXT_MAGIC)) + goto fail; if (ext_block->depth == 0) return ext_block; @@ -359,17 +372,24 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, } if (--i < 0) - return 0; + goto fail; block = grub_le_to_cpu16 (index[i].leaf_hi); - block = (block << 32) + grub_le_to_cpu32 (index[i].leaf); + block = (block << 32) | grub_le_to_cpu32 (index[i].leaf); + if (!buf) + buf = grub_malloc (EXT2_BLOCK_SIZE(data)); + if (!buf) + goto fail; if (grub_disk_read (data->disk, block << LOG2_EXT2_BLOCK_SIZE (data), 0, EXT2_BLOCK_SIZE(data), buf)) - return 0; + goto fail; - ext_block = (struct grub_ext4_extent_header *) buf; + ext_block = buf; } + fail: + grub_free (buf); + return 0; } static grub_disk_addr_t @@ -377,20 +397,21 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_ext2_data *data = node->data; struct grub_ext2_inode *inode = &node->inode; - int blknr = -1; unsigned int blksz = EXT2_BLOCK_SIZE (data); + grub_disk_addr_t blksz_quarter = blksz / 4; int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data); + int log_perblock = log2_blksz + 9 - 2; + grub_uint32_t indir; + int shift; - if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG) + if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG)) { - GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data)); struct grub_ext4_extent_header *leaf; struct grub_ext4_extent *ext; int i; + grub_disk_addr_t ret; - leaf = grub_ext4_find_leaf (data, buf, - (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, - fileblock); + leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock); if (! leaf) { grub_error (GRUB_ERR_BAD_FS, "invalid extent"); @@ -408,7 +429,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { fileblock -= grub_le_to_cpu32 (ext[i].block); if (fileblock >= grub_le_to_cpu16 (ext[i].len)) - return 0; + ret = 0; else { grub_disk_addr_t start; @@ -416,107 +437,75 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) start = grub_le_to_cpu16 (ext[i].start_hi); start = (start << 32) + grub_le_to_cpu32 (ext[i].start); - return fileblock + start; + ret = fileblock + start; } } else { grub_error (GRUB_ERR_BAD_FS, "something wrong with extent"); - return -1; + ret = -1; } + + if (leaf != (struct grub_ext4_extent_header *) inode->blocks.dir_blocks) + grub_free (leaf); + + return ret; } + /* Direct blocks. */ if (fileblock < INDIRECT_BLOCKS) - blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); + return grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); + fileblock -= INDIRECT_BLOCKS; /* Indirect. */ - else if (fileblock < INDIRECT_BLOCKS + blksz / 4) + if (fileblock < blksz_quarter) { - grub_uint32_t indir[blksz / 4]; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (inode->blocks.indir_block)) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]); + indir = inode->blocks.indir_block; + shift = 0; + goto indirect; } + fileblock -= blksz_quarter; /* Double indirect. */ - else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)) + if (fileblock < blksz_quarter * blksz_quarter) { - unsigned int perblock = blksz / 4; - unsigned int rblock = fileblock - (INDIRECT_BLOCKS - + blksz / 4); - grub_uint32_t indir[blksz / 4]; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (inode->blocks.double_indir_block)) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (indir[rblock / perblock])) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - - blknr = grub_le_to_cpu32 (indir[rblock % perblock]); + indir = inode->blocks.double_indir_block; + shift = 1; + goto indirect; } - /* triple indirect. */ - else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1) - + (blksz / 4) * (blksz / 4) * (blksz / 4 + 1)) + fileblock -= blksz_quarter * blksz_quarter; + /* Triple indirect. */ + if (fileblock < blksz_quarter * blksz_quarter * (blksz_quarter + 1)) { - unsigned int perblock = blksz / 4; - unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 - * (blksz / 4 + 1)); - grub_uint32_t indir[blksz / 4]; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (inode->blocks.triple_indir_block)) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (indir[(rblock / perblock) / perblock])) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (indir[(rblock / perblock) % perblock])) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - blknr = grub_le_to_cpu32 (indir[rblock % perblock]); - } - else - { - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "ext2fs doesn't support quadruple indirect blocks"); + indir = inode->blocks.triple_indir_block; + shift = 2; + goto indirect; } + return grub_error (GRUB_ERR_BAD_FS, + "ext2fs doesn't support quadruple indirect blocks"); - return blknr; +indirect: + do { + if (grub_disk_read (data->disk, + ((grub_disk_addr_t) grub_le_to_cpu32 (indir)) + << log2_blksz, + ((fileblock >> (log_perblock * shift)) + & ((1 << log_perblock) - 1)) + * sizeof (indir), + sizeof (indir), &indir)) + return grub_errno; + } while (shift--); + + return grub_le_to_cpu32 (indir); } /* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_ext2_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_ext2_read_block, grub_cpu_to_le32 (node->inode.size) | (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32), @@ -535,6 +524,7 @@ grub_ext2_read_inode (struct grub_ext2_data *data, int inodes_per_block; unsigned int blkno; unsigned int blkoff; + grub_disk_addr_t base; /* It is easier to calculate if the first inode is 0. */ ino--; @@ -551,10 +541,14 @@ grub_ext2_read_inode (struct grub_ext2_data *data, blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group)) % inodes_per_block; + base = grub_le_to_cpu32 (blkgrp.inode_table_id); + if (data->log_group_desc_size >= 6) + base |= (((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id_hi)) + << 32); + /* Read the inode. */ if (grub_disk_read (data->disk, - (((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) - << LOG2_EXT2_BLOCK_SIZE (data)), + ((base + blkno) << LOG2_EXT2_BLOCK_SIZE (data)), EXT2_INODE_SIZE (data) * blkoff, sizeof (struct grub_ext2_inode), inode)) return grub_errno; @@ -578,7 +572,7 @@ grub_ext2_mount (grub_disk_t disk) goto fail; /* Make sure this is an ext2 filesystem. */ - if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC + if (data->sblock.magic != grub_cpu_to_le16_compile_time (EXT2_MAGIC) || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16) { grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem"); @@ -586,13 +580,29 @@ grub_ext2_mount (grub_disk_t disk) } /* Check the FS doesn't have feature bits enabled that we don't support. */ - if (grub_le_to_cpu32 (data->sblock.feature_incompat) - & ~(EXT2_DRIVER_SUPPORTED_INCOMPAT | EXT2_DRIVER_IGNORED_INCOMPAT)) + if (data->sblock.revision_level != grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) + && (data->sblock.feature_incompat + & grub_cpu_to_le32_compile_time (~(EXT2_DRIVER_SUPPORTED_INCOMPAT + | EXT2_DRIVER_IGNORED_INCOMPAT)))) { grub_error (GRUB_ERR_BAD_FS, "filesystem has unsupported incompatible features"); goto fail; } + if (data->sblock.revision_level != grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) + && (data->sblock.feature_incompat + & grub_cpu_to_le32_compile_time (EXT4_FEATURE_INCOMPAT_64BIT)) + && data->sblock.group_desc_size != 0 + && ((data->sblock.group_desc_size & (data->sblock.group_desc_size - 1)) + == 0) + && (data->sblock.group_desc_size & grub_cpu_to_le16_compile_time (0x1fe0))) + { + grub_uint16_t b = grub_le_to_cpu16 (data->sblock.group_desc_size); + for (data->log_group_desc_size = 0; b != (1 << data->log_group_desc_size); + data->log_group_desc_size++); + } + else + data->log_group_desc_size = 5; data->disk = disk; @@ -636,13 +646,13 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) /* If the filesize of the symlink is bigger than 60 the symlink is stored in a separate block, otherwise it is stored in the inode. */ - if (grub_le_to_cpu32 (diro->inode.size) <= 60) - grub_strncpy (symlink, - diro->inode.symlink, - grub_le_to_cpu32 (diro->inode.size)); + if (grub_le_to_cpu32 (diro->inode.size) <= sizeof (diro->inode.symlink)) + grub_memcpy (symlink, + diro->inode.symlink, + grub_le_to_cpu32 (diro->inode.size)); else { - grub_ext2_read_file (diro, 0, 0, + grub_ext2_read_file (diro, 0, 0, 0, grub_le_to_cpu32 (diro->inode.size), symlink); if (grub_errno) @@ -658,10 +668,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) static int grub_ext2_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { unsigned int fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; @@ -678,7 +685,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, { struct ext2_dirent dirent; - grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent), + grub_ext2_read_file (diro, 0, 0, fpos, sizeof (struct ext2_dirent), (char *) &dirent); if (grub_errno) return 0; @@ -688,11 +695,11 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, if (dirent.inode != 0 && dirent.namelen != 0) { - char filename[dirent.namelen + 1]; + char filename[MAX_NAMELEN + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; - grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent), + grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent), dirent.namelen, filename); if (grub_errno) return 0; @@ -743,7 +750,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_REG; } - if (hook (filename, type, fdiro)) + if (hook (filename, type, fdiro, hook_data)) return 1; } @@ -819,64 +826,75 @@ grub_ext2_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_ext2_data *data = (struct grub_ext2_data *) file->data; - return grub_ext2_read_file (&data->diropen, file->read_hook, + return grub_ext2_read_file (&data->diropen, + file->read_hook, file->read_hook_data, file->offset, len, buf); } -static grub_err_t -grub_ext2_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +/* Context for grub_ext2_dir. */ +struct grub_ext2_dir_ctx { - struct grub_ext2_data *data = 0; - struct grub_fshelp_node *fdiro = 0; + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_ext2_data *data; +}; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); +/* Helper for grub_ext2_dir. */ +static int +grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_ext2_dir_ctx *ctx = data; + struct grub_dirhook_info info; - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) + grub_memset (&info, 0, sizeof (info)); + if (! node->inode_read) { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - if (! node->inode_read) - { - grub_ext2_read_inode (data, node->ino, &node->inode); - if (!grub_errno) - node->inode_read = 1; - grub_errno = GRUB_ERR_NONE; - } - if (node->inode_read) - { - info.mtimeset = 1; - info.mtime = grub_le_to_cpu32 (node->inode.mtime); - } - - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); + grub_ext2_read_inode (ctx->data, node->ino, &node->inode); + if (!grub_errno) + node->inode_read = 1; + grub_errno = GRUB_ERR_NONE; } + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (node->inode.mtime); + } + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + +static grub_err_t +grub_ext2_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) +{ + struct grub_ext2_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; + struct grub_fshelp_node *fdiro = 0; grub_dl_ref (my_mod); - data = grub_ext2_mount (device->disk); - if (! data) + ctx.data = grub_ext2_mount (device->disk); + if (! ctx.data) goto fail; - grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir, - grub_ext2_read_symlink, GRUB_FSHELP_DIR); + grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, + grub_ext2_iterate_dir, grub_ext2_read_symlink, + GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_ext2_iterate_dir (fdiro, iterate); + grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx); fail: - if (fdiro != &data->diropen) + if (fdiro != &ctx.data->diropen) grub_free (fdiro); - grub_free (data); + grub_free (ctx.data); grub_dl_unref (my_mod); diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 119fc945f..e84f6c672 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -26,7 +26,11 @@ #include #include #include +#ifndef MODE_EXFAT #include +#else +#include +#endif #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -60,33 +64,16 @@ enum }; #ifdef MODE_EXFAT -struct grub_exfat_bpb -{ - grub_uint8_t jmp_boot[3]; - grub_uint8_t oem_name[8]; - grub_uint8_t mbz[53]; - grub_uint64_t num_hidden_sectors; - grub_uint64_t num_total_sectors; - grub_uint32_t num_reserved_sectors; - grub_uint32_t sectors_per_fat; - grub_uint32_t cluster_offset; - grub_uint32_t cluster_count; - grub_uint32_t root_cluster; - grub_uint32_t num_serial; - grub_uint16_t fs_revision; - grub_uint16_t volume_flags; - grub_uint8_t bytes_per_sector_shift; - grub_uint8_t sectors_per_cluster_shift; - grub_uint8_t num_fats; - grub_uint8_t num_ph_drive; - grub_uint8_t reserved[8]; -} __attribute__ ((packed)); typedef struct grub_exfat_bpb grub_current_fat_bpb_t; #else typedef struct grub_fat_bpb grub_current_fat_bpb_t; #endif #ifdef MODE_EXFAT +enum + { + FLAG_CONTIGUOUS = 2 + }; struct grub_fat_dir_entry { grub_uint8_t entry_type; @@ -135,7 +122,7 @@ struct grub_fat_dir_node grub_uint64_t file_size; grub_uint64_t valid_size; int have_stream; - int is_label; + int is_contiguous; }; typedef struct grub_fat_dir_node grub_fat_dir_node_t; @@ -186,6 +173,8 @@ struct grub_fat_data #ifndef MODE_EXFAT grub_uint32_t root_sector; grub_uint32_t num_root_sectors; +#else + int is_contiguous; #endif int cluster_bits; @@ -336,13 +325,12 @@ grub_fat_mount (grub_disk_t disk) #ifdef MODE_EXFAT { /* exFAT. */ - grub_uint16_t flags = grub_le_to_cpu16 (bpb.volume_flags); - data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster); data->fat_size = 32; data->cluster_eof_mark = 0xffffffff; - if ((flags & 0x1) && bpb.num_fats > 1) + if ((bpb.volume_flags & grub_cpu_to_le16_compile_time (0x1)) + && bpb.num_fats > 1) data->fat_sector += data->sectors_per_fat; } #else @@ -443,6 +431,9 @@ grub_fat_mount (grub_disk_t disk) data->file_cluster = data->root_cluster; data->cur_cluster_num = ~0U; data->attr = GRUB_FAT_ATTR_DIRECTORY; +#ifdef MODE_EXFAT + data->is_contiguous = 0; +#endif return data; fail: @@ -454,8 +445,7 @@ grub_fat_mount (grub_disk_t disk) static grub_ssize_t grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t offset, grub_size_t len, char *buf) { grub_size_t size; @@ -480,6 +470,26 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, } #endif +#ifdef MODE_EXFAT + if (data->is_contiguous) + { + /* Read the data here. */ + sector = (data->cluster_sector + + ((data->file_cluster - 2) + << data->cluster_bits)); + + disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; + grub_disk_read (disk, sector + (offset >> GRUB_DISK_SECTOR_BITS), + offset & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); + disk->read_hook = 0; + if (grub_errno) + return -1; + + return len; + } +#endif + /* Calculate the logical cluster number and offset. */ logical_cluster_bits = (data->cluster_bits + GRUB_DISK_SECTOR_BITS); @@ -498,7 +508,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, { /* Find next cluster. */ grub_uint32_t next_cluster; - unsigned long fat_offset; + grub_uint32_t fat_offset; switch (data->fat_size) { @@ -561,6 +571,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; grub_disk_read (disk, sector, offset, size, buf); disk->read_hook = 0; if (grub_errno) @@ -630,7 +641,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->offset += sizeof (dir); - if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (dir), + if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir), (char *) &dir) != sizeof (dir)) break; @@ -652,7 +663,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, { struct grub_fat_dir_entry sec; ctxt->offset += sizeof (sec); - if (grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (sec), (char *) &sec) != sizeof (sec)) break; @@ -669,6 +680,8 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->dir.file_size = grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size); ctxt->dir.have_stream = 1; + ctxt->dir.is_contiguous = !!(dir.type_specific.stream_extension.flags + & grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS)); break; case 0xc1: { @@ -729,7 +742,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->offset += sizeof (ctxt->dir); /* Read a directory entry. */ - if (grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (ctxt->dir), (char *) &ctxt->dir) != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0) @@ -844,8 +857,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, static char * grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, const char *path, const char *origpath, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { char *dirname, *dirp; int call_hook; @@ -905,7 +917,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, #endif if (*dirname == '\0' && call_hook) { - if (hook (ctxt.filename, &info)) + if (hook (ctxt.filename, &info, hook_data)) break; else continue; @@ -918,6 +930,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, #ifdef MODE_EXFAT data->file_size = ctxt.dir.file_size; data->file_cluster = ctxt.dir.first_cluster; + data->is_contiguous = ctxt.dir.is_contiguous; #else data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) @@ -926,7 +939,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, data->cur_cluster_num = ~0U; if (call_hook) - hook (ctxt.filename, &info); + hook (ctxt.filename, &info, hook_data); break; } @@ -946,9 +959,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, } static grub_err_t -grub_fat_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) { struct grub_fat_data *data = 0; grub_disk_t disk = device->disk; @@ -976,7 +988,7 @@ grub_fat_dir (grub_device_t device, const char *path, do { - p = grub_fat_find_dir (disk, data, p, path, hook); + p = grub_fat_find_dir (disk, data, p, path, hook, hook_data); } while (p && grub_errno == GRUB_ERR_NONE); @@ -1004,7 +1016,7 @@ grub_fat_open (grub_file_t file, const char *name) do { - p = grub_fat_find_dir (file->device->disk, data, p, name, 0); + p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0); if (grub_errno != GRUB_ERR_NONE) goto fail; } @@ -1033,7 +1045,8 @@ grub_fat_open (grub_file_t file, const char *name) static grub_ssize_t grub_fat_read (grub_file_t file, char *buf, grub_size_t len) { - return grub_fat_read_data (file->device->disk, file->data, file->read_hook, + return grub_fat_read_data (file->device->disk, file->data, + file->read_hook, file->read_hook_data, file->offset, len, buf); } @@ -1066,7 +1079,7 @@ grub_fat_label (grub_device_t device, char **label) { offset += sizeof (dir); - if (grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (disk, data, 0, 0, offset, sizeof (dir), (char *) &dir) != sizeof (dir)) break; @@ -1178,6 +1191,29 @@ grub_fat_uuid (grub_device_t device, char **uuid) return grub_errno; } +#ifdef GRUB_UTIL +#ifndef MODE_EXFAT +grub_disk_addr_t +grub_fat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn) +#else +grub_disk_addr_t + grub_exfat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn) +#endif +{ + grub_disk_addr_t ret; + struct grub_fat_data *data; + data = grub_fat_mount (disk); + if (!data) + return 0; + ret = data->cluster_sector; + + *sec_per_lcn = 1ULL << data->cluster_bits; + + grub_free (data); + return ret; +} +#endif + static struct grub_fs grub_fat_fs = { #ifdef MODE_EXFAT diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index 21a72de84..42bd542bb 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -27,184 +27,193 @@ GRUB_MOD_LICENSE ("GPLv3+"); +typedef int (*iterate_dir_func) (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, + void *data); +typedef char *(*read_symlink_func) (grub_fshelp_node_t node); + +/* Context for grub_fshelp_find_file. */ +struct grub_fshelp_find_file_ctx +{ + const char *path; + grub_fshelp_node_t rootnode, currroot, currnode, oldnode; + enum grub_fshelp_filetype foundtype; + int symlinknest; + const char *name; + const char *next; + enum grub_fshelp_filetype type; +}; + +/* Helper for find_file_iter. */ +static void +free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx) +{ + if (node != ctx->rootnode && node != ctx->currroot) + grub_free (node); +} + +/* Helper for grub_fshelp_find_file. */ +static int +find_file_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_fshelp_find_file_ctx *ctx = data; + + if (filetype == GRUB_FSHELP_UNKNOWN || + ((filetype & GRUB_FSHELP_CASE_INSENSITIVE) + ? grub_strncasecmp (ctx->name, filename, ctx->next - ctx->name) + : grub_strncmp (ctx->name, filename, ctx->next - ctx->name)) + || filename[ctx->next - ctx->name]) + { + grub_free (node); + return 0; + } + + /* The node is found, stop iterating over the nodes. */ + ctx->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; + ctx->oldnode = ctx->currnode; + ctx->currnode = node; + + return 1; +} + +static grub_err_t +find_file (const char *currpath, grub_fshelp_node_t currroot, + grub_fshelp_node_t *currfound, + iterate_dir_func iterate_dir, read_symlink_func read_symlink, + struct grub_fshelp_find_file_ctx *ctx) +{ + ctx->currroot = currroot; + ctx->name = currpath; + ctx->type = GRUB_FSHELP_DIR; + ctx->currnode = currroot; + ctx->oldnode = currroot; + + for (;;) + { + int found; + + /* Remove all leading slashes. */ + while (*ctx->name == '/') + ctx->name++; + + /* Found the node! */ + if (! *ctx->name) + { + *currfound = ctx->currnode; + ctx->foundtype = ctx->type; + return 0; + } + + /* Extract the actual part from the pathname. */ + for (ctx->next = ctx->name; *ctx->next && *ctx->next != '/'; ctx->next++); + + /* At this point it is expected that the current node is a + directory, check if this is true. */ + if (ctx->type != GRUB_FSHELP_DIR) + { + free_node (ctx->currnode, ctx); + ctx->currnode = 0; + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + } + + /* Iterate over the directory. */ + found = iterate_dir (ctx->currnode, find_file_iter, ctx); + if (! found) + { + free_node (ctx->currnode, ctx); + ctx->currnode = 0; + if (grub_errno) + return grub_errno; + + break; + } + + /* Read in the symlink and follow it. */ + if (ctx->type == GRUB_FSHELP_SYMLINK) + { + char *symlink; + const char *next; + + /* Test if the symlink does not loop. */ + if (++ctx->symlinknest == 8) + { + free_node (ctx->currnode, ctx); + free_node (ctx->oldnode, ctx); + ctx->currnode = 0; + ctx->oldnode = 0; + return grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); + } + + symlink = read_symlink (ctx->currnode); + free_node (ctx->currnode, ctx); + ctx->currnode = 0; + + if (!symlink) + { + free_node (ctx->oldnode, ctx); + ctx->oldnode = 0; + return grub_errno; + } + + /* The symlink is an absolute path, go back to the root inode. */ + if (symlink[0] == '/') + { + free_node (ctx->oldnode, ctx); + ctx->oldnode = ctx->rootnode; + } + + /* Lookup the node the symlink points to. */ + next = ctx->next; + find_file (symlink, ctx->oldnode, &ctx->currnode, + iterate_dir, read_symlink, ctx); + ctx->next = next; + ctx->type = ctx->foundtype; + grub_free (symlink); + + if (grub_errno) + { + free_node (ctx->oldnode, ctx); + ctx->oldnode = 0; + return grub_errno; + } + } + + if (ctx->oldnode != ctx->currnode) + { + free_node (ctx->oldnode, ctx); + ctx->oldnode = 0; + } + + ctx->name = ctx->next; + } + + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), + ctx->path); +} + /* Lookup the node PATH. The node ROOTNODE describes the root of the directory tree. The node found is returned in FOUNDNODE, which is either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to iterate over all directory entries in the current node. READ_SYMLINK is used to read the symlink if a node is a symlink. EXPECTTYPE is the type node that is expected by the called, an - error is generated if the node is not of the expected type. Make - sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required - because GCC has a nasty bug when using regparm=3. */ + error is generated if the node is not of the expected type. */ grub_err_t grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, grub_fshelp_node_t *foundnode, - int (*iterate_dir) (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR (*hook) - (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)), - char *(*read_symlink) (grub_fshelp_node_t node), + iterate_dir_func iterate_dir, + read_symlink_func read_symlink, enum grub_fshelp_filetype expecttype) { + struct grub_fshelp_find_file_ctx ctx = { + .path = path, + .rootnode = rootnode, + .foundtype = GRUB_FSHELP_DIR, + .symlinknest = 0 + }; grub_err_t err; - enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR; - int symlinknest = 0; - - auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, - grub_fshelp_node_t currroot, - grub_fshelp_node_t *currfound); - - grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, - grub_fshelp_node_t currroot, - grub_fshelp_node_t *currfound) - { - char fpath[grub_strlen (currpath) + 1]; - char *name = fpath; - char *next; - enum grub_fshelp_filetype type = GRUB_FSHELP_DIR; - grub_fshelp_node_t currnode = currroot; - grub_fshelp_node_t oldnode = currroot; - - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - auto void free_node (grub_fshelp_node_t node); - - void free_node (grub_fshelp_node_t node) - { - if (node != rootnode && node != currroot) - grub_free (node); - } - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - if (filetype == GRUB_FSHELP_UNKNOWN || - (grub_strcmp (name, filename) && - (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) || - grub_strcasecmp (name, filename)))) - { - grub_free (node); - return 0; - } - - /* The node is found, stop iterating over the nodes. */ - type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; - oldnode = currnode; - currnode = node; - - return 1; - } - - grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1); - - /* Remove all leading slashes. */ - while (*name == '/') - name++; - - if (! *name) - { - *currfound = currnode; - return 0; - } - - for (;;) - { - int found; - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) - { - /* Remove all leading slashes. */ - while (*next == '/') - *(next++) = '\0'; - } - - /* At this point it is expected that the current node is a - directory, check if this is true. */ - if (type != GRUB_FSHELP_DIR) - { - free_node (currnode); - currnode = 0; - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - } - - /* Iterate over the directory. */ - found = iterate_dir (currnode, iterate); - if (! found) - { - free_node (currnode); - currnode = 0; - if (grub_errno) - return grub_errno; - - break; - } - - /* Read in the symlink and follow it. */ - if (type == GRUB_FSHELP_SYMLINK) - { - char *symlink; - - /* Test if the symlink does not loop. */ - if (++symlinknest == 8) - { - free_node (currnode); - free_node (oldnode); - currnode = 0; - return grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - } - - symlink = read_symlink (currnode); - free_node (currnode); - currnode = 0; - - if (!symlink) - { - free_node (oldnode); - return grub_errno; - } - - /* The symlink is an absolute path, go back to the root inode. */ - if (symlink[0] == '/') - { - free_node (oldnode); - oldnode = rootnode; - } - - /* Lookup the node the symlink points to. */ - find_file (symlink, oldnode, &currnode); - type = foundtype; - grub_free (symlink); - - if (grub_errno) - { - free_node (oldnode); - return grub_errno; - } - } - - if (oldnode != currnode) - free_node (oldnode); - - /* Found the node! */ - if (! next || *next == '\0') - { - *currfound = currnode; - foundtype = type; - return 0; - } - - name = next; - } - - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - } if (!path || path[0] != '/') { @@ -212,14 +221,14 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, return grub_errno; } - err = find_file (path, rootnode, foundnode); + err = find_file (path, rootnode, foundnode, iterate_dir, read_symlink, &ctx); if (err) return err; /* Check if the node that was found was of the expected type. */ - if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype) + if (expecttype == GRUB_FSHELP_REG && ctx.foundtype != expecttype) return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype) + else if (expecttype == GRUB_FSHELP_DIR && ctx.foundtype != expecttype) return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return 0; @@ -227,14 +236,13 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF, beginning with the block POS. READ_HOOK should be set before - reading a block from the file. GET_BLOCK is used to translate file - blocks to disk blocks. The file is FILESIZE bytes big and the + reading a block from the file. READ_HOOK_DATA is passed through as + the DATA argument to READ_HOOK. GET_BLOCK is used to translate + file blocks to disk blocks. The file is FILESIZE bytes big and the blocks have a size of LOG2BLOCKSIZE (in log2). */ grub_ssize_t grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf, grub_disk_addr_t (*get_block) (grub_fshelp_node_t node, grub_disk_addr_t block), @@ -286,6 +294,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, if (blknr) { disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; grub_disk_read (disk, blknr + blocks_start, skipfirst, blockend, buf); @@ -301,24 +310,3 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, return len; } - -unsigned int -grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow) -{ - int mod; - - *pow = 0; - while (blksize > 1) - { - mod = blksize - ((blksize >> 1) << 1); - blksize >>= 1; - - /* Check if it really is a power of two. */ - if (mod) - return grub_error (GRUB_ERR_BAD_NUMBER, - "the blocksize is not a power of two"); - (*pow)++; - } - - return GRUB_ERR_NONE; -} diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 0a249ccb8..25414a5c5 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -161,15 +161,15 @@ struct grub_hfs_filerec struct grub_hfs_record { void *key; - int keylen; + grub_size_t keylen; void *data; - int datalen; + grub_size_t datalen; }; static grub_dl_t my_mod; static int grub_hfs_find_node (struct grub_hfs_data *, char *, - grub_uint32_t, int, char *, int); + grub_uint32_t, int, char *, grub_size_t); /* Find block BLOCK of the file FILE in the mounted UFS filesystem DATA. The first 3 extents are described by DAT. If cache is set, @@ -243,17 +243,17 @@ grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat, POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), - grub_off_t pos, grub_size_t len, char *buf) + grub_disk_read_hook_t read_hook, void *read_hook_data, + grub_uint32_t pos, grub_size_t len, char *buf) { grub_off_t i; grub_off_t blockcnt; - blockcnt = grub_divmod64 (((len + pos) - + data->blksz - 1), data->blksz, 0); + /* Files are at most 2G/4G - 1 bytes on hfs. Avoid 64-bit division. + Moreover len > 0 as checked in upper layer. */ + blockcnt = (len + pos - 1) / data->blksz + 1; - for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++) + for (i = pos / data->blksz; i < blockcnt; i++) { grub_disk_addr_t blknr; grub_off_t blockoff; @@ -261,7 +261,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, int skipfirst = 0; - grub_divmod64 (pos, data->blksz, &blockoff); + blockoff = pos % data->blksz; blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) @@ -270,7 +270,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, /* Last block. */ if (i == blockcnt - 1) { - grub_divmod64 ((len + pos), data->blksz, &blockend); + blockend = (len + pos) % data->blksz; /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) @@ -278,7 +278,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, } /* First block. */ - if (i == grub_divmod64 (pos, data->blksz, 0)) + if (i == pos / data->blksz) { skipfirst = blockoff; blockend -= skipfirst; @@ -289,6 +289,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, if (blknr) { data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, blknr, skipfirst, blockend, buf); data->disk->read_hook = 0; @@ -396,8 +397,8 @@ grub_hfs_mount (grub_disk_t disk) /* Compare the K1 and K2 catalog file keys using HFS character ordering. */ static int -grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1, - struct grub_hfs_catalog_key *k2) +grub_hfs_cmp_catkeys (const struct grub_hfs_catalog_key *k1, + const struct grub_hfs_catalog_key *k2) { /* Taken from hfsutils 3.2.6 and converted to a readable form */ static const unsigned char hfs_charorder[256] = { @@ -640,8 +641,8 @@ grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1, /* Compare the K1 and K2 extent overflow file keys. */ static int -grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1, - struct grub_hfs_extent_key *k2) +grub_hfs_cmp_extkeys (const struct grub_hfs_extent_key *k1, + const struct grub_hfs_extent_key *k2) { int cmp = k1->forktype - k2->forktype; if (cmp == 0) @@ -660,16 +661,25 @@ grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1, static grub_err_t grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, int this, int (*node_hook) (struct grub_hfs_node *hnd, - struct grub_hfs_record *)) + struct grub_hfs_record *, + void *hook_arg), + void *hook_arg) { - int nodesize = type == 0 ? data->cat_size : data->ext_size; + grub_size_t nodesize = type == 0 ? data->cat_size : data->ext_size; - union + union node_union { struct grub_hfs_node node; - char rawnode[nodesize]; - grub_uint16_t offsets[nodesize / 2]; - } node; + char rawnode[0]; + grub_uint16_t offsets[0]; + } *node; + + if (nodesize < sizeof (struct grub_hfs_node)) + nodesize = sizeof (struct grub_hfs_node); + + node = grub_malloc (nodesize); + if (!node) + return grub_errno; do { @@ -686,15 +696,16 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, (type == 0) ? GRUB_HFS_CNID_CAT : GRUB_HFS_CNID_EXT, idx / (data->blksz / nodesize), 0); blk += (idx % (data->blksz / nodesize)); - if (grub_errno) - return grub_errno; - if (grub_disk_read (data->disk, blk, 0, - sizeof (node), &node)) - return grub_errno; + if (grub_errno || grub_disk_read (data->disk, blk, 0, + nodesize, node)) + { + grub_free (node); + return grub_errno; + } /* Iterate over all records in this node. */ - for (i = 0; i < grub_be_to_cpu16 (node.node.reccnt); i++) + for (i = 0; i < grub_be_to_cpu16 (node->node.reccnt); i++) { int pos = (nodesize >> 1) - 1 - i; struct pointer @@ -702,24 +713,77 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, grub_uint8_t keylen; grub_uint8_t key; } __attribute__ ((packed)) *pnt; - pnt = (struct pointer *) (grub_be_to_cpu16 (node.offsets[pos]) - + node.rawnode); + pnt = (struct pointer *) (grub_be_to_cpu16 (node->offsets[pos]) + + node->rawnode); struct grub_hfs_record rec = { &pnt->key, pnt->keylen, &pnt->key + pnt->keylen +(pnt->keylen + 1) % 2, - nodesize - grub_be_to_cpu16 (node.offsets[pos]) + nodesize - grub_be_to_cpu16 (node->offsets[pos]) - pnt->keylen - 1 }; - if (node_hook (&node.node, &rec)) - return 0; + if (node_hook (&node->node, &rec, hook_arg)) + { + grub_free (node); + return 0; + } } - idx = grub_be_to_cpu32 (node.node.next); + idx = grub_be_to_cpu32 (node->node.next); } while (idx && this); + grub_free (node); + return 0; +} + +struct grub_hfs_find_node_node_found_ctx +{ + int found; + int isleaf; + int done; + int type; + const char *key; + char *datar; + grub_size_t datalen; +}; + +static int +grub_hfs_find_node_node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec, + void *hook_arg) +{ + struct grub_hfs_find_node_node_found_ctx *ctx = hook_arg; + int cmp = 1; + + if (ctx->type == 0) + cmp = grub_hfs_cmp_catkeys (rec->key, (const void *) ctx->key); + else + cmp = grub_hfs_cmp_extkeys (rec->key, (const void *) ctx->key); + + /* If the key is smaller or equal to the current node, mark the + entry. In case of a non-leaf mode it will be used to lookup + the rest of the tree. */ + if (cmp <= 0) + ctx->found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); + else /* The key can not be found in the tree. */ + return 1; + + /* Check if this node is a leaf node. */ + if (hnd->type == GRUB_HFS_NODE_LEAF) + { + ctx->isleaf = 1; + + /* Found it!!!! */ + if (cmp == 0) + { + ctx->done = 1; + + grub_memcpy (ctx->datar, rec->data, + rec->datalen < ctx->datalen ? rec->datalen : ctx->datalen); + return 1; + } + } return 0; } @@ -731,64 +795,84 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, the data in DATAR with a maximum length of DATALEN. */ static int grub_hfs_find_node (struct grub_hfs_data *data, char *key, - grub_uint32_t idx, int type, char *datar, int datalen) + grub_uint32_t idx, int type, char *datar, grub_size_t datalen) { - int found = -1; - int isleaf = 0; - int done = 0; - - auto int node_found (struct grub_hfs_node *, struct grub_hfs_record *); - - int node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec) + struct grub_hfs_find_node_node_found_ctx ctx = { - int cmp = 1; - - if (type == 0) - cmp = grub_hfs_cmp_catkeys (rec->key, (void *) key); - else - cmp = grub_hfs_cmp_extkeys (rec->key, (void *) key); - - /* If the key is smaller or equal to the current node, mark the - entry. In case of a non-leaf mode it will be used to lookup - the rest of the tree. */ - if (cmp <= 0) - found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); - else /* The key can not be found in the tree. */ - return 1; - - /* Check if this node is a leaf node. */ - if (hnd->type == GRUB_HFS_NODE_LEAF) - { - isleaf = 1; - - /* Found it!!!! */ - if (cmp == 0) - { - done = 1; - - grub_memcpy (datar, rec->data, - rec->datalen < datalen ? rec->datalen : datalen); - return 1; - } - } - - return 0; - } + .found = -1, + .isleaf = 0, + .done = 0, + .type = type, + .key = key, + .datar = datar, + .datalen = datalen + }; do { - found = -1; + ctx.found = -1; - if (grub_hfs_iterate_records (data, type, idx, 0, node_found)) + if (grub_hfs_iterate_records (data, type, idx, 0, grub_hfs_find_node_node_found, &ctx)) return 0; - if (found == -1) + if (ctx.found == -1) return 0; - idx = found; - } while (! isleaf); + idx = ctx.found; + } while (! ctx.isleaf); - return done; + return ctx.done; +} + +struct grub_hfs_iterate_dir_node_found_ctx +{ + grub_uint32_t dir_be; + int found; + int isleaf; + grub_uint32_t next; + int (*hook) (struct grub_hfs_record *, void *hook_arg); + void *hook_arg; +}; + +static int +grub_hfs_iterate_dir_node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec, + void *hook_arg) +{ + struct grub_hfs_iterate_dir_node_found_ctx *ctx = hook_arg; + struct grub_hfs_catalog_key *ckey = rec->key; + + /* The lowest key possible with DIR as root directory. */ + const struct grub_hfs_catalog_key key = {0, ctx->dir_be, 0, ""}; + + if (grub_hfs_cmp_catkeys (rec->key, &key) <= 0) + ctx->found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); + + if (hnd->type == 0xFF && ckey->strlen > 0) + { + ctx->isleaf = 1; + ctx->next = grub_be_to_cpu32 (hnd->next); + + /* An entry was found. */ + if (ckey->parent_dir == ctx->dir_be) + return ctx->hook (rec, ctx->hook_arg); + } + + return 0; +} + +static int +grub_hfs_iterate_dir_it_dir (struct grub_hfs_node *hnd __attribute ((unused)), + struct grub_hfs_record *rec, + void *hook_arg) +{ + struct grub_hfs_catalog_key *ckey = rec->key; + struct grub_hfs_iterate_dir_node_found_ctx *ctx = hook_arg; + + /* Stop when the entries do not match anymore. */ + if (ckey->parent_dir != ctx->dir_be) + return 1; + + return ctx->hook (rec, ctx->hook_arg); } @@ -797,70 +881,35 @@ grub_hfs_find_node (struct grub_hfs_data *data, char *key, call HOOK. */ static grub_err_t grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, - unsigned int dir, int (*hook) (struct grub_hfs_record *)) + grub_uint32_t dir, int (*hook) (struct grub_hfs_record *, void *hook_arg), + void *hook_arg) { - int found = -1; - int isleaf = 0; - int next = 0; - - /* The lowest key possible with DIR as root directory. */ - struct grub_hfs_catalog_key key = {0, grub_cpu_to_be32 (dir), 0, ""}; - - auto int node_found (struct grub_hfs_node *, struct grub_hfs_record *); - auto int it_dir (struct grub_hfs_node * __attribute ((unused)), - struct grub_hfs_record *); - - - int node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec) - { - struct grub_hfs_catalog_key *ckey = rec->key; - - if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0) - found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); - - if (hnd->type == 0xFF && ckey->strlen > 0) - { - isleaf = 1; - next = grub_be_to_cpu32 (hnd->next); - - /* An entry was found. */ - if (grub_be_to_cpu32 (ckey->parent_dir) == dir) - return hook (rec); - } - - return 0; - } - - int it_dir (struct grub_hfs_node *hnd __attribute ((unused)), - struct grub_hfs_record *rec) - { - struct grub_hfs_catalog_key *ckey = rec->key; - struct grub_hfs_catalog_key *origkey = &key; - - /* Stop when the entries do not match anymore. */ - if (grub_be_to_cpu32 (ckey->parent_dir) - != grub_be_to_cpu32 ((origkey)->parent_dir)) - return 1; - - return hook (rec); - } + struct grub_hfs_iterate_dir_node_found_ctx ctx = + { + .dir_be = grub_cpu_to_be32 (dir), + .found = -1, + .isleaf = 0, + .next = 0, + .hook = hook, + .hook_arg = hook_arg + }; do { - found = -1; + ctx.found = -1; - if (grub_hfs_iterate_records (data, 0, root_idx, 0, node_found)) + if (grub_hfs_iterate_records (data, 0, root_idx, 0, grub_hfs_iterate_dir_node_found, &ctx)) return grub_errno; - if (found == -1) + if (ctx.found == -1) return 0; - root_idx = found; - } while (! isleaf); + root_idx = ctx.found; + } while (! ctx.isleaf); /* If there was a matching record in this leaf node, continue the iteration until the last record was found. */ - grub_hfs_iterate_records (data, 0, next, 1, it_dir); + grub_hfs_iterate_records (data, 0, ctx.next, 1, grub_hfs_iterate_dir_it_dir, &ctx); return grub_errno; } @@ -1148,57 +1197,66 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, return grub_errno; } +struct grub_hfs_dir_hook_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +static int +grub_hfs_dir_hook (struct grub_hfs_record *rec, void *hook_arg) +{ + struct grub_hfs_dir_hook_ctx *ctx = hook_arg; + struct grub_hfs_dirrec *drec = rec->data; + struct grub_hfs_filerec *frec = rec->data; + struct grub_hfs_catalog_key *ckey = rec->key; + char fname[sizeof (ckey->str) * MAX_UTF8_PER_MAC_ROMAN + 1]; + struct grub_dirhook_info info; + grub_size_t len; + + grub_memset (fname, 0, sizeof (fname)); + + grub_memset (&info, 0, sizeof (info)); + + len = ckey->strlen; + if (len > sizeof (ckey->str)) + len = sizeof (ckey->str); + macroman_to_utf8 (fname, ckey->str, len, 1); + + info.case_insensitive = 1; + + if (drec->type == GRUB_HFS_FILETYPE_DIR) + { + info.dir = 1; + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; + return ctx->hook (fname, &info, ctx->hook_data); + } + if (frec->type == GRUB_HFS_FILETYPE_FILE) + { + info.dir = 0; + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; + return ctx->hook (fname, &info, ctx->hook_data); + } + + return 0; +} static grub_err_t -grub_hfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) { int inode; - auto int dir_hook (struct grub_hfs_record *rec); - - int dir_hook (struct grub_hfs_record *rec) - { - struct grub_hfs_dirrec *drec = rec->data; - struct grub_hfs_filerec *frec = rec->data; - struct grub_hfs_catalog_key *ckey = rec->key; - char fname[sizeof (ckey->str) * MAX_UTF8_PER_MAC_ROMAN + 1]; - struct grub_dirhook_info info; - grub_size_t len; - - grub_memset (fname, 0, sizeof (fname)); - - grub_memset (&info, 0, sizeof (info)); - - len = ckey->strlen; - if (len > sizeof (ckey->str)) - len = sizeof (ckey->str); - macroman_to_utf8 (fname, ckey->str, len, 1); - - info.case_insensitive = 1; - - if (drec->type == GRUB_HFS_FILETYPE_DIR) - { - info.dir = 1; - info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; - return hook (fname, &info); - } - if (frec->type == GRUB_HFS_FILETYPE_FILE) - { - info.dir = 0; - info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; - return hook (fname, &info); - } - - return 0; - } - struct grub_hfs_data *data; struct grub_hfs_filerec frec; + struct grub_hfs_dir_hook_ctx ctx = + { + .hook = hook, + .hook_data = hook_data + }; grub_dl_ref (my_mod); @@ -1216,7 +1274,7 @@ grub_hfs_dir (grub_device_t device, const char *path, goto fail; } - grub_hfs_iterate_dir (data, data->cat_root, inode, dir_hook); + grub_hfs_iterate_dir (data, data->cat_root, inode, grub_hfs_dir_hook, &ctx); fail: grub_free (data); @@ -1270,7 +1328,8 @@ grub_hfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hfs_data *data = (struct grub_hfs_data *) file->data; - return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf); + return grub_hfs_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 981246475..a119c7ace 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -19,6 +19,7 @@ /* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ +#define grub_fshelp_node grub_hfsplus_file #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -36,42 +38,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_HFSPLUSX_MAGIC 0x4858 #define GRUB_HFSPLUS_SBLOCK 2 -/* A HFS+ extent. */ -struct grub_hfsplus_extent -{ - /* The first block of a file on disk. */ - grub_uint32_t start; - /* The amount of blocks described by this extent. */ - grub_uint32_t count; -} __attribute__ ((packed)); - -/* The descriptor of a fork. */ -struct grub_hfsplus_forkdata -{ - grub_uint64_t size; - grub_uint32_t clumpsize; - grub_uint32_t blocks; - struct grub_hfsplus_extent extents[8]; -} __attribute__ ((packed)); - -/* The HFS+ Volume Header. */ -struct grub_hfsplus_volheader -{ - grub_uint16_t magic; - grub_uint16_t version; - grub_uint32_t attributes; - grub_uint8_t unused1[12]; - grub_uint32_t utime; - grub_uint8_t unused2[16]; - grub_uint32_t blksize; - grub_uint8_t unused3[60]; - grub_uint64_t num_serial; - struct grub_hfsplus_forkdata allocations_file; - struct grub_hfsplus_forkdata extents_file; - struct grub_hfsplus_forkdata catalog_file; - struct grub_hfsplus_forkdata attrib_file; - struct grub_hfsplus_forkdata startup_file; -} __attribute__ ((packed)); /* The type of node. */ enum grub_hfsplus_btnode_type @@ -82,16 +48,6 @@ enum grub_hfsplus_btnode_type GRUB_HFSPLUS_BTNODE_TYPE_MAP = 2, }; -struct grub_hfsplus_btnode -{ - grub_uint32_t next; - grub_uint32_t prev; - grub_int8_t type; - grub_uint8_t height; - grub_uint16_t count; - grub_uint16_t unused; -} __attribute__ ((packed)); - /* The header of a HFS+ B+ Tree. */ struct grub_hfsplus_btheader { @@ -111,35 +67,6 @@ struct grub_hfsplus_btheader grub_uint32_t attributes; } __attribute__ ((packed)); -/* The on disk layout of a catalog key. */ -struct grub_hfsplus_catkey -{ - grub_uint16_t keylen; - grub_uint32_t parent; - grub_uint16_t namelen; - grub_uint16_t name[30]; -} __attribute__ ((packed)); - -/* The on disk layout of an extent overflow file key. */ -struct grub_hfsplus_extkey -{ - grub_uint16_t keylen; - grub_uint8_t type; - grub_uint8_t unused; - grub_uint32_t fileid; - grub_uint32_t start; -} __attribute__ ((packed)); - -struct grub_hfsplus_key -{ - union - { - struct grub_hfsplus_extkey extkey; - struct grub_hfsplus_catkey catkey; - grub_uint16_t keylen; - }; -} __attribute__ ((packed)); - struct grub_hfsplus_catfile { grub_uint16_t type; @@ -162,9 +89,13 @@ struct grub_hfsplus_catfile #define GRUB_HFSPLUS_FILEMODE_SYMLINK 0120000 /* Some pre-defined file IDs. */ -#define GRUB_HFSPLUS_FILEID_ROOTDIR 2 -#define GRUB_HFSPLUS_FILEID_OVERFLOW 3 -#define GRUB_HFSPLUS_FILEID_CATALOG 4 +enum + { + GRUB_HFSPLUS_FILEID_ROOTDIR = 2, + GRUB_HFSPLUS_FILEID_OVERFLOW = 3, + GRUB_HFSPLUS_FILEID_CATALOG = 4, + GRUB_HFSPLUS_FILEID_ATTR = 8 + }; enum grub_hfsplus_filetype { @@ -177,98 +108,15 @@ enum grub_hfsplus_filetype #define GRUB_HFSPLUSX_BINARYCOMPARE 0xBC #define GRUB_HFSPLUSX_CASEFOLDING 0xCF -/* Internal representation of a catalog key. */ -struct grub_hfsplus_catkey_internal -{ - grub_uint32_t parent; - const grub_uint16_t *name; - grub_size_t namelen; -}; - -/* Internal representation of an extent overflow key. */ -struct grub_hfsplus_extkey_internal -{ - grub_uint32_t fileid; - grub_uint8_t type; - grub_uint32_t start; -}; - -struct grub_hfsplus_key_internal -{ - union - { - struct grub_hfsplus_extkey_internal extkey; - struct grub_hfsplus_catkey_internal catkey; - }; -}; - - - -struct grub_fshelp_node -{ - struct grub_hfsplus_data *data; - struct grub_hfsplus_extent extents[8]; - grub_uint64_t size; - grub_uint32_t fileid; - grub_int32_t mtime; -}; - -struct grub_hfsplus_btree -{ - grub_uint32_t root; - grub_size_t nodesize; - - /* Catalog file node. */ - struct grub_fshelp_node file; -}; - -/* Information about a "mounted" HFS+ filesystem. */ -struct grub_hfsplus_data -{ - struct grub_hfsplus_volheader volheader; - grub_disk_t disk; - - unsigned int log2blksize; - - struct grub_hfsplus_btree catalog_tree; - struct grub_hfsplus_btree extoverflow_tree; - - struct grub_fshelp_node dirroot; - struct grub_fshelp_node opened_file; - - /* This is the offset into the physical disk for an embedded HFS+ - filesystem (one inside a plain HFS wrapper). */ - grub_disk_addr_t embedded_offset; - int case_sensitive; -}; - static grub_dl_t my_mod; -/* Return the offset of the record with the index INDEX, in the node - NODE which is part of the B+ tree BTREE. */ -static inline grub_off_t -grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_btnode *node, int index) -{ - char *cnode = (char *) node; - void *recptr; - recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); - return grub_be_to_cpu16 (grub_get_unaligned16 (recptr)); -} - -/* Return a pointer to the record with the index INDEX, in the node - NODE which is part of the B+ tree BTREE. */ -static inline struct grub_hfsplus_key * -grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_btnode *node, int index) -{ - char *cnode = (char *) node; - grub_off_t offset; - offset = grub_hfsplus_btree_recoffset (btree, node, index); - return (struct grub_hfsplus_key *) &cnode[offset]; -} +grub_err_t (*grub_hfsplus_open_compressed) (struct grub_fshelp_node *node); +grub_ssize_t (*grub_hfsplus_read_compressed) (struct grub_hfsplus_file *node, + grub_off_t pos, + grub_size_t len, + char *buf); /* Find the extent that points to FILEBLOCK. If it is not in one of the 8 extents described by EXTENT, return -1. In that case set @@ -292,14 +140,6 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent, return 0xffffffffffffffffULL; } -static grub_err_t -grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_key_internal *key, - int (*compare_keys) (struct grub_hfsplus_key *keya, - struct grub_hfsplus_key_internal *keyb), - struct grub_hfsplus_btnode **matchnode, - grub_off_t *keyoffset); - static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb); @@ -310,7 +150,8 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_hfsplus_btnode *nnode = 0; grub_disk_addr_t blksleft = fileblock; - struct grub_hfsplus_extent *extents = &node->extents[0]; + struct grub_hfsplus_extent *extents = node->compressed + ? &node->resource_extents[0] : &node->extents[0]; while (1) { @@ -344,10 +185,11 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) extoverflow.extkey.fileid = node->fileid; extoverflow.extkey.type = 0; extoverflow.extkey.start = fileblock - blksleft; - + extoverflow.extkey.type = node->compressed ? 0xff : 0; if (grub_hfsplus_btree_search (&node->data->extoverflow_tree, &extoverflow, - grub_hfsplus_cmp_extkey, &nnode, &ptr)) + grub_hfsplus_cmp_extkey, &nnode, &ptr) + || !nnode) { grub_error (GRUB_ERR_READ_ERROR, "no block found for the file id 0x%x and the block offset 0x%x", @@ -373,13 +215,13 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) /* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ -static grub_ssize_t +grub_ssize_t grub_hfsplus_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_hfsplus_read_block, node->size, node->data->log2blksize - GRUB_DISK_SECTOR_BITS, @@ -460,15 +302,27 @@ grub_hfsplus_mount (grub_disk_t disk) /* Make a new node for the catalog tree. */ data->catalog_tree.file.data = data; data->catalog_tree.file.fileid = GRUB_HFSPLUS_FILEID_CATALOG; + data->catalog_tree.file.compressed = 0; grub_memcpy (&data->catalog_tree.file.extents, data->volheader.catalog_file.extents, sizeof data->volheader.catalog_file.extents); data->catalog_tree.file.size = grub_be_to_cpu64 (data->volheader.catalog_file.size); + data->attr_tree.file.data = data; + data->attr_tree.file.fileid = GRUB_HFSPLUS_FILEID_ATTR; + grub_memcpy (&data->attr_tree.file.extents, + data->volheader.attr_file.extents, + sizeof data->volheader.attr_file.extents); + + data->attr_tree.file.size = + grub_be_to_cpu64 (data->volheader.attr_file.size); + data->attr_tree.file.compressed = 0; + /* Make a new node for the extent overflow file. */ data->extoverflow_tree.file.data = data; data->extoverflow_tree.file.fileid = GRUB_HFSPLUS_FILEID_OVERFLOW; + data->extoverflow_tree.file.compressed = 0; grub_memcpy (&data->extoverflow_tree.file.extents, data->volheader.extents_file.extents, sizeof data->volheader.catalog_file.extents); @@ -477,7 +331,7 @@ grub_hfsplus_mount (grub_disk_t disk) grub_be_to_cpu64 (data->volheader.extents_file.size); /* Read the essential information about the trees. */ - if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, + if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) goto fail; @@ -487,20 +341,34 @@ grub_hfsplus_mount (grub_disk_t disk) data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) && (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE)); - if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) goto fail; data->extoverflow_tree.root = grub_be_to_cpu32 (header.root); - if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, 0, sizeof (node), (char *) &node) <= 0) goto fail; data->extoverflow_tree.root = grub_be_to_cpu32 (header.root); data->extoverflow_tree.nodesize = grub_be_to_cpu16 (header.nodesize); + if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0, + sizeof (struct grub_hfsplus_btnode), + sizeof (header), (char *) &header) <= 0) + { + grub_errno = 0; + data->attr_tree.root = 0; + data->attr_tree.nodesize = 0; + } + else + { + data->attr_tree.root = grub_be_to_cpu32 (header.root); + data->attr_tree.nodesize = grub_be_to_cpu16 (header.nodesize); + } + data->dirroot.data = data; data->dirroot.fileid = GRUB_HFSPLUS_FILEID_ROOTDIR; @@ -586,6 +454,12 @@ grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, return 1; if (extkey_a->type < extkey_b->type) return -1; + + if (extkey_a->type > extkey_b->type) + return +1; + + if (extkey_a->type < extkey_b->type) + return -1; akey = grub_be_to_cpu32 (extkey_a->start); if (akey > extkey_b->start) @@ -605,7 +479,7 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node) if (!symlink) return 0; - numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink); + numread = grub_hfsplus_read_file (node, 0, 0, 0, node->size, symlink); if (numread != (grub_ssize_t) node->size) { grub_free (symlink); @@ -620,7 +494,8 @@ static int grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *first_node, grub_disk_addr_t first_rec, - int (*hook) (void *record)) + int (*hook) (void *record, void *hook_arg), + void *hook_arg) { grub_disk_addr_t rec; grub_uint64_t saved_node = -1; @@ -633,7 +508,7 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, /* Iterate over all records in this node. */ for (rec = first_rec; rec < grub_be_to_cpu16 (first_node->count); rec++) { - if (hook (grub_hfsplus_btree_recptr (btree, first_node, rec))) + if (hook (grub_hfsplus_btree_recptr (btree, first_node, rec), hook_arg)) return 1; } @@ -649,7 +524,7 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, saved_node = first_node->next; node_count++; - if (grub_hfsplus_read_file (&btree->file, 0, + if (grub_hfsplus_read_file (&btree->file, 0, 0, (((grub_disk_addr_t) grub_be_to_cpu32 (first_node->next)) * btree->nodesize), @@ -667,7 +542,7 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, keys using the function COMPARE_KEYS. When a match is found, return the node in MATCHNODE and a pointer to the data in this node in KEYOFFSET. MATCHNODE should be freed by the caller. */ -static grub_err_t +grub_err_t grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, struct grub_hfsplus_key_internal *key, int (*compare_keys) (struct grub_hfsplus_key *keya, @@ -682,6 +557,12 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, grub_uint64_t save_node; grub_uint64_t node_count = 0; + if (!btree->nodesize) + { + *matchnode = 0; + return 0; + } + node = grub_malloc (btree->nodesize); if (! node) return grub_errno; @@ -702,7 +583,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, node_count++; /* Read a node. */ - if (grub_hfsplus_read_file (&btree->file, 0, + if (grub_hfsplus_read_file (&btree->file, 0, 0, (grub_disk_addr_t) currnode * (grub_disk_addr_t) btree->nodesize, btree->nodesize, (char *) node) <= 0) @@ -759,132 +640,150 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, { *matchnode = 0; grub_free (node); - return 1; + return 0; } } } -static int -grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) +struct list_nodes_ctx { - int ret = 0; + int ret; + grub_fshelp_node_t dir; + grub_fshelp_iterate_dir_hook_t hook; + void *hook_data; +}; - auto int list_nodes (void *record); - int list_nodes (void *record) +static int +list_nodes (void *record, void *hook_arg) +{ + struct grub_hfsplus_catkey *catkey; + char *filename; + int i; + struct grub_fshelp_node *node; + struct grub_hfsplus_catfile *fileinfo; + enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; + struct list_nodes_ctx *ctx = hook_arg; + + catkey = (struct grub_hfsplus_catkey *) record; + + fileinfo = + (struct grub_hfsplus_catfile *) ((char *) record + + grub_be_to_cpu16 (catkey->keylen) + + 2 + (grub_be_to_cpu16(catkey->keylen) + % 2)); + + /* Stop iterating when the last directory entry is found. */ + if (grub_be_to_cpu32 (catkey->parent) != ctx->dir->fileid) + return 1; + + /* Determine the type of the node that is found. */ + switch (fileinfo->type) { - struct grub_hfsplus_catkey *catkey; - char *filename; - int i; - struct grub_fshelp_node *node; - struct grub_hfsplus_catfile *fileinfo; - enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; + case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_REG): + { + int mode = (grub_be_to_cpu16 (fileinfo->mode) + & GRUB_HFSPLUS_FILEMODE_MASK); - catkey = (struct grub_hfsplus_catkey *) record; - - fileinfo = - (struct grub_hfsplus_catfile *) ((char *) record - + grub_be_to_cpu16 (catkey->keylen) - + 2 + (grub_be_to_cpu16(catkey->keylen) - % 2)); - - /* Stop iterating when the last directory entry is found. */ - if (grub_be_to_cpu32 (catkey->parent) != dir->fileid) - return 1; - - /* Determine the type of the node that is found. */ - switch (fileinfo->type) - { - case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_REG): - { - int mode = (grub_be_to_cpu16 (fileinfo->mode) - & GRUB_HFSPLUS_FILEMODE_MASK); - - if (mode == GRUB_HFSPLUS_FILEMODE_REG) - type = GRUB_FSHELP_REG; - else if (mode == GRUB_HFSPLUS_FILEMODE_SYMLINK) - type = GRUB_FSHELP_SYMLINK; - else - type = GRUB_FSHELP_UNKNOWN; - break; - } - case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR): - type = GRUB_FSHELP_DIR; - break; - case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR_THREAD): - if (dir->fileid == 2) - return 0; - node = grub_malloc (sizeof (*node)); - if (!node) - return 1; - node->data = dir->data; - node->mtime = 0; - node->size = 0; - node->fileid = grub_be_to_cpu32 (fileinfo->parentid); - - ret = hook ("..", GRUB_FSHELP_DIR, node); - return ret; - } - - if (type == GRUB_FSHELP_UNKNOWN) + if (mode == GRUB_HFSPLUS_FILEMODE_REG) + type = GRUB_FSHELP_REG; + else if (mode == GRUB_HFSPLUS_FILEMODE_SYMLINK) + type = GRUB_FSHELP_SYMLINK; + else + type = GRUB_FSHELP_UNKNOWN; + break; + } + case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR): + type = GRUB_FSHELP_DIR; + break; + case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR_THREAD): + if (ctx->dir->fileid == 2) return 0; - - filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) - * GRUB_MAX_UTF8_PER_UTF16 + 1); - if (! filename) - return 0; - - /* Make sure the byte order of the UTF16 string is correct. */ - for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) - { - catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); - - if (catkey->name[i] == '/') - catkey->name[i] = ':'; - - /* If the name is obviously invalid, skip this node. */ - if (catkey->name[i] == 0) - return 0; - } - - *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, - grub_be_to_cpu16 (catkey->namelen)) = '\0'; - - /* Restore the byte order to what it was previously. */ - for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) - { - if (catkey->name[i] == ':') - catkey->name[i] = '/'; - catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); - } - - /* hfs+ is case insensitive. */ - if (! dir->data->case_sensitive) - type |= GRUB_FSHELP_CASE_INSENSITIVE; - - /* A valid node is found; setup the node and call the - callback function. */ node = grub_malloc (sizeof (*node)); if (!node) return 1; - node->data = dir->data; + node->data = ctx->dir->data; + node->mtime = 0; + node->size = 0; + node->fileid = grub_be_to_cpu32 (fileinfo->parentid); - grub_memcpy (node->extents, fileinfo->data.extents, - sizeof (node->extents)); - node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; - node->size = grub_be_to_cpu64 (fileinfo->data.size); - node->fileid = grub_be_to_cpu32 (fileinfo->fileid); - - ret = hook (filename, type, node); - - grub_free (filename); - - return ret; + ctx->ret = ctx->hook ("..", GRUB_FSHELP_DIR, node, ctx->hook_data); + return ctx->ret; } + if (type == GRUB_FSHELP_UNKNOWN) + return 0; + + filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + * GRUB_MAX_UTF8_PER_UTF16 + 1); + if (! filename) + return 0; + + /* Make sure the byte order of the UTF16 string is correct. */ + for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) + { + catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); + + if (catkey->name[i] == '/') + catkey->name[i] = ':'; + + /* If the name is obviously invalid, skip this node. */ + if (catkey->name[i] == 0) + return 0; + } + + *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, + grub_be_to_cpu16 (catkey->namelen)) = '\0'; + + /* Restore the byte order to what it was previously. */ + for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) + { + if (catkey->name[i] == ':') + catkey->name[i] = '/'; + catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); + } + + /* hfs+ is case insensitive. */ + if (! ctx->dir->data->case_sensitive) + type |= GRUB_FSHELP_CASE_INSENSITIVE; + + /* A valid node is found; setup the node and call the + callback function. */ + node = grub_malloc (sizeof (*node)); + if (!node) + return 1; + node->data = ctx->dir->data; + node->compressed = 0; + node->cbuf = 0; + node->compress_index = 0; + + grub_memcpy (node->extents, fileinfo->data.extents, + sizeof (node->extents)); + grub_memcpy (node->resource_extents, fileinfo->resource.extents, + sizeof (node->resource_extents)); + node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; + node->size = grub_be_to_cpu64 (fileinfo->data.size); + node->resource_size = grub_be_to_cpu64 (fileinfo->resource.size); + node->fileid = grub_be_to_cpu32 (fileinfo->fileid); + + ctx->ret = ctx->hook (filename, type, node, ctx->hook_data); + + grub_free (filename); + + return ctx->ret; +} + +static int +grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + struct list_nodes_ctx ctx = + { + .ret = 0, + .dir = dir, + .hook = hook, + .hook_data = hook_data + }; + struct grub_hfsplus_key_internal intern; struct grub_hfsplus_btnode *node; grub_disk_addr_t ptr; @@ -895,7 +794,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, if (!fsnode) return 1; *fsnode = *dir; - if (hook (".", GRUB_FSHELP_DIR, fsnode)) + if (hook (".", GRUB_FSHELP_DIR, fsnode, hook_data)) return 1; } @@ -906,16 +805,17 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern, - grub_hfsplus_cmp_catkey, &node, &ptr)) + grub_hfsplus_cmp_catkey, &node, &ptr) + || !node) return 0; /* Iterate over all entries in this directory. */ grub_hfsplus_btree_iterate_node (&dir->data->catalog_tree, node, ptr, - list_nodes); + list_nodes, &ctx); grub_free (node); - return ret; + return ctx.ret; } /* Open a file named NAME and initialize FILE. */ @@ -937,6 +837,14 @@ grub_hfsplus_open (struct grub_file *file, const char *name) if (grub_errno) goto fail; + if (grub_hfsplus_open_compressed) + { + grub_err_t err; + err = grub_hfsplus_open_compressed (fdiro); + if (err) + goto fail; + } + file->size = fdiro->size; data->opened_file = *fdiro; grub_free (fdiro); @@ -960,7 +868,13 @@ grub_hfsplus_open (struct grub_file *file, const char *name) static grub_err_t grub_hfsplus_close (grub_file_t file) { - grub_free (file->data); + struct grub_hfsplus_data *data = + (struct grub_hfsplus_data *) file->data; + + grub_free (data->opened_file.cbuf); + grub_free (data->opened_file.compress_index); + + grub_free (data); grub_dl_unref (my_mod); @@ -974,36 +888,50 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hfsplus_data *data = (struct grub_hfsplus_data *) file->data; - return grub_hfsplus_read_file (&data->opened_file, file->read_hook, - file->offset, len, buf); + data->opened_file.file = file; + + if (grub_hfsplus_read_compressed && data->opened_file.compressed) + return grub_hfsplus_read_compressed (&data->opened_file, + file->offset, len, buf); + + return grub_hfsplus_read_file (&data->opened_file, + file->read_hook, file->read_hook_data, + file->offset, len, buf); +} + +/* Context for grub_hfsplus_dir. */ +struct grub_hfsplus_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_hfsplus_dir. */ +static int +grub_hfsplus_dir_iter (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_hfsplus_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = node->mtime; + info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); } static grub_err_t grub_hfsplus_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_hfsplus_dir_ctx ctx = { hook, hook_data }; struct grub_hfsplus_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = node->mtime; - info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_hfsplus_mount (device->disk); @@ -1018,7 +946,7 @@ grub_hfsplus_dir (grub_device_t device, const char *path, goto fail; /* Iterate over all entries in this directory. */ - grub_hfsplus_iterate_dir (fdiro, iterate); + grub_hfsplus_iterate_dir (fdiro, grub_hfsplus_dir_iter, &ctx); fail: if (data && fdiro != &data->dirroot) @@ -1055,7 +983,8 @@ grub_hfsplus_label (grub_device_t device, char **label) /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&data->catalog_tree, &intern, - grub_hfsplus_cmp_catkey_id, &node, &ptr)) + grub_hfsplus_cmp_catkey_id, &node, &ptr) + || !node) { grub_free (data); return 0; diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c new file mode 100644 index 000000000..59cb8cbc0 --- /dev/null +++ b/grub-core/fs/hfspluscomp.c @@ -0,0 +1,307 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* big-endian. */ +struct grub_hfsplus_compress_header1 +{ + grub_uint32_t header_size; + grub_uint32_t end_descriptor_offset; + grub_uint32_t total_compressed_size_including_seek_blocks_and_header2; + grub_uint32_t value_0x32; + grub_uint8_t unused[0xf0]; +} __attribute__ ((packed)); + +/* big-endian. */ +struct grub_hfsplus_compress_header2 +{ + grub_uint32_t total_compressed_size_including_seek_blocks; +} __attribute__ ((packed)); + +/* little-endian. */ +struct grub_hfsplus_compress_header3 +{ + grub_uint32_t num_chunks; +} __attribute__ ((packed)); + +/* little-endian. */ +struct grub_hfsplus_compress_block_descriptor +{ + grub_uint32_t offset; + grub_uint32_t size; +}; + +struct grub_hfsplus_compress_end_descriptor +{ + grub_uint8_t always_the_same[50]; +} __attribute__ ((packed)); + +struct grub_hfsplus_attr_header +{ + grub_uint8_t unused[3]; + grub_uint8_t type; + grub_uint32_t unknown[1]; + grub_uint64_t size; +} __attribute__ ((packed)); + +struct grub_hfsplus_compress_attr +{ + grub_uint32_t magic; + grub_uint32_t type; + grub_uint32_t uncompressed_inline_size; + grub_uint32_t always_0; +} __attribute__ ((packed)); + +enum + { + HFSPLUS_COMPRESSION_INLINE = 3, + HFSPLUS_COMPRESSION_RESOURCE = 4 + }; + +static int +grub_hfsplus_cmp_attrkey (struct grub_hfsplus_key *keya, + struct grub_hfsplus_key_internal *keyb) +{ + struct grub_hfsplus_attrkey *attrkey_a = &keya->attrkey; + struct grub_hfsplus_attrkey_internal *attrkey_b = &keyb->attrkey; + grub_uint32_t aparent = grub_be_to_cpu32 (attrkey_a->cnid); + grub_size_t len; + int diff; + + if (aparent > attrkey_b->cnid) + return 1; + if (aparent < attrkey_b->cnid) + return -1; + + len = grub_be_to_cpu16 (attrkey_a->namelen); + if (len > attrkey_b->namelen) + len = attrkey_b->namelen; + /* Since it's big-endian memcmp gives the same result as manually comparing + uint16_t but may be faster. */ + diff = grub_memcmp (attrkey_a->name, attrkey_b->name, + len * sizeof (attrkey_a->name[0])); + if (diff == 0) + diff = grub_be_to_cpu16 (attrkey_a->namelen) - attrkey_b->namelen; + return diff; +} + +#define HFSPLUS_COMPRESS_BLOCK_SIZE 65536 + +static grub_ssize_t +hfsplus_read_compressed_real (struct grub_hfsplus_file *node, + grub_off_t pos, grub_size_t len, char *buf) +{ + char *tmp_buf = 0; + grub_size_t len0 = len; + + if (node->compressed == 1) + { + grub_memcpy (buf, node->cbuf + pos, len); + if (grub_file_progress_hook && node->file) + grub_file_progress_hook (0, 0, len, node->file); + return len; + } + + while (len) + { + grub_uint32_t block = pos / HFSPLUS_COMPRESS_BLOCK_SIZE; + grub_size_t curlen = HFSPLUS_COMPRESS_BLOCK_SIZE + - (pos % HFSPLUS_COMPRESS_BLOCK_SIZE); + + if (curlen > len) + curlen = len; + + if (node->cbuf_block != block) + { + grub_uint32_t sz = grub_le_to_cpu32 (node->compress_index[block].size); + grub_size_t ts; + if (!tmp_buf) + tmp_buf = grub_malloc (HFSPLUS_COMPRESS_BLOCK_SIZE); + if (!tmp_buf) + return -1; + if (grub_hfsplus_read_file (node, 0, 0, + grub_le_to_cpu32 (node->compress_index[block].start) + 0x104, + sz, tmp_buf) + != (grub_ssize_t) sz) + { + grub_free (tmp_buf); + return -1; + } + ts = HFSPLUS_COMPRESS_BLOCK_SIZE; + if (ts > node->size - (pos & ~(HFSPLUS_COMPRESS_BLOCK_SIZE))) + ts = node->size - (pos & ~(HFSPLUS_COMPRESS_BLOCK_SIZE)); + if (grub_zlib_decompress (tmp_buf, sz, 0, + node->cbuf, ts) < 0) + { + grub_free (tmp_buf); + return -1; + } + node->cbuf_block = block; + } + grub_memcpy (buf, node->cbuf + (pos % HFSPLUS_COMPRESS_BLOCK_SIZE), + curlen); + if (grub_file_progress_hook && node->file) + grub_file_progress_hook (0, 0, curlen, node->file); + buf += curlen; + pos += curlen; + len -= curlen; + } + grub_free (tmp_buf); + return len0; +} + +static grub_err_t +hfsplus_open_compressed_real (struct grub_hfsplus_file *node) +{ + grub_err_t err; + struct grub_hfsplus_btnode *attr_node; + grub_off_t attr_off; + struct grub_hfsplus_key_internal key; + struct grub_hfsplus_attr_header *attr_head; + struct grub_hfsplus_compress_attr *cmp_head; +#define c grub_cpu_to_be16_compile_time + const grub_uint16_t compress_attr_name[] = + { + c('c'), c('o'), c('m'), c('.'), c('a'), c('p'), c('p'), c('l'), c('e'), + c('.'), c('d'), c('e'), c('c'), c('m'), c('p'), c('f'), c('s') }; +#undef c + if (node->size) + return 0; + + key.attrkey.cnid = node->fileid; + key.attrkey.namelen = sizeof (compress_attr_name) / sizeof (compress_attr_name[0]); + key.attrkey.name = compress_attr_name; + + err = grub_hfsplus_btree_search (&node->data->attr_tree, &key, + grub_hfsplus_cmp_attrkey, + &attr_node, &attr_off); + if (err || !attr_node) + { + grub_errno = 0; + return 0; + } + + attr_head = (struct grub_hfsplus_attr_header *) + ((char *) grub_hfsplus_btree_recptr (&node->data->attr_tree, + attr_node, attr_off) + + sizeof (struct grub_hfsplus_attrkey) + sizeof (compress_attr_name)); + if (attr_head->type != 0x10 + || !(attr_head->size & grub_cpu_to_be64_compile_time(~0xfULL))) + { + grub_free (attr_node); + return 0; + } + cmp_head = (struct grub_hfsplus_compress_attr *) (attr_head + 1); + if (cmp_head->magic != grub_cpu_to_be32_compile_time (0x66706d63)) + { + grub_free (attr_node); + return 0; + } + node->size = grub_le_to_cpu32 (cmp_head->uncompressed_inline_size); + + if (cmp_head->type == grub_cpu_to_le32_compile_time (HFSPLUS_COMPRESSION_RESOURCE)) + { + grub_uint32_t index_size; + node->compressed = 2; + + if (grub_hfsplus_read_file (node, 0, 0, + 0x104, sizeof (index_size), + (char *) &index_size) + != 4) + { + node->compressed = 0; + grub_free (attr_node); + grub_errno = 0; + return 0; + } + node->compress_index_size = grub_le_to_cpu32 (index_size); + node->compress_index = grub_malloc (node->compress_index_size + * sizeof (node->compress_index[0])); + if (!node->compress_index) + { + node->compressed = 0; + grub_free (attr_node); + return grub_errno; + } + if (grub_hfsplus_read_file (node, 0, 0, + 0x104 + sizeof (index_size), + node->compress_index_size + * sizeof (node->compress_index[0]), + (char *) node->compress_index) + != (grub_ssize_t) (node->compress_index_size + * sizeof (node->compress_index[0]))) + { + node->compressed = 0; + grub_free (attr_node); + grub_free (node->compress_index); + grub_errno = 0; + return 0; + } + + node->cbuf_block = -1; + + node->cbuf = grub_malloc (HFSPLUS_COMPRESS_BLOCK_SIZE); + grub_free (attr_node); + if (!node->cbuf) + { + node->compressed = 0; + grub_free (node->compress_index); + return grub_errno; + } + return 0; + } + if (cmp_head->type != HFSPLUS_COMPRESSION_INLINE) + { + grub_free (attr_node); + return 0; + } + + node->cbuf = grub_malloc (node->size); + if (!node->cbuf) + return grub_errno; + + if (grub_zlib_decompress ((char *) (cmp_head + 1), + grub_cpu_to_be64 (attr_head->size) + - sizeof (*cmp_head), 0, + node->cbuf, node->size) < 0) + return grub_errno; + node->compressed = 1; + return 0; +} + +GRUB_MOD_INIT(hfspluscomp) +{ + grub_hfsplus_open_compressed = hfsplus_open_compressed_real; + grub_hfsplus_read_compressed = hfsplus_read_compressed_real; +} + +GRUB_MOD_FINI(hfspluscomp) +{ + grub_hfsplus_open_compressed = 0; + grub_hfsplus_read_compressed = 0; +} diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index cd4acc8ec..69e61ca02 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -79,6 +79,7 @@ struct grub_iso9660_dir struct grub_iso9660_date2 mtime; grub_uint8_t flags; grub_uint8_t unused2[6]; +#define MAX_NAMELEN 255 grub_uint8_t namelen; } __attribute__ ((packed)); @@ -260,42 +261,26 @@ static grub_err_t grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, grub_ssize_t sua_size, grub_err_t (*hook) - (struct grub_iso9660_susp_entry *entry)) + (struct grub_iso9660_susp_entry *entry, void *hook_arg), + void *hook_arg) { char *sua; struct grub_iso9660_susp_entry *entry; - grub_disk_addr_t ce_block; - int is_ce = 0; - - auto grub_err_t load_sua (void); - - /* Load a part of the System Usage Area. */ - grub_err_t load_sua (void) - { - grub_err_t err; - sua = grub_malloc (sua_size); - if (!sua) - return grub_errno; - - if (is_ce) - err = grub_disk_read (node->data->disk, ce_block, off, - sua_size, sua); - else - err = read_node (node, off, sua_size, sua); - if (err) - return err; - - entry = (struct grub_iso9660_susp_entry *) sua; - return 0; - } + grub_err_t err; if (sua_size <= 0) return GRUB_ERR_NONE; - if (load_sua ()) + sua = grub_malloc (sua_size); + if (!sua) return grub_errno; - for (; (char *) entry < (char *) sua + sua_size - 1; + /* Load a part of the System Usage Area. */ + err = read_node (node, off, sua_size, sua); + if (err) + return err; + + for (entry = (struct grub_iso9660_susp_entry *) sua; (char *) entry < (char *) sua + sua_size - 1 && entry->len > 0; entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len)) { @@ -307,19 +292,28 @@ grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, if (grub_strncmp ((char *) entry->sig, "CE", 2) == 0) { struct grub_iso9660_susp_ce *ce; + grub_disk_addr_t ce_block; - is_ce = 1; ce = (struct grub_iso9660_susp_ce *) entry; sua_size = grub_le_to_cpu32 (ce->len); off = grub_le_to_cpu32 (ce->off); ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; grub_free (sua); - if (load_sua ()) + sua = grub_malloc (sua_size); + if (!sua) return grub_errno; + + /* Load a part of the System Usage Area. */ + err = grub_disk_read (node->data->disk, ce_block, off, + sua_size, sua); + if (err) + return err; + + entry = (struct grub_iso9660_susp_entry *) sua; } - if (hook (entry)) + if (hook (entry, hook_arg)) { grub_free (sua); return 0; @@ -335,11 +329,11 @@ grub_iso9660_convert_string (grub_uint8_t *us, int len) { char *p; int i; - grub_uint16_t t[len]; + grub_uint16_t t[MAX_NAMELEN / 2 + 1]; p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! p) - return p; + return NULL; for (i=0; isig, "ER", 2) == 0) + { + data->rockridge = 1; + return 1; + } + return 0; +} + static grub_err_t set_rockridge (struct grub_iso9660_data *data) { @@ -358,20 +367,6 @@ set_rockridge (struct grub_iso9660_data *data) struct grub_iso9660_dir rootdir; struct grub_iso9660_susp_entry *entry; - auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *); - - grub_err_t susp_iterate (struct grub_iso9660_susp_entry *susp_entry) - { - /* The "ER" entry is used to detect extensions. The - `IEEE_P1285' extension means Rock ridge. */ - if (grub_strncmp ((char *) susp_entry->sig, "ER", 2) == 0) - { - data->rockridge = 1; - return 1; - } - return 0; - } - data->rockridge = 0; /* Read the system use area and test it to see if SUSP is @@ -423,7 +418,8 @@ set_rockridge (struct grub_iso9660_data *data) /* Iterate over the entries in the SUA area to detect extensions. */ if (grub_iso9660_susp_iterate (&rootnode, - sua_pos, sua_size, susp_iterate)) + sua_pos, sua_size, susp_iterate_set_rockridge, + data)) { grub_free (sua); return grub_errno; @@ -519,157 +515,159 @@ get_node_size (grub_fshelp_node_t node) return ret; } +struct iterate_dir_ctx +{ + char *filename; + int filename_alloc; + enum grub_fshelp_filetype type; + char *symlink; + int was_continue; +}; + + /* Extend the symlink. */ +static void +add_part (struct iterate_dir_ctx *ctx, + const char *part, + int len2) +{ + int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0; + + ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1); + if (! ctx->symlink) + return; + + grub_memcpy (ctx->symlink + size, part, len2); + ctx->symlink[size + len2] = 0; +} + +static grub_err_t +susp_iterate_dir (struct grub_iso9660_susp_entry *entry, + void *_ctx) +{ + struct iterate_dir_ctx *ctx = _ctx; + + /* The filename in the rock ridge entry. */ + if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0) + { + /* The flags are stored at the data position 0, here the + filename type is stored. */ + /* FIXME: Fix this slightly improper cast. */ + if (entry->data[0] & GRUB_ISO9660_RR_DOT) + ctx->filename = (char *) "."; + else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) + ctx->filename = (char *) ".."; + else if (entry->len >= 5) + { + grub_size_t off = 0, csize = 1; + char *old; + csize = entry->len - 5; + old = ctx->filename; + if (ctx->filename_alloc) + { + off = grub_strlen (ctx->filename); + ctx->filename = grub_realloc (ctx->filename, csize + off + 1); + } + else + { + off = 0; + ctx->filename = grub_zalloc (csize + 1); + } + if (!ctx->filename) + { + ctx->filename = old; + return grub_errno; + } + ctx->filename_alloc = 1; + grub_memcpy (ctx->filename + off, (char *) &entry->data[1], csize); + ctx->filename[off + csize] = '\0'; + } + } + /* The mode information (st_mode). */ + else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0) + { + /* At position 0 of the PX record the st_mode information is + stored (little-endian). */ + grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8)) + & GRUB_ISO9660_FSTYPE_MASK); + + switch (mode) + { + case GRUB_ISO9660_FSTYPE_DIR: + ctx->type = GRUB_FSHELP_DIR; + break; + case GRUB_ISO9660_FSTYPE_REG: + ctx->type = GRUB_FSHELP_REG; + break; + case GRUB_ISO9660_FSTYPE_SYMLINK: + ctx->type = GRUB_FSHELP_SYMLINK; + break; + default: + ctx->type = GRUB_FSHELP_UNKNOWN; + } + } + else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) + { + unsigned int pos = 1; + + /* The symlink is not stored as a POSIX symlink, translate it. */ + while (pos + sizeof (*entry) < entry->len) + { + /* The current position is the `Component Flag'. */ + switch (entry->data[pos] & 30) + { + case 0: + { + /* The data on pos + 2 is the actual data, pos + 1 + is the length. Both are part of the `Component + Record'. */ + if (ctx->symlink && !ctx->was_continue) + add_part (ctx, "/", 1); + add_part (ctx, (char *) &entry->data[pos + 2], + entry->data[pos + 1]); + ctx->was_continue = (entry->data[pos] & 1); + break; + } + + case 2: + add_part (ctx, "./", 2); + break; + + case 4: + add_part (ctx, "../", 3); + break; + + case 8: + add_part (ctx, "/", 1); + break; + } + /* In pos + 1 the length of the `Component Record' is + stored. */ + pos += entry->data[pos + 1] + 2; + } + + /* Check if `grub_realloc' failed. */ + if (grub_errno) + return grub_errno; + } + + return 0; +} + static int grub_iso9660_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_iso9660_dir dirent; grub_off_t offset = 0; - char *filename = 0; - int filename_alloc = 0; - enum grub_fshelp_filetype type; grub_off_t len; - char *symlink = 0; - int was_continue = 0; - - /* Extend the symlink. */ - auto inline void __attribute__ ((always_inline)) add_part (const char *part, - int len2); - - auto inline void __attribute__ ((always_inline)) add_part (const char *part, - int len2) - { - int size = symlink ? grub_strlen (symlink) : 0; - - symlink = grub_realloc (symlink, size + len2 + 1); - if (! symlink) - return; - - symlink[size] = 0; - grub_strncat (symlink, part, len2); - } - - auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *); - - grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry) - { - /* The filename in the rock ridge entry. */ - if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0) - { - /* The flags are stored at the data position 0, here the - filename type is stored. */ - /* FIXME: Fix this slightly improper cast. */ - if (entry->data[0] & GRUB_ISO9660_RR_DOT) - filename = (char *) "."; - else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) - filename = (char *) ".."; - else if (entry->len >= 5) - { - grub_size_t size = 1, csize = 1; - char *old; - csize = size = entry->len - 5; - old = filename; - if (filename_alloc) - { - size += grub_strlen (filename); - filename = grub_realloc (filename, size + 1); - } - else - { - filename_alloc = 1; - filename = grub_zalloc (size + 1); - filename[0] = 0; - } - if (!filename) - { - filename = old; - return grub_errno; - } - filename_alloc = 1; - grub_strncat (filename, (char *) &entry->data[1], csize); - filename[size] = '\0'; - } - } - /* The mode information (st_mode). */ - else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0) - { - /* At position 0 of the PX record the st_mode information is - stored (little-endian). */ - grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8)) - & GRUB_ISO9660_FSTYPE_MASK); - - switch (mode) - { - case GRUB_ISO9660_FSTYPE_DIR: - type = GRUB_FSHELP_DIR; - break; - case GRUB_ISO9660_FSTYPE_REG: - type = GRUB_FSHELP_REG; - break; - case GRUB_ISO9660_FSTYPE_SYMLINK: - type = GRUB_FSHELP_SYMLINK; - break; - default: - type = GRUB_FSHELP_UNKNOWN; - } - } - else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) - { - unsigned int pos = 1; - - /* The symlink is not stored as a POSIX symlink, translate it. */ - while (pos + sizeof (*entry) < entry->len) - { - /* The current position is the `Component Flag'. */ - switch (entry->data[pos] & 30) - { - case 0: - { - /* The data on pos + 2 is the actual data, pos + 1 - is the length. Both are part of the `Component - Record'. */ - if (symlink && !was_continue) - add_part ("/", 1); - add_part ((char *) &entry->data[pos + 2], - entry->data[pos + 1]); - was_continue = (entry->data[pos] & 1); - break; - } - - case 2: - add_part ("./", 2); - break; - - case 4: - add_part ("../", 3); - break; - - case 8: - add_part ("/", 1); - break; - } - /* In pos + 1 the length of the `Component Record' is - stored. */ - pos += entry->data[pos + 1] + 2; - } - - /* Check if `grub_realloc' failed. */ - if (grub_errno) - return grub_errno; - } - - return 0; - } + struct iterate_dir_ctx ctx; len = get_node_size (dir); for (; offset < len; offset += dirent.len) { - symlink = 0; - was_continue = 0; + ctx.symlink = 0; + ctx.was_continue = 0; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; @@ -682,7 +680,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, } { - char name[dirent.namelen + 1]; + char name[MAX_NAMELEN + 1]; int nameoffset = offset + sizeof (dirent); struct grub_fshelp_node *node; int sua_off = (sizeof (dirent) + dirent.namelen + 1 @@ -691,13 +689,13 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, sua_off += offset + dir->data->susp_skip; - filename = 0; - filename_alloc = 0; - type = GRUB_FSHELP_UNKNOWN; + ctx.filename = 0; + ctx.filename_alloc = 0; + ctx.type = GRUB_FSHELP_UNKNOWN; if (dir->data->rockridge && grub_iso9660_susp_iterate (dir, sua_off, sua_size, - susp_iterate_dir)) + susp_iterate_dir, &ctx)) return 0; /* Read the name. */ @@ -717,55 +715,55 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ - if (type == GRUB_FSHELP_UNKNOWN) + if (ctx.type == GRUB_FSHELP_UNKNOWN) { if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR) - type = GRUB_FSHELP_DIR; + ctx.type = GRUB_FSHELP_DIR; else - type = GRUB_FSHELP_REG; + ctx.type = GRUB_FSHELP_REG; } /* . and .. */ - if (!filename && dirent.namelen == 1 && name[0] == 0) - filename = (char *) "."; + if (!ctx.filename && dirent.namelen == 1 && name[0] == 0) + ctx.filename = (char *) "."; - if (!filename && dirent.namelen == 1 && name[0] == 1) - filename = (char *) ".."; + if (!ctx.filename && dirent.namelen == 1 && name[0] == 1) + ctx.filename = (char *) ".."; /* The filename was not stored in a rock ridge entry. Read it from the iso9660 filesystem. */ - if (!dir->data->joliet && !filename) + if (!dir->data->joliet && !ctx.filename) { char *ptr; name[dirent.namelen] = '\0'; - filename = grub_strrchr (name, ';'); - if (filename) - *filename = '\0'; + ctx.filename = grub_strrchr (name, ';'); + if (ctx.filename) + *ctx.filename = '\0'; /* ISO9660 names are not case-preserving. */ - type |= GRUB_FSHELP_CASE_INSENSITIVE; + ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE; for (ptr = name; *ptr; ptr++) *ptr = grub_tolower (*ptr); if (ptr != name && *(ptr - 1) == '.') *(ptr - 1) = 0; - filename = name; + ctx.filename = name; } - if (dir->data->joliet && !filename) + if (dir->data->joliet && !ctx.filename) { char *oldname, *semicolon; oldname = name; - filename = grub_iso9660_convert_string + ctx.filename = grub_iso9660_convert_string ((grub_uint8_t *) oldname, dirent.namelen >> 1); - semicolon = grub_strrchr (filename, ';'); + semicolon = grub_strrchr (ctx.filename, ';'); if (semicolon) *semicolon = '\0'; - if (filename_alloc) + if (ctx.filename_alloc) grub_free (oldname); - filename_alloc = 1; + ctx.filename_alloc = 1; } node->dirents[0] = dirent; @@ -774,8 +772,8 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, offset += dirent.len; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) { - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); grub_free (node); return 0; } @@ -790,8 +788,8 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, * sizeof (node->dirents[0]))); if (!new_node) { - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); grub_free (node); return 0; } @@ -799,10 +797,10 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, } node->dirents[node->have_dirents++] = dirent; } - if (symlink) + if (ctx.symlink) { if ((node->alloc_dirents - node->have_dirents) - * sizeof (node->dirents[0]) < grub_strlen (symlink) + 1) + * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) { struct grub_fshelp_node *new_node; new_node = grub_realloc (node, @@ -810,11 +808,11 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, + ((node->alloc_dirents - ARRAY_SIZE (node->dirents)) * sizeof (node->dirents[0])) - + grub_strlen (symlink) + 1); + + grub_strlen (ctx.symlink) + 1); if (!new_node) { - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); grub_free (node); return 0; } @@ -823,19 +821,19 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, node->have_symlink = 1; grub_strcpy (node->symlink + node->have_dirents * sizeof (node->dirents[0]) - - sizeof (node->dirents), symlink); - grub_free (symlink); - symlink = 0; - was_continue = 0; + - sizeof (node->dirents), ctx.symlink); + grub_free (ctx.symlink); + ctx.symlink = 0; + ctx.was_continue = 0; } - if (hook (filename, type, node)) + if (hook (ctx.filename, ctx.type, node, hook_data)) { - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); return 1; } - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); } } @@ -844,32 +842,39 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, +/* Context for grub_iso9660_dir. */ +struct grub_iso9660_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_iso9660_dir. */ +static int +grub_iso9660_dir_iter (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_iso9660_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); + + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_iso9660_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_iso9660_dir_ctx ctx = { hook, hook_data }; struct grub_iso9660_data *data = 0; struct grub_fshelp_node rootnode; struct grub_fshelp_node *foundnode; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); - - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_iso9660_mount (device->disk); @@ -891,7 +896,7 @@ grub_iso9660_dir (grub_device_t device, const char *path, goto fail; /* List the files in the directory. */ - grub_iso9660_iterate_dir (foundnode, iterate); + grub_iso9660_iterate_dir (foundnode, grub_iso9660_dir_iter, &ctx); if (foundnode != &rootnode) grub_free (foundnode); @@ -957,6 +962,7 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len) /* XXX: The file is stored in as a single extent. */ data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; read_node (data->node, file->offset, len, buf); data->disk->read_hook = NULL; diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index b98a5a374..062501492 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -255,60 +255,60 @@ static grub_dl_t my_mod; static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino); +static grub_int64_t +getblk (struct grub_jfs_treehead *treehead, + struct grub_jfs_tree_extent *extents, + struct grub_jfs_data *data, + grub_uint64_t blk) +{ + int found = -1; + int i; + + for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2; i++) + { + if (treehead->flags & GRUB_JFS_TREE_LEAF) + { + /* Read the leafnode. */ + if (grub_le_to_cpu32 (extents[i].offset2) <= blk + && ((grub_le_to_cpu16 (extents[i].extent.length)) + + (extents[i].extent.length2 << 16) + + grub_le_to_cpu32 (extents[i].offset2)) > blk) + return (blk - grub_le_to_cpu32 (extents[i].offset2) + + grub_le_to_cpu32 (extents[i].extent.blk2)); + } + else + if (blk >= grub_le_to_cpu32 (extents[i].offset2)) + found = i; + } + + if (found != -1) + { + struct + { + struct grub_jfs_treehead treehead; + struct grub_jfs_tree_extent extents[254]; + } tree; + + if (grub_disk_read (data->disk, + ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2)) + << (grub_le_to_cpu16 (data->sblock.log2_blksz) + - GRUB_DISK_SECTOR_BITS), 0, + sizeof (tree), (char *) &tree)) + return -1; + + return getblk (&tree.treehead, &tree.extents[0], data, blk); + } + + return -1; +} + /* Get the block number for the block BLK in the node INODE in the mounted filesystem DATA. */ static grub_int64_t grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, grub_uint64_t blk) { - auto grub_int64_t getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents); - - grub_int64_t getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents) - { - int found = -1; - int i; - - for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2; i++) - { - if (treehead->flags & GRUB_JFS_TREE_LEAF) - { - /* Read the leafnode. */ - if (grub_le_to_cpu32 (extents[i].offset2) <= blk - && ((grub_le_to_cpu16 (extents[i].extent.length)) - + (extents[i].extent.length2 << 16) - + grub_le_to_cpu32 (extents[i].offset2)) > blk) - return (blk - grub_le_to_cpu32 (extents[i].offset2) - + grub_le_to_cpu32 (extents[i].extent.blk2)); - } - else - if (blk >= grub_le_to_cpu32 (extents[i].offset2)) - found = i; - } - - if (found != -1) - { - struct - { - struct grub_jfs_treehead treehead; - struct grub_jfs_tree_extent extents[254]; - } tree; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2)) - << (grub_le_to_cpu16 (data->sblock.log2_blksz) - - GRUB_DISK_SECTOR_BITS), 0, - sizeof (tree), (char *) &tree)) - return -1; - - return getblk (&tree.treehead, &tree.extents[0]); - } - - return -1; - } - - return getblk (&inode->file.tree, &inode->file.extents[0]); + return getblk (&inode->file.tree, &inode->file.extents[0], data, blk); } @@ -489,6 +489,13 @@ grub_jfs_closedir (struct grub_jfs_diropen *diro) grub_free (diro); } +static void +le_to_cpu16_copy (grub_uint16_t *out, grub_uint16_t *in, grub_size_t len) +{ + while (len--) + *out++ = grub_le_to_cpu16 (*in++); +} + /* Read in the next dirent from the directory described by DIRO. */ static grub_err_t @@ -501,15 +508,6 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) int nextent; grub_uint16_t filename[256]; - auto void addstr (grub_uint16_t *uname, int ulen); - - /* Add the unicode string to the utf16 filename buffer. */ - void addstr (grub_uint16_t *name, int ulen) - { - while (ulen--) - filename[strpos++] = grub_le_to_cpu16 (*(name++)); - } - /* The last node, read in more. */ if (diro->index == diro->count) { @@ -547,8 +545,10 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) return grub_jfs_getent (diro); } - addstr (leaf->namepart, len < diro->data->namecomponentlen ? len - : diro->data->namecomponentlen); + le_to_cpu16_copy (filename + strpos, leaf->namepart, len < diro->data->namecomponentlen ? len + : diro->data->namecomponentlen); + strpos += len < diro->data->namecomponentlen ? len + : diro->data->namecomponentlen; diro->ino = grub_le_to_cpu32 (leaf->inode); len -= diro->data->namecomponentlen; @@ -558,7 +558,8 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) do { next_leaf = &diro->next_leaf[nextent]; - addstr (next_leaf->namepart, len < 15 ? len : 15 ); + le_to_cpu16_copy (filename + strpos, next_leaf->namepart, len < 15 ? len : 15); + strpos += len < 15 ? len : 15; len -= 15; nextent = next_leaf->next; @@ -577,8 +578,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_jfs_read_file (struct grub_jfs_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { grub_off_t i; @@ -616,6 +616,7 @@ grub_jfs_read_file (struct grub_jfs_data *data, } data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS), @@ -638,136 +639,74 @@ static grub_err_t grub_jfs_find_file (struct grub_jfs_data *data, const char *path, grub_uint32_t start_ino) { - char fpath[grub_strlen (path)]; - char *name = fpath; - char *next; - struct grub_jfs_diropen *diro; - - grub_strncpy (fpath, path, grub_strlen (path) + 1); + const char *name; + const char *next = path; + struct grub_jfs_diropen *diro = NULL; if (grub_jfs_read_inode (data, start_ino, &data->currinode)) return grub_errno; - /* Skip the first slashes. */ - while (*name == '/') - { - name++; - if (!*name) - return 0; - } - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) - { - while (*next == '/') - { - next[0] = '\0'; - next++; - } - } - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) - return grub_errno; - - for (;;) + while (1) { + name = next; + while (*name == '/') + name++; if (name[0] == 0) return GRUB_ERR_NONE; + for (next = name; *next && *next != '/'; next++); - if (name[0] == '.' && name[1] == 0) - { - if (!next) - return 0; + if (name[0] == '.' && name + 1 == next) + continue; - name = next; - next = grub_strchr (name, '/'); - while (next && *next == '/') - { - next[0] = '\0'; - next++; - } - continue; - } - - if (name[0] == '.' && name[1] == '.' && name[2] == 0) + if (name[0] == '.' && name[1] == '.' && name + 2 == next) { grub_uint32_t ino = grub_le_to_cpu32 (data->currinode.dir.header.idotdot); - grub_jfs_closedir (diro); - diro = 0; - if (grub_jfs_read_inode (data, ino, &data->currinode)) - break; - - if (!next) - return 0; - - name = next; - next = grub_strchr (name, '/'); - while (next && *next == '/') - { - next[0] = '\0'; - next++; - } - - /* Open this directory for reading dirents. */ - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) return grub_errno; continue; } - if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE) - break; + diro = grub_jfs_opendir (data, &data->currinode); + if (!diro) + return grub_errno; - /* Check if the current direntry matches the current part of the - pathname. */ - if (data->caseins ? grub_strcasecmp (name, diro->name) == 0 - : grub_strcmp (name, diro->name) == 0) + for (;;) { - grub_uint32_t ino = diro->ino; - grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode); - - grub_jfs_closedir (diro); - diro = 0; - - if (grub_jfs_read_inode (data, ino, &data->currinode)) - break; - - /* Check if this is a symlink. */ - if ((grub_le_to_cpu32 (data->currinode.mode) - & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_LNK) + if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE) { - grub_jfs_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; + grub_jfs_closedir (diro); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); } - if (!next) - return 0; - - name = next; - next = grub_strchr (name, '/'); - while (next && *next == '/') + /* Check if the current direntry matches the current part of the + pathname. */ + if ((data->caseins ? grub_strncasecmp (name, diro->name, next - name) == 0 + : grub_strncmp (name, diro->name, next - name) == 0) && !diro->name[next - name]) { - next[0] = '\0'; - next++; + grub_uint32_t ino = diro->ino; + grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode); + + grub_jfs_closedir (diro); + diro = 0; + + if (grub_jfs_read_inode (data, ino, &data->currinode)) + break; + + /* Check if this is a symlink. */ + if ((grub_le_to_cpu32 (data->currinode.mode) + & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_LNK) + { + grub_jfs_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; + } + + break; } - - /* Open this directory for reading dirents. */ - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) - return grub_errno; - - continue; } } - - grub_jfs_closedir (diro); - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - return grub_errno; } @@ -775,15 +714,21 @@ static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) { grub_size_t size = grub_le_to_cpu64 (data->currinode.size); - char symlink[size + 1]; + char *symlink; if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); - if (size <= sizeof (data->currinode.symlink.path)) - grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size); - else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0) + symlink = grub_malloc (size + 1); + if (!symlink) return grub_errno; + if (size <= sizeof (data->currinode.symlink.path)) + grub_memcpy (symlink, (char *) (data->currinode.symlink.path), size); + else if (grub_jfs_read_file (data, 0, 0, 0, size, symlink) < 0) + { + grub_free (symlink); + return grub_errno; + } symlink[size] = '\0'; @@ -793,14 +738,15 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) grub_jfs_find_file (data, symlink, ino); + grub_free (symlink); + return grub_errno; } static grub_err_t grub_jfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_jfs_data *data = 0; struct grub_jfs_diropen *diro = 0; @@ -832,7 +778,7 @@ grub_jfs_dir (grub_device_t device, const char *path, & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR; info.mtimeset = 1; info.mtime = grub_le_to_cpu32 (inode.mtime.sec); - if (hook (diro->name, &info)) + if (hook (diro->name, &info, hook_data)) goto fail; } @@ -895,7 +841,8 @@ grub_jfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_jfs_data *data = (struct grub_jfs_data *) file->data; - return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf); + return grub_jfs_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 1e1c13b56..98e1b71ec 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -161,6 +161,12 @@ struct grub_minix_inode #endif +#if defined(MODE_MINIX3) +#define MAX_MINIX_FILENAME_SIZE 60 +#else +#define MAX_MINIX_FILENAME_SIZE 30 +#endif + /* Information about a "mounted" minix filesystem. */ struct grub_minix_data { @@ -178,6 +184,20 @@ static grub_dl_t my_mod; static grub_err_t grub_minix_find_file (struct grub_minix_data *data, const char *path); + /* Read the block pointer in ZONE, on the offset NUM. */ +static grub_minix_uintn_t +grub_get_indir (struct grub_minix_data *data, + grub_minix_uintn_t zone, + grub_minix_uintn_t num) +{ + grub_minix_uintn_t indirn; + grub_disk_read (data->disk, + GRUB_MINIX_ZONE2SECT(zone), + sizeof (grub_minix_uintn_t) * num, + sizeof (grub_minix_uintn_t), (char *) &indirn); + return grub_minix_to_cpu_n (indirn); +} + static grub_minix_uintn_t grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { @@ -185,21 +205,6 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)); - auto grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t, - grub_minix_uintn_t); - - /* Read the block pointer in ZONE, on the offset NUM. */ - grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t zone, - grub_minix_uintn_t num) - { - grub_minix_uintn_t indirn; - grub_disk_read (data->disk, - GRUB_MINIX_ZONE2SECT(zone), - sizeof (grub_minix_uintn_t) * num, - sizeof (grub_minix_uintn_t), (char *) &indirn); - return grub_minix_to_cpu_n (indirn); - } - /* Direct block. */ if (blk < GRUB_MINIX_INODE_DIR_BLOCKS) return GRUB_MINIX_INODE_DIR_ZONES (data, blk); @@ -208,7 +213,7 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) blk -= GRUB_MINIX_INODE_DIR_BLOCKS; if (blk < block_per_zone) { - indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); + indir = grub_get_indir (data, GRUB_MINIX_INODE_INDIR_ZONE (data), blk); return indir; } @@ -216,10 +221,10 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) blk -= block_per_zone; if (blk < block_per_zone * block_per_zone) { - indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data), + indir = grub_get_indir (data, GRUB_MINIX_INODE_DINDIR_ZONE (data), blk / block_per_zone); - indir = grub_get_indir (indir, blk % block_per_zone); + indir = grub_get_indir (data, indir, blk % block_per_zone); return indir; } @@ -229,10 +234,10 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone)) { - indir = grub_get_indir (grub_minix_to_cpu_n (data->inode.triple_indir_zone), + indir = grub_get_indir (data, grub_minix_to_cpu_n (data->inode.triple_indir_zone), (blk / block_per_zone) / block_per_zone); - indir = grub_get_indir (indir, (blk / block_per_zone) % block_per_zone); - indir = grub_get_indir (indir, blk % block_per_zone); + indir = grub_get_indir (data, indir, (blk / block_per_zone) % block_per_zone); + indir = grub_get_indir (data, indir, blk % block_per_zone); return indir; } @@ -249,8 +254,7 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_minix_read_file (struct grub_minix_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { grub_uint32_t i; @@ -261,12 +265,12 @@ grub_minix_read_file (struct grub_minix_data *data, /* Adjust len so it we can't read past the end of the file. */ if (len + pos > GRUB_MINIX_INODE_SIZE (data)) len = GRUB_MINIX_INODE_SIZE (data) - pos; + if (len == 0) + return 0; /* Files are at most 2G/4G - 1 bytes on minixfs. Avoid 64-bit division. */ - blockcnt = ((grub_uint32_t) ((len + pos - + (data->block_size << GRUB_DISK_SECTOR_BITS) - - 1) - >> GRUB_DISK_SECTOR_BITS)) / data->block_size; + blockcnt = ((grub_uint32_t) ((len + pos - 1) + >> GRUB_DISK_SECTOR_BITS)) / data->block_size + 1; posblock = (((grub_uint32_t) pos) / (data->block_size << GRUB_DISK_SECTOR_BITS)); blockoff = (((grub_uint32_t) pos) @@ -301,6 +305,7 @@ grub_minix_read_file (struct grub_minix_data *data, } data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, GRUB_MINIX_ZONE2SECT(blknr), skipfirst, blockend, buf); @@ -347,16 +352,19 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino) static grub_err_t grub_minix_lookup_symlink (struct grub_minix_data *data, grub_minix_ino_t ino) { - char symlink[GRUB_MINIX_INODE_SIZE (data) + 1]; + char *symlink; + grub_size_t sz = GRUB_MINIX_INODE_SIZE (data); if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); - if (grub_minix_read_file (data, 0, 0, - GRUB_MINIX_INODE_SIZE (data), symlink) < 0) + symlink = grub_malloc (sz + 1); + if (!symlink) + return grub_errno; + if (grub_minix_read_file (data, 0, 0, 0, sz, symlink) < 0) return grub_errno; - symlink[GRUB_MINIX_INODE_SIZE (data)] = '\0'; + symlink[sz] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') @@ -377,90 +385,70 @@ grub_minix_lookup_symlink (struct grub_minix_data *data, grub_minix_ino_t ino) static grub_err_t grub_minix_find_file (struct grub_minix_data *data, const char *path) { - char fpath[grub_strlen (path) + 1]; - char *name = fpath; - char *next; + const char *name; + const char *next = path; unsigned int pos = 0; grub_minix_ino_t dirino; - grub_strcpy (fpath, path); - - /* Skip the first slash. */ - while (*name == '/') - name++; - if (!*name) - return 0; - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) + while (1) { - next[0] = '\0'; - next++; - while (*next == '/') - next++; - } - - do - { - grub_minix_ino_t ino; - char filename[data->filename_size + 1]; - - if (grub_strlen (name) == 0) + name = next; + /* Skip the first slash. */ + while (*name == '/') + name++; + if (!*name) return GRUB_ERR_NONE; - if (grub_minix_read_file (data, 0, pos, sizeof (ino), - (char *) &ino) < 0) - return grub_errno; - if (grub_minix_read_file (data, 0, pos + sizeof (ino), - data->filename_size, (char *) filename)< 0) - return grub_errno; + if ((GRUB_MINIX_INODE_MODE (data) + & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - filename[data->filename_size] = '\0'; + /* Extract the actual part from the pathname. */ + for (next = name; *next && *next != '/'; next++); - /* Check if the current direntry matches the current part of the - pathname. */ - if (!grub_strcmp (name, filename)) + for (pos = 0; ; ) { - dirino = data->ino; - grub_minix_read_inode (data, grub_minix_to_cpu_ino (ino)); + grub_minix_ino_t ino; + char filename[MAX_MINIX_FILENAME_SIZE + 1]; - /* Follow the symlink. */ - if ((GRUB_MINIX_INODE_MODE (data) - & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK) + if (pos >= GRUB_MINIX_INODE_SIZE (data)) { - grub_minix_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + return grub_errno; } - if (!next) - return 0; + if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino), + (char *) &ino) < 0) + return grub_errno; + if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino), + data->filename_size, (char *) filename)< 0) + return grub_errno; - pos = 0; + pos += sizeof (ino) + data->filename_size; - name = next; - next = grub_strchr (name, '/'); - if (next) + filename[data->filename_size] = '\0'; + + /* Check if the current direntry matches the current part of the + pathname. */ + if (grub_strncmp (name, filename, next - name) == 0 + && filename[next - name] == '\0') { - next[0] = '\0'; - next++; - while (*next == '/') - next++; + dirino = data->ino; + grub_minix_read_inode (data, grub_minix_to_cpu_ino (ino)); + + /* Follow the symlink. */ + if ((GRUB_MINIX_INODE_MODE (data) + & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK) + { + grub_minix_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; + } + + break; } - - if ((GRUB_MINIX_INODE_MODE (data) - & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - - continue; } - - pos += sizeof (ino) + data->filename_size; - } while (pos < GRUB_MINIX_INODE_SIZE (data)); - - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - return grub_errno; + } } @@ -536,8 +524,7 @@ grub_minix_mount (grub_disk_t disk) static grub_err_t grub_minix_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_minix_data *data = 0; unsigned int pos = 0; @@ -563,17 +550,17 @@ grub_minix_dir (grub_device_t device, const char *path, while (pos < GRUB_MINIX_INODE_SIZE (data)) { grub_minix_ino_t ino; - char filename[data->filename_size + 1]; + char filename[MAX_MINIX_FILENAME_SIZE + 1]; grub_minix_ino_t dirino = data->ino; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); - if (grub_minix_read_file (data, 0, pos, sizeof (ino), + if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino), (char *) &ino) < 0) return grub_errno; - if (grub_minix_read_file (data, 0, pos + sizeof (ino), + if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino), data->filename_size, (char *) filename) < 0) return grub_errno; @@ -590,7 +577,7 @@ grub_minix_dir (grub_device_t device, const char *path, info.mtimeset = 1; info.mtime = grub_minix_to_cpu32 (data->inode.mtime); - if (hook (filename, &info) ? 1 : 0) + if (hook (filename, &info, hook_data) ? 1 : 0) break; /* Load the old inode back in. */ @@ -650,7 +637,8 @@ grub_minix_read (grub_file_t file, char *buf, grub_size_t len) struct grub_minix_data *data = (struct grub_minix_data *) file->data; - return grub_minix_read_file (data, file->read_hook, file->offset, len, buf); + return grub_minix_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c index fdcc160e8..c7767ed3b 100644 --- a/grub-core/fs/newc.c +++ b/grub-core/fs/newc.c @@ -1,2 +1,73 @@ -#define MODE_NEWC 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4)) +#define MAGIC "070701" +#define MAGIC2 "070702" +struct head +{ + char magic[6]; + char ino[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char devmajor[8]; + char devminor[8]; + char rdevmajor[8]; + char rdevminor[8]; + char namesize[8]; + char check[8]; +} __attribute__ ((packed)); + +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && grub_isxdigit (*str)) + { + char dig = *str++; + if (dig >= '0' && dig <= '9') + dig &= 0xf; + else if (dig >= 'a' && dig <= 'f') + dig -= 'a' - 10; + else + dig -= 'A' - 10; + ret = (ret << 4) | (dig); + } + return ret; +} + +#define FSNAME "newc" + +#include "cpio_common.c" + +GRUB_MOD_INIT (newc) +{ + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (newc) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index f36c513fa..1318f2140 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -136,6 +136,7 @@ struct grub_nilfs2_dir_entry { grub_uint64_t inode; grub_uint16_t rec_len; +#define MAX_NAMELEN 255 grub_uint8_t name_len; grub_uint8_t file_type; #if 0 /* followed by file name. */ @@ -214,6 +215,8 @@ struct grub_nilfs2_palloc_group_desc grub_uint32_t pg_nfrees; }; +#define LOG_SIZE_GROUP_DESC 2 + #define LOG_NILFS_DAT_ENTRY_SIZE 5 struct grub_nilfs2_dat_entry { @@ -311,10 +314,12 @@ grub_nilfs2_palloc_group (struct grub_nilfs2_data *data, } static inline grub_uint32_t -grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data) +grub_nilfs2_palloc_log_groups_per_desc_block (struct grub_nilfs2_data *data) { - return NILFS2_BLOCK_SIZE (data) / - sizeof (struct grub_nilfs2_palloc_group_desc); + return LOG2_BLOCK_SIZE (data) - LOG_SIZE_GROUP_DESC; + + COMPILE_TIME_ASSERT (sizeof (struct grub_nilfs2_palloc_group_desc) + == (1 << LOG_SIZE_GROUP_DESC)); } static inline grub_uint32_t @@ -338,8 +343,8 @@ static inline grub_uint32_t grub_nilfs2_blocks_per_desc_block_log (struct grub_nilfs2_data *data, unsigned long log_entry_size) { - return grub_nilfs2_palloc_groups_per_desc_block (data) * - grub_nilfs2_blocks_per_group_log (data, log_entry_size) + 1; + return(grub_nilfs2_blocks_per_group_log (data, log_entry_size) + << grub_nilfs2_palloc_log_groups_per_desc_block (data)) + 1; } static inline grub_uint32_t @@ -348,7 +353,7 @@ grub_nilfs2_palloc_desc_block_offset_log (struct grub_nilfs2_data *data, unsigned long log_entry_size) { grub_uint32_t desc_block = - group / grub_nilfs2_palloc_groups_per_desc_block (data); + group >> grub_nilfs2_palloc_log_groups_per_desc_block (data); return desc_block * grub_nilfs2_blocks_per_desc_block_log (data, log_entry_size); } @@ -358,8 +363,8 @@ grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data, unsigned long group, unsigned long log_entry_size) { - unsigned long desc_offset = group % - grub_nilfs2_palloc_groups_per_desc_block (data); + unsigned long desc_offset = group + & ((1 << grub_nilfs2_palloc_log_groups_per_desc_block (data)) - 1); return grub_nilfs2_palloc_desc_block_offset_log (data, group, log_entry_size) + 1 @@ -501,9 +506,13 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_uint64_t key, int need_translate) { struct grub_nilfs2_btree_node *node; - GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data)); + void *block; grub_uint64_t ptr; - int level, found, index; + int level, found = 0, index; + + block = grub_malloc (NILFS2_BLOCK_SIZE (data)); + if (!block) + return -1; node = grub_nilfs2_btree_get_root (inode); level = grub_nilfs2_btree_get_level (node); @@ -518,14 +527,14 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_nilfs2_btree_get_nonroot_node (data, ptr, block); if (grub_errno) { - return -1; + goto fail; } node = (struct grub_nilfs2_btree_node *) block; if (node->bn_level != level) { grub_error (GRUB_ERR_BAD_FS, "btree level mismatch\n"); - return -1; + goto fail; } if (!found) @@ -542,14 +551,19 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, else { grub_error (GRUB_ERR_BAD_FS, "btree corruption\n"); - return -1; + goto fail; } } + grub_free (block); + if (!found) return -1; return ptr; + fail: + grub_free (block); + return -1; } static inline grub_uint64_t @@ -626,13 +640,11 @@ grub_nilfs2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_nilfs2_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t - sector, - unsigned offset, - unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_nilfs2_read_block, grub_le_to_cpu64 (node->inode.i_size), LOG2_NILFS2_BLOCK_SIZE (node->data), 0); @@ -852,7 +864,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node) if (!symlink) return 0; - grub_nilfs2_read_file (diro, 0, 0, + grub_nilfs2_read_file (diro, 0, 0, 0, grub_le_to_cpu64 (diro->inode.i_size), symlink); if (grub_errno) { @@ -866,10 +878,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node) static int grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_off_t fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; @@ -886,7 +895,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, { struct grub_nilfs2_dir_entry dirent; - grub_nilfs2_read_file (diro, 0, fpos, + grub_nilfs2_read_file (diro, 0, 0, fpos, sizeof (struct grub_nilfs2_dir_entry), (char *) &dirent); if (grub_errno) @@ -897,11 +906,11 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, if (dirent.name_len != 0) { - char filename[dirent.name_len + 1]; + char filename[MAX_NAMELEN + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; - grub_nilfs2_read_file (diro, 0, + grub_nilfs2_read_file (diro, 0, 0, fpos + sizeof (struct grub_nilfs2_dir_entry), dirent.name_len, filename); if (grub_errno) @@ -953,7 +962,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_REG; } - if (hook (filename, type, fdiro)) + if (hook (filename, type, fdiro, hook_data)) return 1; } @@ -1024,64 +1033,74 @@ grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_nilfs2_data *data = (struct grub_nilfs2_data *) file->data; - return grub_nilfs2_read_file (&data->diropen, file->read_hook, + return grub_nilfs2_read_file (&data->diropen, + file->read_hook, file->read_hook_data, file->offset, len, buf); } +/* Context for grub_nilfs2_dir. */ +struct grub_nilfs2_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_nilfs2_data *data; +}; + +/* Helper for grub_nilfs2_dir. */ +static int +grub_nilfs2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_nilfs2_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + if (!node->inode_read) + { + grub_nilfs2_read_inode (ctx->data, node->ino, &node->inode); + if (!grub_errno) + node->inode_read = 1; + grub_errno = GRUB_ERR_NONE; + } + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_le_to_cpu64 (node->inode.i_mtime); + } + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_nilfs2_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info * info)) + grub_fs_dir_hook_t hook, void *hook_data) { - struct grub_nilfs2_data *data = 0; + struct grub_nilfs2_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - if (!node->inode_read) - { - grub_nilfs2_read_inode (data, node->ino, &node->inode); - if (!grub_errno) - node->inode_read = 1; - grub_errno = GRUB_ERR_NONE; - } - if (node->inode_read) - { - info.mtimeset = 1; - info.mtime = grub_le_to_cpu64 (node->inode.i_mtime); - } - - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); - data = grub_nilfs2_mount (device->disk); - if (!data) + ctx.data = grub_nilfs2_mount (device->disk); + if (!ctx.data) goto fail; - grub_fshelp_find_file (path, &data->diropen, &fdiro, + grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_nilfs2_iterate_dir (fdiro, iterate); + grub_nilfs2_iterate_dir (fdiro, grub_nilfs2_dir_iter, &ctx); fail: - if (fdiro != &data->diropen) + if (fdiro != &ctx.data->diropen) grub_free (fdiro); - grub_free (data); + grub_free (ctx.data); grub_dl_unref (my_mod); diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index b9762b6a0..83ba5698c 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -55,10 +55,10 @@ u64at (void *ptr, grub_size_t ofs) grub_ntfscomp_func_t grub_ntfscomp_func; static grub_err_t -fixup (char *buf, int len, const char *magic) +fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic) { - int ss; - char *pu; + grub_uint16_t ss; + grub_uint8_t *pu; grub_uint16_t us; COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE); @@ -86,25 +86,20 @@ fixup (char *buf, int len, const char *magic) return 0; } -static grub_err_t read_mft (struct grub_ntfs_data *data, char *buf, - grub_uint32_t mftno); -static grub_err_t read_attr (struct grub_ntfs_attr *at, char *dest, +static grub_err_t read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, + grub_uint64_t mftno); +static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void - NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t - sector, - unsigned offset, - unsigned length)); + grub_disk_read_hook_t read_hook, + void *read_hook_data); -static grub_err_t read_data (struct grub_ntfs_attr *at, char *pa, char *dest, +static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, + grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void - NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t - sector, - unsigned offset, - unsigned length)); + grub_disk_read_hook_t read_hook, + void *read_hook_data); static void init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft) @@ -123,8 +118,8 @@ free_attr (struct grub_ntfs_attr *at) grub_free (at->sbuf); } -static char * -find_attr (struct grub_ntfs_attr *at, unsigned char attr) +static grub_uint8_t * +find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) { if (at->flags & GRUB_NTFS_AF_ALST) { @@ -133,9 +128,9 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) { at->attr_cur = at->attr_nxt; at->attr_nxt += u16at (at->attr_cur, 4); - if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) + if ((*at->attr_cur == attr) || (attr == 0)) { - char *new_pos; + grub_uint8_t *new_pos; if (at->flags & GRUB_NTFS_AF_MMFT) { @@ -148,7 +143,8 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) 512, at->emft_buf + 512))) return NULL; - if (fixup (at->emft_buf, at->mft->data->mft_size, "FILE")) + if (fixup (at->emft_buf, at->mft->data->mft_size, + (const grub_uint8_t *) "FILE")) return NULL; } else @@ -159,10 +155,9 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) } new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)]; - while ((unsigned char) *new_pos != 0xFF) + while (*new_pos != 0xFF) { - if (((unsigned char) *new_pos == - (unsigned char) *at->attr_cur) + if ((*new_pos == *at->attr_cur) && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18))) { return new_pos; @@ -178,18 +173,18 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) return NULL; } at->attr_cur = at->attr_nxt; - while ((unsigned char) *at->attr_cur != 0xFF) + while (*at->attr_cur != 0xFF) { at->attr_nxt += u16at (at->attr_cur, 4); - if ((unsigned char) *at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) + if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) at->attr_end = at->attr_cur; - if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) + if ((*at->attr_cur == attr) || (attr == 0)) return at->attr_cur; at->attr_cur = at->attr_nxt; } if (at->attr_end) { - char *pa; + grub_uint8_t *pa; at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); if (at->emft_buf == NULL) @@ -198,7 +193,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) pa = at->attr_end; if (pa[8]) { - int n; + grub_uint32_t n; n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1) & (~(GRUB_DISK_SECTOR_SIZE - 1))); @@ -206,7 +201,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->edat_buf = grub_malloc (n); if (!at->edat_buf) return NULL; - if (read_data (at, pa, at->edat_buf, 0, n, 0, 0)) + if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0)) { grub_error (GRUB_ERR_BAD_FS, "fail to read non-resident attribute list"); @@ -223,7 +218,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->flags |= GRUB_NTFS_AF_ALST; while (at->attr_nxt < at->attr_end) { - if (((unsigned char) *at->attr_nxt == attr) || (attr == 0)) + if ((*at->attr_nxt == attr) || (attr == 0)) break; at->attr_nxt += u16at (at->attr_nxt, 4); } @@ -243,12 +238,12 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) pa = at->attr_nxt + u16at (pa, 4); while (pa < at->attr_end) { - if ((unsigned char) *pa != attr) + if (*pa != attr) break; if (read_attr (at, pa + 0x10, u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR), - at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) + at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0)) return NULL; pa += u16at (pa, 4); } @@ -260,11 +255,11 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) return NULL; } -static char * +static grub_uint8_t * locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, - unsigned char attr) + grub_uint8_t attr) { - char *pa; + grub_uint8_t *pa; init_attr (at, mft); pa = find_attr (at, attr); @@ -288,49 +283,40 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, return pa; } -static char * -read_run_data (char *run, int nn, grub_disk_addr_t * val, int sig) +static grub_disk_addr_t +read_run_data (const grub_uint8_t *run, int nn, int sig) { - grub_disk_addr_t r, v; + grub_uint64_t r = 0; - r = 0; - v = 1; + if (sig && nn && (run[nn - 1] & 0x80)) + r = -1; - while (nn--) - { - r += v * (*(unsigned char *) (run++)); - v <<= 8; - } + grub_memcpy (&r, run, nn); - if ((sig) && (r & (v >> 1))) - r -= v; - - *val = r; - return run; + return grub_le_to_cpu64 (r); } grub_err_t grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx) { - int c1, c2; + grub_uint8_t c1, c2; grub_disk_addr_t val; - char *run; + grub_uint8_t *run; run = ctx->cur_run; retry: - c1 = ((unsigned char) (*run) & 0xF); - c2 = ((unsigned char) (*run) >> 4); + c1 = ((*run) & 0x7); + c2 = ((*run) >> 4) & 0x7; + run++; if (!c1) { if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST)) { - void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length); + grub_disk_read_hook_t save_hook; save_hook = ctx->comp.disk->read_hook; ctx->comp.disk->read_hook = 0; - run = find_attr (ctx->attr, (unsigned char) *ctx->attr->attr_cur); + run = find_attr (ctx->attr, *ctx->attr->attr_cur); ctx->comp.disk->read_hook = save_hook; if (run) { @@ -345,10 +331,11 @@ retry: } return grub_error (GRUB_ERR_BAD_FS, "run list overflown"); } - run = read_run_data (run + 1, c1, &val, 0); /* length of current VCN */ ctx->curr_vcn = ctx->next_vcn; - ctx->next_vcn += val; - run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */ + ctx->next_vcn += read_run_data (run, c1, 0); /* length of current VCN */ + run += c1; + val = read_run_data (run, c2, 1); /* offset to previous LCN */ + run += c2; ctx->curr_lcn += val; if (val == 0) ctx->flags |= GRUB_NTFS_RF_BLNK; @@ -376,13 +363,10 @@ grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block) } static grub_err_t -read_data (struct grub_ntfs_attr *at, char *pa, char *dest, +read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { - grub_disk_addr_t vcn; struct grub_ntfs_rlst cc, *ctx; if (len == 0) @@ -391,9 +375,12 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_memset (&cc, 0, sizeof (cc)); ctx = &cc; ctx->attr = at; - ctx->comp.spc = at->mft->data->spc; + ctx->comp.log_spc = at->mft->data->log_spc; ctx->comp.disk = at->mft->data->disk; + if (read_hook == grub_file_progress_hook) + ctx->file = read_hook_data; + if (pa[8] == 0) { if (ofs + len > u32at (pa, 0x10)) @@ -402,52 +389,23 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return 0; } - if (u16at (pa, 0xC) & GRUB_NTFS_FLAG_COMPRESSED) - ctx->flags |= GRUB_NTFS_RF_COMP; - else - ctx->flags &= ~GRUB_NTFS_RF_COMP; ctx->cur_run = pa + u16at (pa, 0x20); - if (ctx->flags & GRUB_NTFS_RF_COMP) + ctx->next_vcn = u32at (pa, 0x10); + ctx->curr_lcn = 0; + + if ((pa[0xC] & GRUB_NTFS_FLAG_COMPRESSED) + && !(at->flags & GRUB_NTFS_AF_GPOS)) { if (!cached) return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed"); - if (at->sbuf) - { - if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == at->save_pos) - { - grub_disk_addr_t n; - - n = GRUB_NTFS_COM_LEN - (ofs - at->save_pos); - if (n > len) - n = len; - - grub_memcpy (dest, at->sbuf + ofs - at->save_pos, n); - if (n == len) - return 0; - - dest += n; - len -= n; - ofs += n; - } - } - else - { - at->sbuf = grub_malloc (GRUB_NTFS_COM_LEN); - if (at->sbuf == NULL) - return grub_errno; - at->save_pos = 1; - } - - vcn = ctx->target_vcn = (ofs >> GRUB_NTFS_COM_LOG_LEN) * (GRUB_NTFS_COM_SEC / ctx->comp.spc); - ctx->target_vcn &= ~0xFULL; + return (grub_ntfscomp_func) ? grub_ntfscomp_func (dest, ofs, len, ctx) + : grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), + "ntfscomp"); } - else - vcn = ctx->target_vcn = grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, 0); - ctx->next_vcn = u32at (pa, 0x10); - ctx->curr_lcn = 0; + ctx->target_vcn = ofs >> (GRUB_NTFS_BLK_SHR + ctx->comp.log_spc); while (ctx->next_vcn <= ctx->target_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -459,71 +417,60 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_disk_addr_t st0, st1; grub_uint64_t m; - grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, &m); + m = (ofs >> GRUB_NTFS_BLK_SHR) & ((1 << ctx->comp.log_spc) - 1); st0 = - (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m; + ((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) + m; st1 = st0 + 1; if (st1 == - (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc) + (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) { if (grub_ntfs_read_run_list (ctx)) return grub_errno; - st1 = ctx->curr_lcn * ctx->comp.spc; + st1 = ctx->curr_lcn << ctx->comp.log_spc; } grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0)); grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1)); return 0; } - if (!(ctx->flags & GRUB_NTFS_RF_COMP)) - { - unsigned int pow; - - if (!grub_fshelp_log2blksize (ctx->comp.spc, &pow)) - grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx, - read_hook, ofs, len, dest, - grub_ntfs_read_block, ofs + len, pow, 0); - return grub_errno; - } - - return (grub_ntfscomp_func) ? grub_ntfscomp_func (at, dest, ofs, len, ctx, - vcn) : - grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), - "ntfscomp"); + grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx, + read_hook, read_hook_data, ofs, len, + (char *) dest, + grub_ntfs_read_block, ofs + len, + ctx->comp.log_spc, 0); + return grub_errno; } static grub_err_t -read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, +read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { - char *save_cur; - unsigned char attr; - char *pp; + grub_uint8_t *save_cur; + grub_uint8_t attr; + grub_uint8_t *pp; grub_err_t ret; save_cur = at->attr_cur; at->attr_nxt = at->attr_cur; - attr = (unsigned char) *at->attr_nxt; + attr = *at->attr_nxt; if (at->flags & GRUB_NTFS_AF_ALST) { - char *pa; + grub_uint8_t *pa; grub_disk_addr_t vcn; /* If compression is possible make sure that we include possible compressed block size. */ - if (GRUB_NTFS_COM_SEC >= at->mft->data->spc) + if (GRUB_NTFS_LOG_COM_SEC >= at->mft->data->log_spc) vcn = ((ofs >> GRUB_NTFS_COM_LOG_LEN) - * (GRUB_NTFS_COM_SEC / at->mft->data->spc)) & ~0xFULL; + << (GRUB_NTFS_LOG_COM_SEC - at->mft->data->log_spc)) & ~0xFULL; else - vcn = grub_divmod64 (ofs, at->mft->data->spc << GRUB_NTFS_BLK_SHR, 0); + vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR); pa = at->attr_nxt + u16at (at->attr_nxt, 4); while (pa < at->attr_end) { - if ((unsigned char) *pa != attr) + if (*pa != attr) break; if (u32at (pa, 8) > vcn) break; @@ -533,7 +480,8 @@ read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, } pp = find_attr (at, attr); if (pp) - ret = read_data (at, pp, dest, ofs, len, cached, read_hook); + ret = read_data (at, pp, dest, ofs, len, cached, + read_hook, read_hook_data); else ret = (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS, @@ -543,17 +491,17 @@ read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, } static grub_err_t -read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno) +read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, grub_uint64_t mftno) { if (read_attr (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR), - data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) - return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno); - return fixup (buf, data->mft_size, "FILE"); + data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0)) + return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%llx fails", (unsigned long long) mftno); + return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE"); } static grub_err_t -init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) +init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno) { unsigned short flag; @@ -568,15 +516,17 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) flag = u16at (mft->buf, 0x16); if ((flag & 1) == 0) - return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%X is not in use", mftno); + return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%llx is not in use", + (unsigned long long) mftno); if ((flag & 2) == 0) { - char *pa; + grub_uint8_t *pa; pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_DATA); if (pa == NULL) - return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno); + return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%llx", + (unsigned long long) mftno); if (!pa[8]) mft->size = u32at (pa, 0x10); @@ -599,25 +549,45 @@ free_file (struct grub_ntfs_file *mft) grub_free (mft->buf); } -static int -list_file (struct grub_ntfs_file *diro, char *pos, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) +static char * +get_utf8 (grub_uint8_t *in, grub_size_t len) { - char *np; + grub_uint8_t *buf; + grub_uint16_t *tmp; + grub_size_t i; + + buf = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); + tmp = grub_malloc (len * sizeof (tmp[0])); + if (!buf || !tmp) + { + grub_free (buf); + grub_free (tmp); + return NULL; + } + for (i = 0; i < len; i++) + tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (in + 2 * i)); + *grub_utf16_to_utf8 (buf, tmp, len) = '\0'; + grub_free (tmp); + return (char *) buf; +} + +static int +list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + grub_uint8_t *np; int ns; while (1) { - char *ustr, namespace; + grub_uint8_t namespace; + char *ustr; if (pos[0xC] & 2) /* end signature */ break; np = pos + 0x50; - ns = (unsigned char) *(np++); + ns = *(np++); namespace = *(np++); /* @@ -630,12 +600,6 @@ list_file (struct grub_ntfs_file *diro, char *pos, struct grub_ntfs_file *fdiro; grub_uint32_t attr; - if (u16at (pos, 4)) - { - grub_error (GRUB_ERR_BAD_FS, "64-bit MFT number"); - return 0; - } - attr = u32at (pos, 0x48); if (attr & GRUB_NTFS_ATTR_REPARSE) type = GRUB_FSHELP_SYMLINK; @@ -649,25 +613,16 @@ list_file (struct grub_ntfs_file *diro, char *pos, return 0; fdiro->data = diro->data; - fdiro->ino = u32at (pos, 0); + fdiro->ino = u64at (pos, 0) & 0xffffffffffffULL; fdiro->mtime = u64at (pos, 0x20); - ustr = grub_malloc (ns * GRUB_MAX_UTF8_PER_UTF16 + 1); + ustr = get_utf8 (np, ns); if (ustr == NULL) return 0; - { - grub_uint16_t tmp[ns]; - int i; - for (i = 0; i < ns; i++) - tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 ((char *) np - + 2 * i)); - - *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, tmp, ns) = '\0'; - } if (namespace) type |= GRUB_FSHELP_CASE_INSENSITIVE; - if (hook (ustr, type, fdiro)) + if (hook (ustr, type, fdiro, hook_data)) { grub_free (ustr); return 1; @@ -696,11 +651,10 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) struct grub_ntfs_file *mft; struct symlink_descriptor symdesc; grub_err_t err; - grub_uint16_t *buf16; + grub_uint8_t *buf16; char *buf, *end; grub_size_t len; - grub_size_t i; - char *pa; + grub_uint8_t *pa; grub_size_t off; mft = (struct grub_ntfs_file *) node; @@ -715,12 +669,13 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK); if (pa == NULL) { - grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%X", mft->ino); + grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%llx", + (unsigned long long) mft->ino); return NULL; } - err = read_attr (&mft->attr, (char *) &symdesc, 0, - sizeof (struct symlink_descriptor), 1, 0); + err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0, + sizeof (struct symlink_descriptor), 1, 0, 0); if (err) return NULL; @@ -746,26 +701,22 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) if (!buf16) return NULL; - err = read_attr (&mft->attr, (char *) buf16, off, len, 1, 0); + err = read_attr (&mft->attr, buf16, off, len, 1, 0, 0); if (err) return NULL; - buf = grub_malloc (len * 2 + 1); + buf = get_utf8 (buf16, len / 2); if (!buf) { grub_free (buf16); return NULL; } + grub_free (buf16); - for (i = 0; i < len / 2; i++) - { - buf16[i] = grub_le_to_cpu16 (buf16[i]); - if (buf16[i] == '\\') - buf16[i] = '/'; - } + for (end = buf; *end; end++) + if (*end == '\\') + *end = '/'; - end = (char *) grub_utf16_to_utf8 ((grub_uint8_t *) buf, buf16, len / 2); - *end = '\0'; /* Split the sequence to avoid GCC thinking that this is a trigraph. */ if (grub_memcmp (buf, "/?" "?/", 4) == 0 && buf[5] == ':' && buf[6] == '/' && grub_isalpha (buf[4])) @@ -778,14 +729,11 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) static int grub_ntfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { - unsigned char *bitmap; + grub_uint8_t *bitmap; struct grub_ntfs_attr attr, *at; - char *cur_pos, *indx, *bmp; + grub_uint8_t *cur_pos, *indx, *bmp; int ret = 0; grub_size_t bitmap_len; struct grub_ntfs_file *mft; @@ -824,7 +772,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, } cur_pos += 0x10; /* Skip index root */ - ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook); + ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data); if (ret) goto done; @@ -836,7 +784,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, { int ofs; - ofs = (unsigned char) cur_pos[0xA]; + ofs = cur_pos[0xA]; /* Namelen=4, Name="$I30" */ if ((cur_pos[9] == 4) && (u32at (cur_pos, ofs) == 0x490024) && @@ -853,12 +801,12 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (is_resident) { - grub_memcpy (bmp, (char *) (cur_pos + u16at (cur_pos, 0x14)), + grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14), bitmap_len); } else { - if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0)) + if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0)) { grub_error (GRUB_ERR_BAD_FS, "fails to read non-resident $BITMAP"); @@ -867,7 +815,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, bitmap_len = u32at (cur_pos, 0x30); } - bitmap = (unsigned char *) bmp; + bitmap = bmp; break; } } @@ -892,7 +840,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (bitmap) { - grub_disk_addr_t v, i; + grub_disk_addr_t i; + grub_uint8_t v; indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR); if (indx == NULL) @@ -905,15 +854,17 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, { if ((read_attr (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR), - (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0)) - || (fixup (indx, mft->data->idx_size, "INDX"))) + (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0)) + || (fixup (indx, mft->data->idx_size, + (const grub_uint8_t *) "INDX"))) goto done; - ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook); + ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], + hook, hook_data); if (ret) goto done; } v <<= 1; - if (v >= 0x100) + if (!v) { v = 1; bitmap++; @@ -934,6 +885,7 @@ grub_ntfs_mount (grub_disk_t disk) { struct grub_ntfs_bpb bpb; struct grub_ntfs_data *data = 0; + grub_uint32_t spc; if (!disk) goto fail; @@ -955,23 +907,26 @@ grub_ntfs_mount (grub_disk_t disk) || (bpb.bytes_per_sector & (bpb.bytes_per_sector - 1)) != 0) goto fail; - data->spc = (((grub_uint32_t) bpb.sectors_per_cluster - * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector)) - >> GRUB_NTFS_BLK_SHR); - if (!data->spc) + spc = (((grub_uint32_t) bpb.sectors_per_cluster + * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector)) + >> GRUB_NTFS_BLK_SHR); + if (spc == 0) goto fail; + for (data->log_spc = 0; (1U << data->log_spc) < spc; data->log_spc++); + if (bpb.clusters_per_mft > 0) - data->mft_size = data->spc * bpb.clusters_per_mft; + data->mft_size = ((grub_disk_addr_t) bpb.clusters_per_mft) << data->log_spc; else - data->mft_size = 1 << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); + data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); if (bpb.clusters_per_index > 0) - data->idx_size = data->spc * bpb.clusters_per_index; + data->idx_size = (((grub_disk_addr_t) bpb.clusters_per_index) + << data->log_spc); else - data->idx_size = 1 << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); + data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); - data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc; + data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) << data->log_spc; if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX)) goto fail; @@ -989,7 +944,7 @@ grub_ntfs_mount (grub_disk_t disk) data->uuid = grub_le_to_cpu64 (bpb.num_serial); - if (fixup (data->mmft.buf, data->mft_size, "FILE")) + if (fixup (data->mmft.buf, data->mft_size, (const grub_uint8_t *) "FILE")) goto fail; if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA)) @@ -1012,33 +967,39 @@ fail: return 0; } +/* Context for grub_ntfs_dir. */ +struct grub_ntfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_ntfs_dir. */ +static int +grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_ntfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_divmod64 (node->mtime, 10000000, 0) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_ntfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_ntfs_dir_ctx ctx = { hook, hook_data }; struct grub_ntfs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = grub_divmod64 (node->mtime, 10000000, 0) - - 86400ULL * 365 * (1970 - 1601) - - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_ntfs_mount (device->disk); @@ -1051,7 +1012,7 @@ grub_ntfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_ntfs_iterate_dir (fdiro, iterate); + grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx); fail: if ((fdiro) && (fdiro != &data->cmft)) @@ -1129,7 +1090,8 @@ grub_ntfs_read (grub_file_t file, char *buf, grub_size_t len) if (file->read_hook) mft->attr.save_pos = 1; - read_attr (&mft->attr, buf, file->offset, len, 1, file->read_hook); + read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1, + file->read_hook, file->read_hook_data); return (grub_errno) ? -1 : (grub_ssize_t) len; } @@ -1157,7 +1119,7 @@ grub_ntfs_label (grub_device_t device, char **label) { struct grub_ntfs_data *data = 0; struct grub_fshelp_node *mft = 0; - char *pa; + grub_uint8_t *pa; grub_dl_ref (my_mod); @@ -1187,21 +1149,11 @@ grub_ntfs_label (grub_device_t device, char **label) pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME); if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) { - char *buf; int len; len = u32at (pa, 0x10) / 2; - buf = grub_malloc (len * 4 + 1); pa += u16at (pa, 0x14); - { - grub_uint16_t tmp[len]; - int i; - for (i = 0; i < len; i++) - tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (pa + 2 * i)); - *grub_utf16_to_utf8 ((grub_uint8_t *) buf, tmp, len) = - '\0'; - } - *label = buf; + *label = get_utf8 (pa, len); } fail: diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c index ec359fa9d..2e1ce51a8 100644 --- a/grub-core/fs/ntfscomp.c +++ b/grub-core/fs/ntfscomp.c @@ -33,8 +33,9 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) if (grub_disk_read (cc->disk, (cc->comp_table[cc->comp_head].next_lcn - - (cc->comp_table[cc->comp_head].next_vcn - cc->cbuf_vcn)) * cc->spc, 0, - cc->spc << GRUB_NTFS_BLK_SHR, cc->cbuf)) + (cc->comp_table[cc->comp_head].next_vcn - cc->cbuf_vcn)) << cc->log_spc, + 0, + 1 << (cc->log_spc + GRUB_NTFS_BLK_SHR), cc->cbuf)) return grub_errno; cc->cbuf_vcn++; if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head].next_vcn)) @@ -44,21 +45,21 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) } static grub_err_t -decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res) +decomp_getch (struct grub_ntfs_comp *cc, grub_uint8_t *res) { - if (cc->cbuf_ofs >= (cc->spc << GRUB_NTFS_BLK_SHR)) + if (cc->cbuf_ofs >= (1U << (cc->log_spc + GRUB_NTFS_BLK_SHR))) { if (decomp_nextvcn (cc)) return grub_errno; } - *res = (unsigned char) cc->cbuf[cc->cbuf_ofs++]; + *res = cc->cbuf[cc->cbuf_ofs++]; return 0; } static grub_err_t decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res) { - unsigned char c1 = 0, c2 = 0; + grub_uint8_t c1 = 0, c2 = 0; if ((decomp_getch (cc, &c1)) || (decomp_getch (cc, &c2))) return grub_errno; @@ -68,7 +69,7 @@ decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res) /* Decompress a block (4096 bytes) */ static grub_err_t -decomp_block (struct grub_ntfs_comp *cc, char *dest) +decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) { grub_uint16_t flg, cnt; @@ -80,7 +81,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) { if (flg & 0x8000) { - unsigned char tag; + grub_uint8_t tag; grub_uint32_t bits, copied; bits = copied = tag = 0; @@ -135,7 +136,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) } else { - unsigned char ch = 0; + grub_uint8_t ch = 0; if (decomp_getch (cc, &ch)) return grub_errno; @@ -159,7 +160,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) { int n; - n = (cc->spc << GRUB_NTFS_BLK_SHR) - cc->cbuf_ofs; + n = (1 << (cc->log_spc + GRUB_NTFS_BLK_SHR)) - cc->cbuf_ofs; if (n > cnt) n = cnt; if ((dest) && (n)) @@ -176,9 +177,9 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) } static grub_err_t -read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) +read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *buf, grub_size_t num) { - int cpb = GRUB_NTFS_COM_SEC / ctx->comp.spc; + int log_cpb = GRUB_NTFS_LOG_COM_SEC - ctx->comp.log_spc; while (num) { @@ -192,7 +193,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) return grub_error (GRUB_ERR_BAD_FS, "invalid compression block"); ctx->comp.comp_head = ctx->comp.comp_tail = 0; ctx->comp.cbuf_vcn = ctx->target_vcn; - ctx->comp.cbuf_ofs = (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + ctx->comp.cbuf_ofs = (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR)); if (ctx->target_vcn >= ctx->next_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -211,20 +212,23 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) } } - nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) / cpb; + nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) >> log_cpb; if (nn > num) nn = num; num -= nn; if (ctx->flags & GRUB_NTFS_RF_BLNK) { - ctx->target_vcn += nn * cpb; + ctx->target_vcn += nn << log_cpb; if (ctx->comp.comp_tail == 0) { if (buf) { grub_memset (buf, 0, nn * GRUB_NTFS_COM_LEN); buf += nn * GRUB_NTFS_COM_LEN; + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, nn * GRUB_NTFS_COM_LEN, + ctx->file); } } else @@ -235,13 +239,16 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) return grub_errno; if (buf) buf += GRUB_NTFS_COM_LEN; + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, GRUB_NTFS_COM_LEN, + ctx->file); nn--; } } } else { - nn *= cpb; + nn <<= log_cpb; while ((ctx->comp.comp_head < ctx->comp.comp_tail) && (nn)) { grub_disk_addr_t tt; @@ -258,10 +265,15 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) (ctx->comp.disk, (ctx->comp.comp_table[ctx->comp.comp_head].next_lcn - (ctx->comp.comp_table[ctx->comp.comp_head].next_vcn - - ctx->target_vcn)) * ctx->comp.spc, 0, - tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) + ctx->target_vcn)) << ctx->comp.log_spc, 0, + tt << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - buf += tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, + tt << (ctx->comp.log_spc + + GRUB_NTFS_BLK_SHR), + ctx->file); + buf += tt << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); } nn -= tt; if (ctx->target_vcn >= @@ -275,10 +287,15 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) if (grub_disk_read (ctx->comp.disk, (ctx->target_vcn - ctx->curr_vcn + - ctx->curr_lcn) * ctx->comp.spc, 0, - nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) + ctx->curr_lcn) << ctx->comp.log_spc, 0, + nn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - buf += nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + buf += nn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, + nn << (ctx->comp.log_spc + + GRUB_NTFS_BLK_SHR), + ctx->file); } ctx->target_vcn += nn; } @@ -288,23 +305,62 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) } static grub_err_t -ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, - grub_size_t len, struct grub_ntfs_rlst *ctx, grub_disk_addr_t vcn) +ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs, + grub_size_t len, struct grub_ntfs_rlst *ctx) { grub_err_t ret; + grub_disk_addr_t vcn; + + if (ctx->attr->sbuf) + { + if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == ctx->attr->save_pos) + { + grub_disk_addr_t n; + + n = GRUB_NTFS_COM_LEN - (ofs - ctx->attr->save_pos); + if (n > len) + n = len; + + grub_memcpy (dest, ctx->attr->sbuf + ofs - ctx->attr->save_pos, n); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, n, ctx->file); + if (n == len) + return 0; + + dest += n; + len -= n; + ofs += n; + } + } + else + { + ctx->attr->sbuf = grub_malloc (GRUB_NTFS_COM_LEN); + if (ctx->attr->sbuf == NULL) + return grub_errno; + ctx->attr->save_pos = 1; + } + + vcn = ctx->target_vcn = (ofs >> GRUB_NTFS_COM_LOG_LEN) * (GRUB_NTFS_COM_SEC >> ctx->comp.log_spc); + ctx->target_vcn &= ~0xFULL; + while (ctx->next_vcn <= ctx->target_vcn) + { + if (grub_ntfs_read_run_list (ctx)) + return grub_errno; + } ctx->comp.comp_head = ctx->comp.comp_tail = 0; - ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << GRUB_NTFS_BLK_SHR); + ctx->comp.cbuf = grub_malloc (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR)); if (!ctx->comp.cbuf) return 0; ret = 0; //ctx->comp.disk->read_hook = read_hook; + //ctx->comp.disk->read_hook_data = read_hook_data; if ((vcn > ctx->target_vcn) && (read_block - (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / GRUB_NTFS_COM_SEC))) + (ctx, NULL, (vcn - ctx->target_vcn) >> (GRUB_NTFS_LOG_COM_SEC - ctx->comp.log_spc)))) { ret = grub_errno; goto quit; @@ -313,21 +369,28 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, if (ofs % GRUB_NTFS_COM_LEN) { grub_uint32_t t, n, o; + void *file = ctx->file; - t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); - if (read_block (ctx, at->sbuf, 1)) + ctx->file = 0; + + t = ctx->target_vcn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + if (read_block (ctx, ctx->attr->sbuf, 1)) { ret = grub_errno; goto quit; } - at->save_pos = t; + ctx->file = file; + + ctx->attr->save_pos = t; o = ofs % GRUB_NTFS_COM_LEN; n = GRUB_NTFS_COM_LEN - o; if (n > len) n = len; - grub_memcpy (dest, &at->sbuf[o], n); + grub_memcpy (dest, &ctx->attr->sbuf[o], n); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, n, ctx->file); if (n == len) goto quit; dest += n; @@ -345,17 +408,21 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, if (len) { grub_uint32_t t; + void *file = ctx->file; - t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); - if (read_block (ctx, at->sbuf, 1)) + ctx->file = 0; + t = ctx->target_vcn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + if (read_block (ctx, ctx->attr->sbuf, 1)) { ret = grub_errno; goto quit; } - at->save_pos = t; + ctx->attr->save_pos = t; - grub_memcpy (dest, at->sbuf, len); + grub_memcpy (dest, ctx->attr->sbuf, len); + if (grub_file_progress_hook && file) + grub_file_progress_hook (0, 0, len, file); } quit: diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c index 5fa88e3f9..7b8a7220e 100644 --- a/grub-core/fs/odc.c +++ b/grub-core/fs/odc.c @@ -1,2 +1,61 @@ -#define MODE_ODC 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define ALIGN_CPIO(x) x + +#define MAGIC "070707" +struct head +{ + char magic[6]; + char dev[6]; + char ino[6]; + char mode[6]; + char uid[6]; + char gid[6]; + char nlink[6]; + char rdev[6]; + char mtime[11]; + char namesize[6]; + char filesize[11]; +} __attribute__ ((packed)); + +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && *str >= '0' && *str <= '7') + ret = (ret << 3) | (*str++ & 0xf); + return ret; +} + +#define FSNAME "odc" + +#include "cpio_common.c" + +GRUB_MOD_INIT (odc) +{ + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (odc) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c new file mode 100644 index 000000000..770721ab9 --- /dev/null +++ b/grub-core/fs/proc.c @@ -0,0 +1,173 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_procfs_entry *grub_procfs_entries; + +static int +grub_procdev_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + return hook ("proc", hook_data); +} + +static grub_err_t +grub_procdev_open (const char *name, grub_disk_t disk) +{ + if (grub_strcmp (name, "proc")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a procfs disk"); + + disk->total_sectors = 0; + disk->id = (unsigned long) "proc"; + + disk->data = 0; + + return GRUB_ERR_NONE; +} + +static void +grub_procdev_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_procdev_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + char *buf __attribute((unused))) +{ + return GRUB_ERR_OUT_OF_RANGE; +} + +static grub_err_t +grub_procdev_write (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), + const char *buf __attribute ((unused))) +{ + return GRUB_ERR_OUT_OF_RANGE; +} + +static grub_ssize_t +grub_procfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + char *data = file->data; + + grub_memcpy (buf, data + file->offset, len); + + return len; +} + +static grub_err_t +grub_procfs_close (grub_file_t file) +{ + char *data; + + data = file->data; + grub_free (data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_procfs_dir (grub_device_t device, const char *path, + grub_fs_dir_hook_t hook, void *hook_data) +{ + const char *ptr; + struct grub_dirhook_info info; + struct grub_procfs_entry *entry; + + grub_memset (&info, 0, sizeof (info)); + + /* Check if the disk is our dummy disk. */ + if (grub_strcmp (device->disk->name, "proc")) + return grub_error (GRUB_ERR_BAD_FS, "not a procfs"); + for (ptr = path; *ptr == '/'; ptr++); + if (*ptr) + return 0; + FOR_LIST_ELEMENTS((entry), (grub_procfs_entries)) + if (hook (entry->name, &info, hook_data)) + return 0; + return 0; +} + +static grub_err_t +grub_procfs_open (struct grub_file *file, const char *path) +{ + const char *pathptr; + struct grub_procfs_entry *entry; + + for (pathptr = path; *pathptr == '/'; pathptr++); + + FOR_LIST_ELEMENTS((entry), (grub_procfs_entries)) + if (grub_strcmp (pathptr, entry->name) == 0) + { + grub_size_t sz; + file->data = entry->get_contents (&sz); + if (!file->data) + return grub_errno; + file->size = sz; + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); +} + +static struct grub_disk_dev grub_procfs_dev = { + .name = "proc", + .id = GRUB_DISK_DEVICE_PROCFS_ID, + .iterate = grub_procdev_iterate, + .open = grub_procdev_open, + .close = grub_procdev_close, + .read = grub_procdev_read, + .write = grub_procdev_write, + .next = 0 +}; + +static struct grub_fs grub_procfs_fs = + { + .name = "procfs", + .dir = grub_procfs_dir, + .open = grub_procfs_open, + .read = grub_procfs_read, + .close = grub_procfs_close, + .next = 0 + }; + +GRUB_MOD_INIT (procfs) +{ + grub_disk_dev_register (&grub_procfs_dev); + grub_fs_register (&grub_procfs_fs); +} + +GRUB_MOD_FINI (procfs) +{ + grub_disk_dev_unregister (&grub_procfs_dev); + grub_fs_unregister (&grub_procfs_fs); +} diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index 26adf23c4..6537377ba 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -240,9 +240,8 @@ struct grub_reiserfs_data static grub_ssize_t grub_reiserfs_read_real (struct grub_fshelp_node *node, grub_off_t off, char *buf, grub_size_t len, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)); + grub_disk_read_hook_t read_hook, + void *read_hook_data); /* Internal-only functions. Not to be used outside of this file. */ @@ -674,7 +673,7 @@ grub_reiserfs_read_symlink (grub_fshelp_node_t node) if (! symlink_buffer) return 0; - ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0); + ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0); if (ret < 0) { grub_free (symlink_buffer); @@ -718,10 +717,8 @@ grub_reiserfs_mount (grub_disk_t disk) /* Call HOOK for each file in directory ITEM. */ static int grub_reiserfs_iterate_dir (grub_fshelp_node_t item, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, + void *hook_data) { struct grub_reiserfs_data *data = item->data; struct grub_reiserfs_block_header *block_header = 0; @@ -784,7 +781,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, = grub_le_to_cpu16 (directory_header->state); grub_fshelp_node_t entry_item; struct grub_reiserfs_key entry_key; - enum grub_reiserfs_item_type entry_type; + enum grub_fshelp_filetype entry_type; char *entry_name; if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK)) @@ -946,7 +943,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, goto next; } } - if (hook (entry_name, entry_type, entry_item)) + if (hook (entry_name, entry_type, entry_item, hook_data)) { grub_dprintf ("reiserfs", "Found : %s, type=%d\n", entry_name, entry_type); @@ -1038,9 +1035,7 @@ grub_reiserfs_open (struct grub_file *file, const char *name) static grub_ssize_t grub_reiserfs_read_real (struct grub_fshelp_node *node, grub_off_t off, char *buf, grub_size_t len, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { unsigned int indirect_block, indirect_block_count; struct grub_reiserfs_key key; @@ -1107,6 +1102,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, (unsigned) block, (unsigned) offset, (unsigned) (offset + length)); found.data->disk->read_hook = read_hook; + found.data->disk->read_hook_data = read_hook_data; grub_disk_read (found.data->disk, block, offset @@ -1133,6 +1129,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, if (grub_errno) goto fail; found.data->disk->read_hook = read_hook; + found.data->disk->read_hook_data = read_hook_data; for (indirect_block = 0; indirect_block < indirect_block_count && current_position < final_position; @@ -1238,7 +1235,7 @@ static grub_ssize_t grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) { return grub_reiserfs_read_real (file->data, file->offset, buf, len, - file->read_hook); + file->read_hook, file->read_hook_data); } /* Close the file FILE. */ @@ -1254,32 +1251,40 @@ grub_reiserfs_close (grub_file_t file) return GRUB_ERR_NONE; } +/* Context for grub_reiserfs_dir. */ +struct grub_reiserfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_reiserfs_dir. */ +static int +grub_reiserfs_dir_iter (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_reiserfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = node->mtime; + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + /* Call HOOK with each file under DIR. */ static grub_err_t grub_reiserfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_reiserfs_dir_ctx ctx = { hook, hook_data }; struct grub_reiserfs_data *data = 0; struct grub_fshelp_node root, *found; struct grub_reiserfs_key root_key; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = node->mtime; - grub_free (node); - return hook (filename, &info); - } grub_dl_ref (my_mod); data = grub_reiserfs_mount (device->disk); if (! data) @@ -1300,7 +1305,7 @@ grub_reiserfs_dir (grub_device_t device, const char *path, grub_reiserfs_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_reiserfs_iterate_dir (found, iterate); + grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx); grub_free (data); grub_dl_unref (my_mod); return GRUB_ERR_NONE; diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index b30caef35..2e3544408 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -171,10 +171,7 @@ grub_romfs_read_symlink (grub_fshelp_node_t node) static int grub_romfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_disk_addr_t caddr; struct grub_romfs_file_header hdr; @@ -306,7 +303,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, } } - if (hook ((char *) name, filetype, node)) + if (hook ((char *) name, filetype, node, hook_data)) { grub_free (name); return 1; @@ -316,30 +313,36 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, return 0; } +/* Context for grub_romfs_dir. */ +struct grub_romfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_romfs_dir. */ +static int +grub_romfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_romfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_romfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_romfs_dir_ctx ctx = { hook, hook_data }; struct grub_romfs_data *data = 0; struct grub_fshelp_node *fdiro = 0, start; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); - } - data = grub_romfs_mount (device); if (! data) goto fail; @@ -352,7 +355,7 @@ grub_romfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_romfs_iterate_dir (fdiro, iterate); + grub_romfs_iterate_dir (fdiro, grub_romfs_dir_iter, &ctx); fail: grub_free (data); @@ -396,6 +399,7 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len) /* XXX: The file is stored in as a single extent. */ data->data->disk->read_hook = file->read_hook; + data->data->disk->read_hook_data = file->read_hook_data; grub_disk_read (data->data->disk, (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS, (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index f7cdb0898..e7d2f72f3 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -345,11 +345,11 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_sfs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_sfs_read_block, node->size, node->data->log_blocksize, 0); } @@ -460,12 +460,48 @@ grub_sfs_read_symlink (grub_fshelp_node_t node) return symlink; } +/* Helper for grub_sfs_iterate_dir. */ +static int +grub_sfs_create_node (struct grub_fshelp_node **node, + struct grub_sfs_data *data, + const char *name, + grub_uint32_t block, grub_uint32_t size, int type, + grub_uint32_t mtime, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + grub_size_t len = grub_strlen (name); + grub_uint8_t *name_u8; + int ret; + *node = grub_malloc (sizeof (**node)); + if (!*node) + return 1; + name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + if (!name_u8) + { + grub_free (*node); + return 1; + } + + (*node)->data = data; + (*node)->size = size; + (*node)->block = block; + (*node)->mtime = mtime; + (*node)->cache = 0; + (*node)->cache_off = 0; + (*node)->next_extent = block; + (*node)->cache_size = 0; + (*node)->cache_allocated = 0; + + *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0'; + + ret = hook ((char *) name_u8, type | data->fshelp_flags, *node, hook_data); + grub_free (name_u8); + return ret; +} + static int grub_sfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_fshelp_node *node = 0; struct grub_sfs_data *data = dir->data; @@ -474,46 +510,6 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, unsigned int next = dir->block; grub_uint32_t pos; - auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, - grub_uint32_t block, - grub_uint32_t size, int type, - grub_uint32_t mtime); - - int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, - grub_uint32_t block, - grub_uint32_t size, int type, - grub_uint32_t mtime) - { - grub_size_t len = grub_strlen (name); - grub_uint8_t *name_u8; - int ret; - node = grub_malloc (sizeof (*node)); - if (!node) - return 1; - name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); - if (!name_u8) - { - grub_free (node); - return 1; - } - - node->data = data; - node->size = size; - node->block = block; - node->mtime = mtime; - node->cache = 0; - node->cache_off = 0; - node->next_extent = block; - node->cache_size = 0; - node->cache_allocated = 0; - - *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0'; - - ret = hook ((char *) name_u8, type | data->fshelp_flags, node); - grub_free (name_u8); - return ret; - } - objc_data = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize); if (!objc_data) goto fail; @@ -570,9 +566,10 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, else block = grub_be_to_cpu32 (obj->file_dir.file.first_block); - if (grub_sfs_create_node (filename, block, + if (grub_sfs_create_node (&node, data, filename, block, grub_be_to_cpu32 (obj->file_dir.file.size), - type, grub_be_to_cpu32 (obj->mtime))) + type, grub_be_to_cpu32 (obj->mtime), + hook, hook_data)) { grub_free (objc_data); return 1; @@ -649,37 +646,44 @@ grub_sfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_sfs_data *data = (struct grub_sfs_data *) file->data; - return grub_sfs_read_file (&data->diropen, file->read_hook, + return grub_sfs_read_file (&data->diropen, + file->read_hook, file->read_hook_data, file->offset, len, buf); } +/* Context for grub_sfs_dir. */ +struct grub_sfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_sfs_dir. */ +static int +grub_sfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_sfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; + info.mtimeset = 1; + grub_free (node->cache); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_sfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_sfs_dir_ctx ctx = { hook, hook_data }; struct grub_sfs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; - info.mtimeset = 1; - grub_free (node->cache); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_sfs_mount (device->disk); @@ -691,7 +695,7 @@ grub_sfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_sfs_iterate_dir (fdiro, iterate); + grub_sfs_iterate_dir (fdiro, grub_sfs_dir_iter, &ctx); fail: if (data && fdiro != &data->diropen) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 44af0f82a..cb3cc3a6e 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -478,10 +478,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node) static int grub_squash_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_uint32_t off; grub_uint32_t endoff; @@ -514,7 +511,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, return 0; grub_memcpy (node, dir, sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); - if (hook (".", GRUB_FSHELP_DIR, node)) + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) return 1; if (dir->stsize != 1) @@ -536,7 +533,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, if (err) return 0; - if (hook ("..", GRUB_FSHELP_DIR, node)) + if (hook ("..", GRUB_FSHELP_DIR, node, hook_data)) return 1; } } @@ -604,7 +601,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk); node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset); node->stsize++; - r = hook (buf, filetype, node); + r = hook (buf, filetype, node, hook_data); grub_free (buf); if (r) @@ -640,28 +637,34 @@ squash_unmount (struct grub_squash_data *data) } +/* Context for grub_squash_dir. */ +struct grub_squash_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_squash_dir. */ +static int +grub_squash_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_squash_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (node->ino.mtime); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_squash_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = grub_le_to_cpu32 (node->ino.mtime); - grub_free (node); - return hook (filename, &info); - } - + struct grub_squash_dir_ctx ctx = { hook, hook_data }; struct grub_squash_data *data = 0; struct grub_fshelp_node *fdiro = 0; struct grub_fshelp_node root; @@ -678,7 +681,7 @@ grub_squash_dir (grub_device_t device, const char *path, grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir, grub_squash_read_symlink, GRUB_FSHELP_DIR); if (!grub_errno) - grub_squash_iterate_dir (fdiro, iterate); + grub_squash_iterate_dir (fdiro, grub_squash_dir_iter, &ctx); squash_unmount (data); diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c index 6ab62bca7..7d25791e8 100644 --- a/grub-core/fs/tar.c +++ b/grub-core/fs/tar.c @@ -1,2 +1,345 @@ -#define MODE_USTAR 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* tar support */ +#define MAGIC "ustar" +struct head +{ + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; +} __attribute__ ((packed)); + +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && *str >= '0' && *str <= '7') + ret = (ret << 3) | (*str++ & 0xf); + return ret; +} + +struct grub_archelp_data +{ + grub_disk_t disk; + grub_off_t hofs, next_hofs; + grub_off_t dofs; + grub_off_t size; + char *linkname; + grub_size_t linkname_alloc; +}; + +static grub_err_t +grub_cpio_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, + grub_uint32_t *mode) +{ + struct head hd; + int reread = 0, have_longname = 0, have_longlink = 0; + + data->hofs = data->next_hofs; + + for (reread = 0; reread < 3; reread++) + { + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (!hd.name[0] && !hd.prefix[0]) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) + return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); + + if (hd.typeflag == 'L') + { + grub_err_t err; + grub_size_t namesize = read_number (hd.size, sizeof (hd.size)); + *name = grub_malloc (namesize + 1); + if (*name == NULL) + return grub_errno; + err = grub_disk_read (data->disk, 0, + data->hofs + GRUB_DISK_SECTOR_SIZE, namesize, + *name); + (*name)[namesize] = 0; + if (err) + return err; + data->hofs += GRUB_DISK_SECTOR_SIZE + + ((namesize + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + have_longname = 1; + continue; + } + + if (hd.typeflag == 'K') + { + grub_err_t err; + grub_size_t linksize = read_number (hd.size, sizeof (hd.size)); + if (data->linkname_alloc < linksize + 1) + { + char *n; + n = grub_malloc (2 * (linksize + 1)); + if (!n) + return grub_errno; + grub_free (data->linkname); + data->linkname = n; + data->linkname_alloc = 2 * (linksize + 1); + } + + err = grub_disk_read (data->disk, 0, + data->hofs + GRUB_DISK_SECTOR_SIZE, linksize, + data->linkname); + if (err) + return err; + data->linkname[linksize] = 0; + data->hofs += GRUB_DISK_SECTOR_SIZE + + ((linksize + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + have_longlink = 1; + continue; + } + + if (!have_longname) + { + grub_size_t extra_size = 0; + + while (extra_size < sizeof (hd.prefix) + && hd.prefix[extra_size]) + extra_size++; + *name = grub_malloc (sizeof (hd.name) + extra_size + 2); + if (*name == NULL) + return grub_errno; + if (hd.prefix[0]) + { + grub_memcpy (*name, hd.prefix, extra_size); + (*name)[extra_size++] = '/'; + } + grub_memcpy (*name + extra_size, hd.name, sizeof (hd.name)); + (*name)[extra_size + sizeof (hd.name)] = 0; + } + + data->size = read_number (hd.size, sizeof (hd.size)); + data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; + data->next_hofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + if (mtime) + *mtime = read_number (hd.mtime, sizeof (hd.mtime)); + if (mode) + { + *mode = read_number (hd.mode, sizeof (hd.mode)); + switch (hd.typeflag) + { + /* Hardlink. */ + case '1': + /* Symlink. */ + case '2': + *mode |= GRUB_ARCHELP_ATTR_LNK; + break; + case '0': + *mode |= GRUB_ARCHELP_ATTR_FILE; + break; + case '5': + *mode |= GRUB_ARCHELP_ATTR_DIR; + break; + } + } + if (!have_longlink) + { + if (data->linkname_alloc < 101) + { + char *n; + n = grub_malloc (101); + if (!n) + return grub_errno; + grub_free (data->linkname); + data->linkname = n; + data->linkname_alloc = 101; + } + grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname)); + data->linkname[100] = 0; + } + return GRUB_ERR_NONE; + } + return GRUB_ERR_NONE; +} + +static char * +grub_cpio_get_link_target (struct grub_archelp_data *data) +{ + return grub_strdup (data->linkname); +} + +static void +grub_cpio_rewind (struct grub_archelp_data *data) +{ + data->next_hofs = 0; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_cpio_find_file, + .get_link_target = grub_cpio_get_link_target, + .rewind = grub_cpio_rewind + }; + +static struct grub_archelp_data * +grub_cpio_mount (grub_disk_t disk) +{ + struct head hd; + struct grub_archelp_data *data; + + if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) + goto fail; + + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) + goto fail; + + data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data)); + if (!data) + goto fail; + + data->disk = disk; + + return data; + +fail: + grub_error (GRUB_ERR_BAD_FS, "not a tarfs filesystem"); + return 0; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_dir (data, &arcops, + path_in, hook, hook_data); + + grub_free (data->linkname); + grub_free (data); + + return err; +} + +static grub_err_t +grub_cpio_open (grub_file_t file, const char *name_in) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (file->device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_open (data, &arcops, name_in); + if (err) + { + grub_free (data->linkname); + grub_free (data); + } + else + { + file->data = data; + file->size = data->size; + } + return err; +} + +static grub_ssize_t +grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_archelp_data *data; + grub_ssize_t ret; + + data = file->data; + + data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; + ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : (grub_ssize_t) len; + data->disk->read_hook = 0; + + return ret; +} + +static grub_err_t +grub_cpio_close (grub_file_t file) +{ + struct grub_archelp_data *data; + + data = file->data; + grub_free (data->linkname); + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_cpio_fs = { + .name = "tarfs", + .dir = grub_cpio_dir, + .open = grub_cpio_open, + .read = grub_cpio_read, + .close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, + .blocklist_install = 0, +#endif +}; + +GRUB_MOD_INIT (tar) +{ + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (tar) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 8e28d41e2..60ce92830 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -27,6 +27,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -215,6 +216,7 @@ struct grub_udf_file_ident struct grub_udf_tag tag; grub_uint16_t version_num; grub_uint8_t characteristics; +#define MAX_FILE_IDENT_LENGTH 256 grub_uint8_t file_ident_length; struct grub_udf_long_ad icb; grub_uint16_t imp_use_length; @@ -564,9 +566,7 @@ fail: static grub_ssize_t grub_udf_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR - (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK) @@ -591,10 +591,11 @@ grub_udf_read_file (grub_fshelp_node_t node, return 0; } - return grub_fshelp_read_file (node->data->disk, node, read_hook, - pos, len, buf, grub_udf_read_block, - U64 (node->block.fe.file_size), - node->data->lbshift, 0); + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, + pos, len, buf, grub_udf_read_block, + U64 (node->block.fe.file_size), + node->data->lbshift, 0); } static unsigned sblocklist[] = { 256, 512, 0 }; @@ -801,6 +802,24 @@ fail: return 0; } +#ifdef GRUB_UTIL +grub_disk_addr_t +grub_udf_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn) +{ + grub_disk_addr_t ret; + static struct grub_udf_data *data; + + data = grub_udf_mount (disk); + if (!data) + return 0; + + ret = U32 (data->pds[data->pms[0]->type1.part_num].start); + *sec_per_lcn = 1ULL << data->lbshift; + grub_free (data); + return ret; +} +#endif + static char * read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) { @@ -843,10 +862,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) static int grub_udf_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_fshelp_node_t child; struct grub_udf_file_ident dirent; @@ -859,12 +875,12 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, /* The current directory is not stored. */ grub_memcpy (child, dir, get_fshelp_size (dir->data)); - if (hook (".", GRUB_FSHELP_DIR, child)) + if (hook (".", GRUB_FSHELP_DIR, child, hook_data)) return 1; while (offset < U64 (dir->block.fe.file_size)) { - if (grub_udf_read_file (dir, 0, offset, sizeof (dirent), + if (grub_udf_read_file (dir, 0, 0, offset, sizeof (dirent), (char *) &dirent) != sizeof (dirent)) return 0; @@ -887,21 +903,21 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT) { /* This is the parent directory. */ - if (hook ("..", GRUB_FSHELP_DIR, child)) + if (hook ("..", GRUB_FSHELP_DIR, child, hook_data)) return 1; } else { enum grub_fshelp_filetype type; char *filename; - grub_uint8_t raw[dirent.file_ident_length]; + grub_uint8_t raw[MAX_FILE_IDENT_LENGTH]; type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); if (child->block.fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK) type = GRUB_FSHELP_SYMLINK; - if ((grub_udf_read_file (dir, 0, offset, + if ((grub_udf_read_file (dir, 0, 0, offset, dirent.file_ident_length, (char *) raw)) != dirent.file_ident_length) @@ -911,7 +927,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, if (!filename) grub_print_error (); - if (filename && hook (filename, type, child)) + if (filename && hook (filename, type, child, hook_data)) { grub_free (filename); return 1; @@ -940,7 +956,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node) raw = grub_malloc (sz); if (!raw) return NULL; - if (grub_udf_read_file (node, NULL, 0, sz, (char *) raw) < 0) + if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0) { grub_free (raw); return NULL; @@ -1012,58 +1028,64 @@ grub_udf_read_symlink (grub_fshelp_node_t node) return NULL; } +/* Context for grub_udf_dir. */ +struct grub_udf_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_udf_dir. */ +static int +grub_udf_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_udf_dir_ctx *ctx = data; + struct grub_dirhook_info info; + const struct grub_udf_timestamp *tstamp = NULL; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) + tstamp = &node->block.fe.modification_time; + else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE) + tstamp = &node->block.efe.modification_time; + + if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000) + { + grub_int16_t tz; + struct grub_datetime datetime; + + datetime.year = U16 (tstamp->year); + datetime.month = tstamp->month; + datetime.day = tstamp->day; + datetime.hour = tstamp->hour; + datetime.minute = tstamp->minute; + datetime.second = tstamp->second; + + tz = U16 (tstamp->type_and_timezone) & 0xfff; + if (tz & 0x800) + tz |= 0xf000; + if (tz == -2047) + tz = 0; + + info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); + + info.mtime -= 60 * tz; + } + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_udf_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_udf_dir_ctx ctx = { hook, hook_data }; struct grub_udf_data *data = 0; struct grub_fshelp_node *rootnode = 0; struct grub_fshelp_node *foundnode = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - const struct grub_udf_timestamp *tstamp = NULL; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) - tstamp = &node->block.fe.modification_time; - else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE) - tstamp = &node->block.efe.modification_time; - - if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000) - { - grub_int16_t tz; - struct grub_datetime datetime; - - datetime.year = U16 (tstamp->year); - datetime.month = tstamp->month; - datetime.day = tstamp->day; - datetime.hour = tstamp->hour; - datetime.minute = tstamp->minute; - datetime.second = tstamp->second; - - tz = U16 (tstamp->type_and_timezone) & 0xfff; - if (tz & 0x800) - tz |= 0xf000; - if (tz == -2047) - tz = 0; - - info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); - - info.mtime -= 60 * tz; - } - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_udf_mount (device->disk); @@ -1083,7 +1105,7 @@ grub_udf_dir (grub_device_t device, const char *path, GRUB_FSHELP_DIR)) goto fail; - grub_udf_iterate_dir (foundnode, iterate); + grub_udf_iterate_dir (foundnode, grub_udf_dir_iter, &ctx); if (foundnode != rootnode) grub_free (foundnode); @@ -1146,7 +1168,8 @@ grub_udf_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data; - return grub_udf_read_file (node, file->read_hook, file->offset, len, buf); + return grub_udf_read_file (node, file->read_hook, file->read_hook_data, + file->offset, len, buf); } static grub_err_t diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index bd0cd1f49..c9c2556d1 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -49,18 +49,46 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_UFS_VOLNAME_LEN 32 +#ifdef MODE_BIGENDIAN +#define grub_ufs_to_cpu16 grub_be_to_cpu16 +#define grub_ufs_to_cpu32 grub_be_to_cpu32 +#define grub_ufs_to_cpu64 grub_be_to_cpu64 +#define grub_cpu_to_ufs32_compile_time grub_cpu_to_be32_compile_time +#else +#define grub_ufs_to_cpu16 grub_le_to_cpu16 +#define grub_ufs_to_cpu32 grub_le_to_cpu32 +#define grub_ufs_to_cpu64 grub_le_to_cpu64 +#define grub_cpu_to_ufs32_compile_time grub_cpu_to_le32_compile_time +#endif + +#ifdef MODE_UFS2 +typedef grub_uint64_t grub_ufs_blk_t; +static inline grub_disk_addr_t +grub_ufs_to_cpu_blk (grub_ufs_blk_t blk) +{ + return grub_ufs_to_cpu64 (blk); +} +#else +typedef grub_uint32_t grub_ufs_blk_t; +static inline grub_disk_addr_t +grub_ufs_to_cpu_blk (grub_ufs_blk_t blk) +{ + return grub_ufs_to_cpu32 (blk); +} +#endif + /* Calculate in which group the inode can be found. */ -#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize)) +#define UFS_BLKSZ(sblock) (grub_ufs_to_cpu32 (sblock->bsize)) #define UFS_LOG_BLKSZ(sblock) (data->log2_blksz) #ifdef MODE_UFS2 -#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits2 (data->inode.field) +#define INODE_ENDIAN(data,field,bits1,bits2) grub_ufs_to_cpu##bits2 (data->inode.field) #else -#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits1 (data->inode.field) +#define INODE_ENDIAN(data,field,bits1,bits2) grub_ufs_to_cpu##bits1 (data->inode.field) #endif -#define INODE_SIZE(data) grub_le_to_cpu64 (data->inode.size) -#define INODE_MODE(data) grub_le_to_cpu16 (data->inode.mode) +#define INODE_SIZE(data) grub_ufs_to_cpu64 (data->inode.size) +#define INODE_MODE(data) grub_ufs_to_cpu16 (data->inode.mode) #ifdef MODE_UFS2 #define LOG_INODE_BLKSZ 3 #else @@ -139,9 +167,9 @@ struct grub_ufs_inode grub_uint64_t mtime; grub_uint64_t ctime; grub_uint64_t create_time; - grub_uint32_t atime_sec; - grub_uint32_t mtime_sec; - grub_uint32_t ctime_sec; + grub_uint32_t atime_usec; + grub_uint32_t mtime_usec; + grub_uint32_t ctime_usec; grub_uint32_t create_time_sec; grub_uint32_t gen; grub_uint32_t kernel_flags; @@ -169,9 +197,12 @@ struct grub_ufs_inode grub_uint16_t uid; grub_uint16_t gid; grub_uint64_t size; - grub_uint64_t atime; - grub_uint64_t mtime; - grub_uint64_t ctime; + grub_uint32_t atime; + grub_uint32_t atime_usec; + grub_uint32_t mtime; + grub_uint32_t mtime_usec; + grub_uint32_t ctime; + grub_uint32_t ctime_usec; union { struct @@ -226,7 +257,6 @@ static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data, static grub_disk_addr_t grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) { - struct grub_ufs_sblock *sblock = &data->sblock; unsigned long indirsz; int log2_blksz, log_indirsz; @@ -234,47 +264,41 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) if (blk < GRUB_UFS_DIRBLKS) return INODE_DIRBLOCKS (data, blk); - log2_blksz = grub_le_to_cpu32 (data->sblock.log2_blksz); + log2_blksz = grub_ufs_to_cpu32 (data->sblock.log2_blksz); blk -= GRUB_UFS_DIRBLKS; log_indirsz = data->log2_blksz - LOG_INODE_BLKSZ; indirsz = 1 << log_indirsz; + /* Single indirect block. */ if (blk < indirsz) { -#ifdef MODE_UFS2 - grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)]; -#else - grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)]; -#endif + grub_ufs_blk_t indir; grub_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 0)) << log2_blksz, - 0, sizeof (indir), indir); - return indir[blk]; + blk * sizeof (indir), sizeof (indir), &indir); + return indir; } blk -= indirsz; /* Double indirect block. */ if (blk < (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz) { -#ifdef MODE_UFS2 - grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)]; -#else - grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)]; -#endif + grub_ufs_blk_t indir; grub_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 1)) << log2_blksz, - 0, sizeof (indir), indir); + (blk >> log_indirsz) * sizeof (indir), + sizeof (indir), &indir); grub_disk_read (data->disk, - ((grub_disk_addr_t) indir [blk >> log_indirsz]) - << log2_blksz, - 0, sizeof (indir), indir); + grub_ufs_to_cpu_blk (indir) << log2_blksz, + (blk & ((1 << log_indirsz) - 1)) * sizeof (indir), + sizeof (indir), &indir); - return indir[blk & ((1 << log_indirsz) - 1)]; + return indir; } blk -= (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz; @@ -282,31 +306,28 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) /* Triple indirect block. */ if (!(blk >> (3 * log_indirsz))) { -#ifdef MODE_UFS2 - grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)]; -#else - grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)]; -#endif + grub_ufs_blk_t indir; grub_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 2)) << log2_blksz, - 0, sizeof (indir), indir); + (blk >> (2 * log_indirsz)) * sizeof (indir), + sizeof (indir), &indir); grub_disk_read (data->disk, - ((grub_disk_addr_t) indir [blk >> (2 * log_indirsz)]) - << log2_blksz, - 0, sizeof (indir), indir); + grub_ufs_to_cpu_blk (indir) << log2_blksz, + ((blk >> log_indirsz) + & ((1 << log_indirsz) - 1)) * sizeof (indir), + sizeof (indir), &indir); grub_disk_read (data->disk, - ((grub_disk_addr_t) indir [(blk >> log_indirsz) - & ((1 << log_indirsz) - 1)]) - << log2_blksz, - 0, sizeof (indir), indir); + grub_ufs_to_cpu_blk (indir) << log2_blksz, + (blk & ((1 << log_indirsz) - 1)) * sizeof (indir), + sizeof (indir), &indir); - return indir[blk & ((1 << log_indirsz) - 1)]; + return indir; } - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + grub_error (GRUB_ERR_BAD_FS, "ufs does not support quadruple indirect blocks"); return 0; } @@ -316,8 +337,7 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_ufs_read_file (struct grub_ufs_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { struct grub_ufs_sblock *sblock = &data->sblock; @@ -365,8 +385,9 @@ grub_ufs_read_file (struct grub_ufs_data *data, if (blknr) { data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, - blknr << grub_le_to_cpu32 (data->sblock.log2_blksz), + blknr << grub_ufs_to_cpu32 (data->sblock.log2_blksz), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) @@ -389,17 +410,17 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) struct grub_ufs_sblock *sblock = &data->sblock; /* Determine the group the inode is in. */ - int group = ino / grub_le_to_cpu32 (sblock->ino_per_group); + int group = ino / grub_ufs_to_cpu32 (sblock->ino_per_group); /* Determine the inode within the group. */ - int grpino = ino % grub_le_to_cpu32 (sblock->ino_per_group); + int grpino = ino % grub_ufs_to_cpu32 (sblock->ino_per_group); /* The first block of the group. */ - int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group)); + int grpblk = group * (grub_ufs_to_cpu32 (sblock->frags_per_group)); #ifndef MODE_UFS2 - grpblk += grub_le_to_cpu32 (sblock->cylg_offset) - * (group & (~grub_le_to_cpu32 (sblock->cylg_mask))); + grpblk += grub_ufs_to_cpu32 (sblock->cylg_offset) + * (group & (~grub_ufs_to_cpu32 (sblock->cylg_mask))); #endif if (!inode) @@ -409,8 +430,8 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) } grub_disk_read (data->disk, - ((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk) - << grub_le_to_cpu32 (data->sblock.log2_blksz)) + ((grub_ufs_to_cpu32 (sblock->inoblk_offs) + grpblk) + << grub_ufs_to_cpu32 (data->sblock.log2_blksz)) + grpino / UFS_INODE_PER_BLOCK, (grpino % UFS_INODE_PER_BLOCK) * sizeof (struct grub_ufs_inode), @@ -426,11 +447,15 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) static grub_err_t grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) { - char symlink[INODE_SIZE (data) + 1]; + char *symlink; + grub_size_t sz = INODE_SIZE (data); if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); + symlink = grub_malloc (sz + 1); + if (!symlink) + return grub_errno; /* Normally we should just check that data->inode.nblocks == 0. However old Linux doesn't maintain nblocks correctly and so it's always 0. If size is bigger than inline space then the symlink is surely not @@ -440,8 +465,8 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) && INODE_SIZE (data) <= sizeof (data->inode.symlink)) grub_strcpy (symlink, (char *) data->inode.symlink); else - grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink); - symlink[INODE_SIZE (data)] = '\0'; + grub_ufs_read_file (data, 0, 0, 0, sz, symlink); + symlink[sz] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') @@ -449,10 +474,15 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) /* Now load in the old inode. */ if (grub_ufs_read_inode (data, ino, 0)) - return grub_errno; + { + grub_free (symlink); + return grub_errno; + } grub_ufs_find_file (data, symlink); + grub_free (symlink); + return grub_errno; } @@ -462,95 +492,91 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data, const char *path) { - char fpath[grub_strlen (path) + 1]; - char *name = fpath; - char *next; + const char *name; + const char *next = path; unsigned int pos = 0; int dirino; + char *filename; - grub_strcpy (fpath, path); + /* We reject filenames longer than the one we're looking + for without reading, so this allocation is enough. */ + filename = grub_malloc (grub_strlen (path) + 2); + if (!filename) + return grub_errno; - /* Skip the first slash. */ - while (*name == '/') - name++; - if (!*name) - return 0; - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) - { - next[0] = '\0'; - next++; - while (*next == '/') - next++; - } - - do + while (1) { struct grub_ufs_dirent dirent; - int namelen; - if (grub_strlen (name) == 0) - return GRUB_ERR_NONE; + name = next; + /* Skip the first slash. */ + while (*name == '/') + name++; + if (*name == 0) + { + grub_free (filename); + return GRUB_ERR_NONE; + } - if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), - (char *) &dirent) < 0) - return grub_errno; + if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) + != GRUB_UFS_ATTR_DIR) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, + N_("not a directory")); + goto fail; + } + + /* Extract the actual part from the pathname. */ + for (next = name; *next && *next != '/'; next++); + for (pos = 0; ; pos += grub_ufs_to_cpu16 (dirent.direntlen)) + { + int namelen; + + if (pos >= INODE_SIZE (data)) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("file `%s' not found"), + path); + goto fail; + } + + if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent), + (char *) &dirent) < 0) + goto fail; #ifdef MODE_UFS2 - namelen = dirent.namelen_bsd; + namelen = dirent.namelen_bsd; #else - namelen = grub_le_to_cpu16 (dirent.namelen); + namelen = grub_ufs_to_cpu16 (dirent.namelen); #endif - { - char filename[namelen + 1]; - - if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), - namelen, filename) < 0) - return grub_errno; - - filename[namelen] = '\0'; - - if (!grub_strcmp (name, filename)) - { - dirino = data->ino; - grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino), 0); - - if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) - == GRUB_UFS_ATTR_LNK) - { - grub_ufs_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; - } - - if (!next) - return 0; - - pos = 0; - - name = next; - next = grub_strchr (name, '/'); - if (next) - { - next[0] = '\0'; - next++; - while (*next == '/') - next++; - } - - if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - + if (namelen < next - name) continue; - } - } - pos += grub_le_to_cpu16 (dirent.direntlen); - } while (pos < INODE_SIZE (data)); + if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent), + next - name + (namelen != next - name), + filename) < 0) + goto fail; - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + if (grub_strncmp (name, filename, next - name) == 0 + && (namelen == next - name || filename[next - name] == '\0')) + { + dirino = data->ino; + grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), 0); + + if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) + == GRUB_UFS_ATTR_LNK) + { + grub_ufs_lookup_symlink (data, dirino); + if (grub_errno) + goto fail; + } + + break; + } + } + } + fail: + grub_free (filename); return grub_errno; } @@ -576,12 +602,12 @@ grub_ufs_mount (grub_disk_t disk) /* No need to byteswap bsize in this check. It works the same on both endiannesses. */ - if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC + if (data->sblock.magic == grub_cpu_to_ufs32_compile_time (GRUB_UFS_MAGIC) && data->sblock.bsize != 0 && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0)) { for (data->log2_blksz = 0; - (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sblock.bsize); + (1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize); data->log2_blksz++); data->disk = disk; @@ -610,8 +636,7 @@ grub_ufs_mount (grub_disk_t disk) static grub_err_t grub_ufs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_ufs_data *data; unsigned int pos = 0; @@ -645,40 +670,56 @@ grub_ufs_dir (grub_device_t device, const char *path, struct grub_ufs_dirent dirent; int namelen; - if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), + if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent), (char *) &dirent) < 0) break; + if (dirent.direntlen == 0) + break; + #ifdef MODE_UFS2 namelen = dirent.namelen_bsd; #else - namelen = grub_le_to_cpu16 (dirent.namelen); + namelen = grub_ufs_to_cpu16 (dirent.namelen); #endif - { - char filename[namelen + 1]; - struct grub_dirhook_info info; - struct grub_ufs_inode inode; + char *filename = grub_malloc (namelen + 1); + if (!filename) + goto fail; + struct grub_dirhook_info info; + struct grub_ufs_inode inode; - grub_memset (&info, 0, sizeof (info)); + grub_memset (&info, 0, sizeof (info)); - if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), - namelen, filename) < 0) + if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent), + namelen, filename) < 0) + { + grub_free (filename); break; + } - filename[namelen] = '\0'; - grub_ufs_read_inode (data, dirent.ino, (char *) &inode); + filename[namelen] = '\0'; + grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), + (char *) &inode); - info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE) - == GRUB_UFS_ATTR_DIR); - info.mtime = grub_le_to_cpu64 (inode.mtime); - info.mtimeset = 1; + info.dir = ((grub_ufs_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE) + == GRUB_UFS_ATTR_DIR); +#ifdef MODE_UFS2 + info.mtime = grub_ufs_to_cpu64 (inode.mtime); +#else + info.mtime = grub_ufs_to_cpu32 (inode.mtime); +#endif + info.mtimeset = 1; - if (hook (filename, &info)) + if (hook (filename, &info, hook_data)) + { + grub_free (filename); break; - } + } - pos += grub_le_to_cpu16 (dirent.direntlen); + grub_free (filename); + + pos += grub_ufs_to_cpu16 (dirent.direntlen); } fail: @@ -730,7 +771,8 @@ grub_ufs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_ufs_data *data = (struct grub_ufs_data *) file->data; - return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf); + return grub_ufs_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } @@ -773,8 +815,8 @@ grub_ufs_uuid (grub_device_t device, char **uuid) data = grub_ufs_mount (disk); if (data && (data->sblock.uuidhi != 0 || data->sblock.uuidlow != 0)) *uuid = grub_xasprintf ("%08x%08x", - (unsigned) grub_le_to_cpu32 (data->sblock.uuidhi), - (unsigned) grub_le_to_cpu32 (data->sblock.uuidlow)); + (unsigned) grub_ufs_to_cpu32 (data->sblock.uuidhi), + (unsigned) grub_ufs_to_cpu32 (data->sblock.uuidlow)); else *uuid = NULL; @@ -799,10 +841,10 @@ grub_ufs_mtime (grub_device_t device, grub_int32_t *tm) *tm = 0; else { - *tm = grub_le_to_cpu32 (data->sblock.mtime); + *tm = grub_ufs_to_cpu32 (data->sblock.mtime); #ifdef MODE_UFS2 - if (*tm < (grub_int64_t) grub_le_to_cpu64 (data->sblock.mtime2)) - *tm = grub_le_to_cpu64 (data->sblock.mtime2); + if (*tm < (grub_int64_t) grub_ufs_to_cpu64 (data->sblock.mtime2)) + *tm = grub_ufs_to_cpu64 (data->sblock.mtime2); #endif } @@ -819,8 +861,12 @@ static struct grub_fs grub_ufs_fs = { #ifdef MODE_UFS2 .name = "ufs2", +#else +#ifdef MODE_BIGENDIAN + .name = "ufs1_be", #else .name = "ufs1", +#endif #endif .dir = grub_ufs_dir, .open = grub_ufs_open, @@ -839,8 +885,12 @@ static struct grub_fs grub_ufs_fs = #ifdef MODE_UFS2 GRUB_MOD_INIT(ufs2) #else +#ifdef MODE_BIGENDIAN +GRUB_MOD_INIT(ufs1_be) +#else GRUB_MOD_INIT(ufs1) #endif +#endif { grub_fs_register (&grub_ufs_fs); my_mod = mod; @@ -849,8 +899,12 @@ GRUB_MOD_INIT(ufs1) #ifdef MODE_UFS2 GRUB_MOD_FINI(ufs2) #else +#ifdef MODE_BIGENDIAN +GRUB_MOD_FINI(ufs1_be) +#else GRUB_MOD_FINI(ufs1) #endif +#endif { grub_fs_unregister (&grub_ufs_fs); } diff --git a/grub-core/fs/ufs_be.c b/grub-core/fs/ufs_be.c new file mode 100644 index 000000000..a58f75a99 --- /dev/null +++ b/grub-core/fs/ufs_be.c @@ -0,0 +1,2 @@ +#define MODE_BIGENDIAN 1 +#include "ufs.c" diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 2c6b00c2a..7cd3e07bf 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -285,7 +285,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) if (node->inode.format == XFS_INODE_FORMAT_BTREE) { - grub_uint64_t *keys; + const grub_uint64_t *keys; int recoffset; leaf = grub_malloc (node->data->bsize); @@ -295,9 +295,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); keys = &node->inode.data.btree.keys[0]; if (node->inode.fork_offset) - recoffset = (node->inode.fork_offset - - ((char *) &node->inode.data.btree.keys - (char *) &node->inode)) - / (2 * sizeof (grub_uint64_t)); + recoffset = (node->inode.fork_offset - 1) / 2; else recoffset = ((1 << node->data->sblock.log2_inode) - ((char *) &node->inode.data.btree.keys @@ -381,11 +379,11 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_xfs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_xfs_read_block, grub_be_to_cpu64 (node->inode.size), node->data->sblock.log2_bsize @@ -412,7 +410,7 @@ grub_xfs_read_symlink (grub_fshelp_node_t node) if (!symlink) return 0; - numread = grub_xfs_read_file (node, 0, 0, size, symlink); + numread = grub_xfs_read_file (node, 0, 0, 0, size, symlink); if (numread != size) { grub_free (symlink); @@ -443,46 +441,56 @@ grub_xfs_mode_to_filetype (grub_uint16_t mode) } +/* Context for grub_xfs_iterate_dir. */ +struct grub_xfs_iterate_dir_ctx +{ + grub_fshelp_iterate_dir_hook_t hook; + void *hook_data; + struct grub_fshelp_node *diro; +}; + +/* Helper for grub_xfs_iterate_dir. */ +static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, + struct grub_xfs_iterate_dir_ctx *ctx) +{ + struct grub_fshelp_node *fdiro; + grub_err_t err; + + fdiro = grub_malloc (sizeof (struct grub_fshelp_node) + - sizeof (struct grub_xfs_inode) + + (1 << ctx->diro->data->sblock.log2_inode) + 1); + if (!fdiro) + { + grub_print_error (); + return 0; + } + + /* The inode should be read, otherwise the filetype can + not be determined. */ + fdiro->ino = ino; + fdiro->inode_read = 1; + fdiro->data = ctx->diro->data; + err = grub_xfs_read_inode (ctx->diro->data, ino, &fdiro->inode); + if (err) + { + grub_print_error (); + return 0; + } + + return ctx->hook (filename, grub_xfs_mode_to_filetype (fdiro->inode.mode), + fdiro, ctx->hook_data); +} + static int grub_xfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename); - - int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename) - { - struct grub_fshelp_node *fdiro; - grub_err_t err; - - fdiro = grub_malloc (sizeof (struct grub_fshelp_node) - - sizeof (struct grub_xfs_inode) - + (1 << diro->data->sblock.log2_inode)); - if (!fdiro) - { - grub_print_error (); - return 0; - } - - /* The inode should be read, otherwise the filetype can - not be determined. */ - fdiro->ino = ino; - fdiro->inode_read = 1; - fdiro->data = diro->data; - err = grub_xfs_read_inode (diro->data, ino, &fdiro->inode); - if (err) - { - grub_print_error (); - return 0; - } - - return hook (filename, - grub_xfs_mode_to_filetype (fdiro->inode.mode), - fdiro); - } + struct grub_xfs_iterate_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data, + .diro = diro + }; switch (diro->inode.format) { @@ -508,10 +516,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, } /* Synthesize the direntries for `.' and `..'. */ - if (call_hook (diro->ino, ".")) + if (iterate_dir_call_hook (diro->ino, ".", &ctx)) return 1; - if (call_hook (parent, "..")) + if (iterate_dir_call_hook (parent, "..", &ctx)) return 1; for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) @@ -520,7 +528,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_uint8_t *inopos = (((grub_uint8_t *) de) + sizeof (struct grub_xfs_dir_entry) + de->len - 1); - char name[de->len + 1]; + grub_uint8_t c; /* inopos might be unaligned. */ if (smallino) @@ -539,10 +547,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, | (((grub_uint64_t) inopos[7]) << 0); ino = grub_cpu_to_be64 (ino); - grub_memcpy (name, de->name, de->len); - name[de->len] = '\0'; - if (call_hook (ino, name)) + c = de->name[de->len]; + de->name[de->len] = '\0'; + if (iterate_dir_call_hook (ino, de->name, &ctx)) return 1; + de->name[de->len] = c; de = ((struct grub_xfs_dir_entry *) (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len @@ -584,7 +593,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, struct grub_xfs_dirblock_tail *tail; tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start]; - numread = grub_xfs_read_file (dir, 0, + numread = grub_xfs_read_file (dir, 0, 0, blk << dirblk_log2, dirblk_size, dirblock); if (numread != dirblk_size) @@ -619,7 +628,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, is not used by GRUB. So it can be overwritten. */ filename[direntry->len] = '\0'; - if (call_hook (direntry->inode, filename)) + if (iterate_dir_call_hook (direntry->inode, filename, &ctx)) { grub_free (dirblock); return 1; @@ -675,7 +684,7 @@ grub_xfs_mount (grub_disk_t disk) data = grub_realloc (data, sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) - + (1 << data->sblock.log2_inode)); + + (1 << data->sblock.log2_inode) + 1); if (! data) goto fail; @@ -703,34 +712,40 @@ grub_xfs_mount (grub_disk_t disk) } +/* Context for grub_xfs_dir. */ +struct grub_xfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_xfs_dir. */ +static int +grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_xfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); + } + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_xfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_xfs_dir_ctx ctx = { hook, hook_data }; struct grub_xfs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - if (node->inode_read) - { - info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); - } - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_xfs_mount (device->disk); @@ -742,7 +757,7 @@ grub_xfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_xfs_iterate_dir (fdiro, iterate); + grub_xfs_iterate_dir (fdiro, grub_xfs_dir_iter, &ctx); fail: if (fdiro != &data->diropen) @@ -815,8 +830,9 @@ grub_xfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_xfs_data *data = (struct grub_xfs_data *) file->data; - return grub_xfs_read_file (&data->diropen, file->read_hook, - file->offset, len, buf); + return grub_xfs_read_file (&data->diropen, + file->read_hook, file->read_hook_data, + file->offset, len, buf); } diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index ba0554abd..4d0bde4ce 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2,6 +2,7 @@ * GRUB -- GRand Unified Bootloader * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011 Free Software Foundation, Inc. * Copyright 2010 Sun Microsystems, Inc. + * Copyright (c) 2012 by Delphix. All rights reserved. * * GRUB is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -128,7 +129,7 @@ LEAF_HASH (int bs, grub_uint64_t h, zap_leaf_phys_t *l) static inline int ZAP_LEAF_NUMCHUNKS (int bs) { - return (((1 << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) / + return (((1U << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) / ZAP_LEAF_CHUNKSIZE - 2); } @@ -153,11 +154,13 @@ ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) /* - * Decompression Entry - lzjb + * Decompression Entry - lzjb & lz4 */ extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); +extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t); + typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len); typedef struct decomp_entry @@ -176,10 +179,10 @@ typedef void zio_checksum_t(const void *data, grub_uint64_t size, * Information about each checksum function. */ typedef struct zio_checksum_info { - zio_checksum_t *ci_func; /* checksum function for each byteorder */ - int ci_correctable; /* number of correctable bits */ - int ci_eck; /* uses zio embedded checksum? */ - const char *ci_name; /* descriptive name */ + zio_checksum_t *ci_func; /* checksum function for each byteorder */ + int ci_correctable; /* number of correctable bits */ + int ci_eck; /* uses zio embedded checksum? */ + const char *ci_name; /* descriptive name */ } zio_checksum_info_t; typedef struct dnode_end @@ -253,6 +256,14 @@ struct grub_zfs_data grub_uint64_t guid; }; +/* Context for grub_zfs_dir. */ +struct grub_zfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_zfs_data *data; +}; + grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, void *nonce, @@ -263,6 +274,20 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key grub_size_t keysize, grub_uint64_t salt, grub_uint64_t algo) = NULL; +/* + * List of pool features that the grub implementation of ZFS supports for + * read. Note that features that are only required for write do not need + * to be listed here since grub opens pools in read-only mode. + */ +#define MAX_SUPPORTED_FEATURE_STRLEN 50 +static const char *spa_feature_names[] = { + "org.illumos:lz4_compress",NULL +}; + +static int +check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx); +static int +check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); static grub_err_t zlib_decompress (void *s, void *d, @@ -322,6 +347,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ {"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */ + {"lz4", lz4_decompress}, /* ZIO_COMPRESS_LZ4 */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, @@ -341,7 +367,7 @@ zfs_log2 (grub_uint64_t num) num = num >> 1; } - return (i); + return i; } /* Checksum Functions */ @@ -388,7 +414,7 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, { grub_dprintf ("zfs", "unknown checksum function %d\n", checksum); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown checksum function %d", checksum); + "unknown checksum function %d", checksum); } if (ci->ci_eck) @@ -449,19 +475,19 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) - return (-1); + return -1; if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) - return (1); + return 1; if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) - return (-1); + return -1; if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) - return (1); + return 1; - return (0); + return 0; } /* @@ -482,15 +508,11 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset, if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) > 0 - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) - <= SPA_VERSION) + && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN))) endian = GRUB_ZFS_LITTLE_ENDIAN; if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) > 0 - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) - <= SPA_VERSION) + && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN))) endian = GRUB_ZFS_BIG_ENDIAN; if (endian == GRUB_ZFS_UNKNOWN_ENDIAN) @@ -547,7 +569,7 @@ find_bestub (uberblock_phys_t * ub_array, if (!ubbest) grub_errno = err; - return (ubbest); + return ubbest; } static inline grub_size_t @@ -763,6 +785,167 @@ fill_vdev_info (struct grub_zfs_data *data, diskdesc, inserted, 0xffffffff); } +/* + * For a given XDR packed nvlist, verify the first 4 bytes and move on. + * + * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : + * + * encoding method/host endian (4 bytes) + * nvl_version (4 bytes) + * nvl_nvflag (4 bytes) + * encoded nvpairs: + * encoded size of the nvpair (4 bytes) + * decoded size of the nvpair (4 bytes) + * name string size (4 bytes) + * name string data (sizeof(NV_ALIGN4(string)) + * data type (4 bytes) + * # of elements in the nvpair (4 bytes) + * data + * 2 zero's for the last nvpair + * (end of the entire list) (8 bytes) + * + */ + +/* + * The nvlist_next_nvpair() function returns a handle to the next nvpair in the + * list following nvpair. If nvpair is NULL, the first pair is returned. If + * nvpair is the last pair in the nvlist, NULL is returned. + */ +static const char * +nvlist_next_nvpair (const char *nvl, const char *nvpair) +{ + const char *nvp; + int encode_size; + int name_len; + if (nvl == NULL) + return NULL; + + if (nvpair == NULL) + { + /* skip over header, nvl_version and nvl_nvflag */ + nvpair = nvl + 4 * 3; + } + else + { + /* skip to the next nvpair */ + encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); + nvpair += encode_size; + /*If encode_size equals 0 nvlist_next_nvpair would return + * the same pair received in input, leading to an infinite loop. + * If encode_size is less than 0, this will move the pointer + * backwards, *possibly* examinining two times the same nvpair + * and potentially getting into an infinite loop. */ + if(encode_size <= 0) + { + grub_dprintf ("zfs", "nvpair with size <= 0\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return NULL; + } + } + /* 8 bytes of 0 marks the end of the list */ + if (grub_get_unaligned64 (nvpair) == 0) + return NULL; + /*consistency checks*/ + if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return NULL; + } + encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); + + nvp = nvpair + 4*2; + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + + nvp = nvp + ((name_len + 3) & ~3); // align + if (nvp + 4 >= nvl + VDEV_PHYS_SIZE + || encode_size < 0 + || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return NULL; + } + /* end consistency checks */ + + return nvpair; +} + +/* + * This function returns 0 on success and 1 on failure. On success, a string + * containing the name of nvpair is saved in buf. + */ +static int +nvpair_name (const char *nvp, char **buf, grub_size_t *buflen) +{ + /* skip over encode/decode size */ + nvp += 4 * 2; + + *buf = (char *) (nvp + 4); + *buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + + return 0; +} + +/* + * This function retrieves the value of the nvpair in the form of enumerated + * type data_type_t. + */ +static int +nvpair_type (const char *nvp) +{ + int name_len, type; + + /* skip over encode/decode size */ + nvp += 4 * 2; + + /* skip over name_len */ + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + + /* skip over name */ + nvp = nvp + ((name_len + 3) & ~3); /* align */ + + type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + + return type; +} + +static int +nvpair_value (const char *nvp,char **val, + grub_size_t *size_out, grub_size_t *nelm_out) +{ + int name_len,nelm,encode_size; + + /* skip over encode/decode size */ + encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp)); + nvp += 8; + + /* skip over name_len */ + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + + /* skip over name */ + nvp = nvp + ((name_len + 3) & ~3); /* align */ + + /* skip over type */ + nvp += 4; + nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp +=4; + if (nelm < 1) + { + grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); + return 0; + } + *val = (char *) nvp; + *size_out = encode_size; + if (nelm_out) + *nelm_out = nelm; + + return 1; +} + /* * Check the disk label information and retrieve needed vdev name-value pairs. * @@ -773,7 +956,7 @@ check_pool_label (struct grub_zfs_data *data, int *inserted) { grub_uint64_t pool_state, txg = 0; - char *nvlist; + char *nvlist,*features; #if 0 char *nv; #endif @@ -781,6 +964,9 @@ check_pool_label (struct grub_zfs_data *data, grub_uint64_t version; int found; grub_err_t err; + grub_zfs_endian_t endian; + vdev_phys_t *phys; + zio_cksum_t emptycksum; *inserted = 0; @@ -788,6 +974,28 @@ check_pool_label (struct grub_zfs_data *data, if (err) return err; + phys = (vdev_phys_t*) nvlist; + if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic, + GRUB_ZFS_LITTLE_ENDIAN) + == ZEC_MAGIC) + endian = GRUB_ZFS_LITTLE_ENDIAN; + else if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic, + GRUB_ZFS_BIG_ENDIAN) + == ZEC_MAGIC) + endian = GRUB_ZFS_BIG_ENDIAN; + else + { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, + "bad vdev_phys_t.vp_zbt.zec_magic number"); + } + /* Now check the integrity of the vdev_phys_t structure though checksum. */ + ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0); + err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian, + nvlist, VDEV_PHYS_SIZE); + if (err) + return err; + grub_dprintf ("zfs", "check 2 passed\n"); found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE, @@ -837,13 +1045,13 @@ check_pool_label (struct grub_zfs_data *data, } grub_dprintf ("zfs", "check 8 passed\n"); - if (version > SPA_VERSION) + if (!SPA_VERSION_IS_SUPPORTED(version)) { grub_free (nvlist); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new version %llu > %llu", (unsigned long long) version, - (unsigned long long) SPA_VERSION); + (unsigned long long) SPA_VERSION_BEFORE_FEATURES); } grub_dprintf ("zfs", "check 9 passed\n"); @@ -893,7 +1101,31 @@ check_pool_label (struct grub_zfs_data *data, grub_free (nv); } grub_dprintf ("zfs", "check 10 passed\n"); - + features = grub_zfs_nvlist_lookup_nvlist(nvlist, + ZPOOL_CONFIG_FEATURES_FOR_READ); + if (features) + { + const char *nvp=NULL; + char name[MAX_SUPPORTED_FEATURE_STRLEN + 1]; + char *nameptr; + grub_size_t namelen; + while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL) + { + nvpair_name (nvp, &nameptr, &namelen); + if(namelen > MAX_SUPPORTED_FEATURE_STRLEN) + namelen = MAX_SUPPORTED_FEATURE_STRLEN; + grub_memcpy (name, nameptr, namelen); + name[namelen] = '\0'; + grub_dprintf("zfs","str=%s\n",name); + if (check_feature(name,1, NULL) != 0) + { + grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name); + err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name); + return err; + } + } + } + grub_dprintf ("zfs", "check 12 passed (feature flags)\n"); grub_free (nvlist); return GRUB_ERR_NONE; @@ -988,43 +1220,47 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label"); } +/* Helper for scan_devices. */ +static int +scan_devices_iter (const char *name, void *hook_data) +{ + struct grub_zfs_data *data = hook_data; + grub_device_t dev; + grub_err_t err; + int inserted; + + dev = grub_device_open (name); + if (!dev) + return 0; + if (!dev->disk) + { + grub_device_close (dev); + return 0; + } + err = scan_disk (dev, data, 0, &inserted); + if (err == GRUB_ERR_BAD_FS) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (err) + { + grub_device_close (dev); + grub_print_error (); + return 0; + } + + if (!inserted) + grub_device_close (dev); + + return 0; +} + static grub_err_t scan_devices (struct grub_zfs_data *data) { - auto int hook (const char *name); - int hook (const char *name) - { - grub_device_t dev; - grub_err_t err; - int inserted; - dev = grub_device_open (name); - if (!dev) - return 0; - if (!dev->disk) - { - grub_device_close (dev); - return 0; - } - err = scan_disk (dev, data, 0, &inserted); - if (err == GRUB_ERR_BAD_FS) - { - grub_device_close (dev); - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (err) - { - grub_device_close (dev); - grub_print_error (); - return 0; - } - - if (!inserted) - grub_device_close (dev); - - return 0; - } - grub_device_iterate (hook); + grub_device_iterate (scan_devices_iter, data); return GRUB_ERR_NONE; } @@ -1037,9 +1273,9 @@ static const grub_uint8_t poly = 0x1d; /* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */ static inline void xor_out (grub_uint8_t *a, const grub_uint8_t *b, grub_size_t s, - int known_idx, int recovery_pow) + unsigned known_idx, unsigned recovery_pow) { - int add; + unsigned add; /* Simple xor. */ if (known_idx == 0 || recovery_pow == 0) @@ -1061,10 +1297,12 @@ gf_mul (grub_uint8_t a, grub_uint8_t b) return powx[powx_inv[a] + powx_inv[b]]; } -static inline grub_err_t +#define MAX_NBUFS 4 + +static grub_err_t recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, const unsigned *powers, - const int *idx) + const unsigned *idx) { grub_dprintf ("zfs", "recovering %u buffers\n", nbufs); /* Now we have */ @@ -1115,9 +1353,9 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, return GRUB_ERR_NONE; } /* Otherwise use Gauss. */ - default: + case 3: { - grub_uint8_t matrix1[nbufs][nbufs], matrix2[nbufs][nbufs]; + grub_uint8_t matrix1[MAX_NBUFS][MAX_NBUFS], matrix2[MAX_NBUFS][MAX_NBUFS]; int i, j, k; for (i = 0; i < nbufs; i++) @@ -1127,7 +1365,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, for (j = 0; j < nbufs; j++) matrix2[i][j] = 0; for (i = 0; i < nbufs; i++) - matrix2[i][i] = 1; + matrix2[i][i] = 1; for (i = 0; i < nbufs; i++) { @@ -1185,7 +1423,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, for (i = 0; i < (int) s; i++) { - grub_uint8_t b[nbufs]; + grub_uint8_t b[MAX_NBUFS]; for (j = 0; j < nbufs; j++) b[j] = bufs[j][i]; for (j = 0; j < nbufs; j++) @@ -1197,6 +1435,8 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, } return GRUB_ERR_NONE; } + default: + return grub_error (GRUB_ERR_BUG, "too big matrix"); } } @@ -1234,7 +1474,9 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, break; grub_errno = GRUB_ERR_NONE; } - return (grub_errno = err); + grub_errno = err; + + return err; } case DEVICE_RAIDZ: { @@ -1247,7 +1489,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_size_t orig_len = len; grub_uint8_t *recovery_buf[4]; grub_size_t recovery_len[4]; - int recovery_idx[4]; + unsigned recovery_idx[4]; unsigned failed_devices = 0; int idx, orig_idx; @@ -1653,7 +1895,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, err = grub_zfs_decrypt (data->subvol.keyring[besti].cipher, data->subvol.keyring[besti].algo, &(bp)->blk_dva[encrypted], - compbuf, psize, ((grub_uint32_t *) &zc + 5), + compbuf, psize, zc.zc_mac, endian); } if (err) @@ -1786,8 +2028,9 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, static int mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, - int NESTED_FUNC_ATTR (*hook) (const char *name, - grub_uint64_t val)) + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_dir_ctx *ctx) { int i, chunks; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; @@ -1799,7 +2042,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value, (int)mzap_ent[i].mze_cd); if (hook (mzap_ent[i].mze_name, - grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian))) + grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx)) return 1; } @@ -1841,7 +2084,7 @@ zap_hash (grub_uint64_t salt, const char *name, */ crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1); - return (crc); + return crc; } /* @@ -1863,7 +2106,7 @@ name_cmp (const char *s1, const char *s2, grub_size_t n, while (n--) { if (grub_toupper (*t1) != grub_toupper (*t2)) - return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); + return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); t1++; t2++; @@ -2050,12 +2293,11 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, static int fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_size_t name_elem_length, - int NESTED_FUNC_ATTR (*hook) (const void *name, - grub_size_t name_length, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize), - struct grub_zfs_data *data) + int (*hook) (const void *name, grub_size_t name_length, + const void *val_in, + grub_size_t nelem, grub_size_t elemsize, + void *data), + void *hook_data, struct grub_zfs_data *data) { zap_leaf_phys_t *l; void *l_in; @@ -2085,11 +2327,11 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++) { blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], - zap_dnode->endian); + zap_dnode->endian); for (idx2 = 0; idx2 < idx; idx2++) if (blkid == grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))], - zap_dnode->endian)) + zap_dnode->endian)) break; if (idx2 != idx) continue; @@ -2115,53 +2357,53 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, } for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++) - { - char *buf; - struct zap_leaf_entry *le; - char *val; - grub_size_t val_length; - le = ZAP_LEAF_ENTRY (l, blksft, chunk); + { + char *buf; + struct zap_leaf_entry *le; + char *val; + grub_size_t val_length; + le = ZAP_LEAF_ENTRY (l, blksft, chunk); - /* Verify the chunk entry */ - if (le->le_type != ZAP_CHUNK_ENTRY) + /* Verify the chunk entry */ + if (le->le_type != ZAP_CHUNK_ENTRY) + continue; + + buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) + * name_elem_length + 1); + if (zap_leaf_array_get (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_name_chunk, + endian), + grub_zfs_to_cpu16 (le->le_name_length, + endian) + * name_elem_length, buf)) + { + grub_free (buf); continue; + } + buf[le->le_name_length * name_elem_length] = 0; - buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) - * name_elem_length + 1); - if (zap_leaf_array_get (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_name_chunk, - endian), - grub_zfs_to_cpu16 (le->le_name_length, - endian) - * name_elem_length, buf)) - { - grub_free (buf); - continue; - } - buf[le->le_name_length * name_elem_length] = 0; + val_length = ((int) le->le_value_length + * (int) le->le_int_size); + val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian)); + if (zap_leaf_array_get (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_value_chunk, + endian), + val_length, val)) + { + grub_free (buf); + grub_free (val); + continue; + } - val_length = ((int) le->le_value_length - * (int) le->le_int_size); - val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian)); - if (zap_leaf_array_get (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_value_chunk, - endian), - val_length, val)) - { - grub_free (buf); - grub_free (val); - continue; - } - - if (hook (buf, le->le_name_length, - val, le->le_value_length, le->le_int_size)) - { - grub_free (l); - return 1; - } - grub_free (buf); - grub_free (val); - } + if (hook (buf, le->le_name_length, + val, le->le_value_length, le->le_int_size, hook_data)) + { + grub_free (l); + return 1; + } + grub_free (buf); + grub_free (val); + } grub_free (l); } return 0; @@ -2217,11 +2459,35 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type"); } +/* Context for zap_iterate_u64. */ +struct zap_iterate_u64_ctx +{ + int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *); + struct grub_zfs_dir_ctx *dir_ctx; +}; + +/* Helper for zap_iterate_u64. */ +static int +zap_iterate_u64_transform (const void *name, + grub_size_t namelen __attribute__ ((unused)), + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize, + void *data) +{ + struct zap_iterate_u64_ctx *ctx = data; + + if (elemsize != sizeof (grub_uint64_t) || nelem != 1) + return 0; + return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in), + ctx->dir_ctx); +} + static int zap_iterate_u64 (dnode_end_t * zap_dnode, - int NESTED_FUNC_ATTR (*hook) (const char *name, - grub_uint64_t val), - struct grub_zfs_data *data) + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx) { grub_uint64_t block_type; int size; @@ -2230,23 +2496,6 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, int ret; grub_zfs_endian_t endian; - auto int NESTED_FUNC_ATTR transform (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - - int NESTED_FUNC_ATTR transform (const void *name, - grub_size_t namelen __attribute__ ((unused)), - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize) - { - if (elemsize != sizeof (grub_uint64_t) || nelem != 1) - return 0; - return hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in)); - } - /* Read in the first block of the zap object data. */ size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); @@ -2259,15 +2508,21 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, if (block_type == ZBT_MICRO) { grub_dprintf ("zfs", "micro zap\n"); - ret = mzap_iterate (zapbuf, endian, size, hook); + ret = mzap_iterate (zapbuf, endian, size, hook, ctx); grub_free (zapbuf); return ret; } else if (block_type == ZBT_HEADER) { + struct zap_iterate_u64_ctx transform_ctx = { + .hook = hook, + .dir_ctx = ctx + }; + grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data); + ret = fzap_iterate (zap_dnode, zapbuf, 1, + zap_iterate_u64_transform, &transform_ctx, data); grub_free (zapbuf); return ret; } @@ -2278,12 +2533,11 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, static int zap_iterate (dnode_end_t * zap_dnode, grub_size_t nameelemlen, - int NESTED_FUNC_ATTR (*hook) (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize), - struct grub_zfs_data *data) + int (*hook) (const void *name, grub_size_t namelen, + const void *val_in, + grub_size_t nelem, grub_size_t elemsize, + void *data), + void *hook_data, struct grub_zfs_data *data) { grub_uint64_t block_type; void *zapbuf; @@ -2308,7 +2562,8 @@ zap_iterate (dnode_end_t * zap_dnode, { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data); + ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data, + data); grub_free (zapbuf); return ret; } @@ -2542,7 +2797,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_size_t block; grub_size_t blksz; blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, - dnode_path->dn.endian) + dnode_path->dn.endian) << SPA_MINBLOCKSHIFT); sym_value = grub_malloc (sym_sz); @@ -2587,11 +2842,11 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_free (dn_new); } else while (dnode_path != root) - { - dn_new = dnode_path; - dnode_path = dn_new->next; - grub_free (dn_new); - } + { + dn_new = dnode_path; + dnode_path = dn_new->next; + grub_free (dn_new); + } } if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA) { @@ -2648,11 +2903,11 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_free (dn_new); } else while (dnode_path != root) - { - dn_new = dnode_path; - dnode_path = dn_new->next; - grub_free (dn_new); - } + { + dn_new = dnode_path; + dnode_path = dn_new->next; + grub_free (dn_new); + } } } } @@ -2822,6 +3077,61 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) return GRUB_ERR_NONE; } +/* Context for dnode_get_fullpath. */ +struct dnode_get_fullpath_ctx +{ + struct subvolume *subvol; + grub_uint64_t salt; + int keyn; +}; + +/* Helper for dnode_get_fullpath. */ +static int +count_zap_keys (const void *name __attribute__ ((unused)), + grub_size_t namelen __attribute__ ((unused)), + const void *val_in __attribute__ ((unused)), + grub_size_t nelem __attribute__ ((unused)), + grub_size_t elemsize __attribute__ ((unused)), + void *data) +{ + struct dnode_get_fullpath_ctx *ctx = data; + + ctx->subvol->nkeys++; + return 0; +} + +/* Helper for dnode_get_fullpath. */ +static int +load_zap_key (const void *name, grub_size_t namelen, const void *val_in, + grub_size_t nelem, grub_size_t elemsize, void *data) +{ + struct dnode_get_fullpath_ctx *ctx = data; + + if (namelen != 1) + { + grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n", + namelen); + return 0; + } + + if (elemsize != 1) + { + grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n", + elemsize); + return 0; + } + + ctx->subvol->keyring[ctx->keyn].txg = + grub_be_to_cpu64 (*(grub_uint64_t *) name); + ctx->subvol->keyring[ctx->keyn].algo = + grub_le_to_cpu64 (*(grub_uint64_t *) val_in); + ctx->subvol->keyring[ctx->keyn].cipher = + grub_zfs_load_key (val_in, nelem, ctx->salt, + ctx->subvol->keyring[ctx->keyn].algo); + ctx->keyn++; + return 0; +} + static grub_err_t dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, dnode_end_t * dn, int *isfs, @@ -2831,57 +3141,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, const char *ptr_at, *filename; grub_uint64_t headobj; grub_uint64_t keychainobj; - grub_uint64_t salt; grub_err_t err; - int keyn = 0; - - auto int NESTED_FUNC_ATTR count_zap_keys (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)), - grub_size_t namelen __attribute__ ((unused)), - const void *val_in __attribute__ ((unused)), - grub_size_t nelem __attribute__ ((unused)), - grub_size_t elemsize __attribute__ ((unused))) - { - subvol->nkeys++; - return 0; - } - - auto int NESTED_FUNC_ATTR load_zap_key (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - int NESTED_FUNC_ATTR load_zap_key (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize) - { - if (namelen != 1) - { - grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n", - namelen); - return 0; - } - - if (elemsize != 1) - { - grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n", - elemsize); - return 0; - } - - subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name); - subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in); - subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt, - subvol->keyring[keyn].algo); - keyn++; - return 0; - } ptr_at = grub_strchr (fullpath, '@'); if (! ptr_at) @@ -2949,6 +3209,10 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); if (grub_zfs_load_key && keychainobj) { + struct dnode_get_fullpath_ctx ctx = { + .subvol = subvol, + .keyn = 0 + }; dnode_end_t keychain_dn, props_dn; grub_uint64_t propsobj; propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian); @@ -2962,12 +3226,12 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } - err = zap_lookup (&props_dn, "salt", &salt, data, 0); + err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0); if (err == GRUB_ERR_FILE_NOT_FOUND) { err = 0; grub_errno = 0; - salt = 0; + ctx.salt = 0; } if (err) { @@ -2984,7 +3248,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } subvol->nkeys = 0; - zap_iterate (&keychain_dn, 8, count_zap_keys, data); + zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data); subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0])); if (!subvol->keyring) { @@ -2992,7 +3256,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_free (snapname); return err; } - zap_iterate (&keychain_dn, 8, load_zap_key, data); + zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data); } if (snapname) @@ -3034,34 +3298,15 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } -/* - * For a given XDR packed nvlist, verify the first 4 bytes and move on. - * - * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : - * - * encoding method/host endian (4 bytes) - * nvl_version (4 bytes) - * nvl_nvflag (4 bytes) - * encoded nvpairs: - * encoded size of the nvpair (4 bytes) - * decoded size of the nvpair (4 bytes) - * name string size (4 bytes) - * name string data (sizeof(NV_ALIGN4(string)) - * data type (4 bytes) - * # of elements in the nvpair (4 bytes) - * data - * 2 zero's for the last nvpair - * (end of the entire list) (8 bytes) - * - */ - static int nvlist_find_value (const char *nvlist_in, const char *name, int valtype, char **val, grub_size_t *size_out, grub_size_t *nelm_out) { - int name_len, type, encode_size; - const char *nvpair, *nvp_name, *nvlist = nvlist_in; + grub_size_t nvp_name_len, name_len = grub_strlen(name); + int type; + const char *nvpair=NULL,*nvlist=nvlist_in; + char *nvp_name; /* Verify if the 1st and 2nd byte in the nvlist are valid. */ /* NOTE: independently of what endianness header announces all @@ -3074,62 +3319,21 @@ nvlist_find_value (const char *nvlist_in, const char *name, return 0; } - /* skip the header, nvl_version, and nvl_nvflag */ - nvlist = nvlist + 4 * 3; /* * Loop thru the nvpair list * The XDR representation of an integer is in big-endian byte order. */ - while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist)))) + while ((nvpair=nvlist_next_nvpair(nvlist,nvpair))) { - int nelm; - - if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE) + nvpair_name(nvpair,&nvp_name, &nvp_name_len); + type = nvpair_type(nvpair); + if (type == valtype + && (nvp_name_len == name_len + || (nvp_name_len > name_len && nvp_name[name_len] == '\0')) + && grub_memcmp (nvp_name, name, name_len) == 0) { - grub_dprintf ("zfs", "nvlist overflow\n"); - grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); - return 0; + return nvpair_value(nvpair,val,size_out,nelm_out); } - - nvpair = nvlist + 4 * 2; /* skip the encode/decode size */ - - name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); - nvpair += 4; - - nvp_name = nvpair; - nvpair = nvpair + ((name_len + 3) & ~3); /* align */ - - if (nvpair + 8 >= nvlist_in + VDEV_PHYS_SIZE - || encode_size < 0 - || nvpair + 8 + encode_size > nvlist_in + VDEV_PHYS_SIZE) - { - grub_dprintf ("zfs", "nvlist overflow\n"); - grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); - return 0; - } - - type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); - nvpair += 4; - - nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); - if (nelm < 1) - { - grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); - return 0; - } - - nvpair += 4; - - if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype) - { - *val = (char *) nvpair; - *size_out = encode_size; - if (nelm_out) - *nelm_out = nelm; - return 1; - } - - nvlist += encode_size; /* goto the next nvpair */ } return 0; } @@ -3386,6 +3590,11 @@ zfs_mount (grub_device_t dev) return NULL; } + if (ub->ub_version >= SPA_VERSION_FEATURES && + check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian, + data) != 0) + return NULL; + /* Got the MOS. Save it at the memory addr MOS. */ grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, DNODE_SIZE); @@ -3661,7 +3870,7 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, return err; } -static void +static grub_err_t fill_fs_info (struct grub_dirhook_info *info, dnode_end_t mdn, struct grub_zfs_data *data) { @@ -3682,30 +3891,32 @@ fill_fs_info (struct grub_dirhook_info *info, if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } } - make_mdn (&mdn, data); + err = make_mdn (&mdn, data); + if (err) + return err; err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, &dn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } err = dnode_get (&mdn, objnum, 0, &dn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } if (dn.dn.dn_bonustype == DMU_OT_SA) @@ -3723,12 +3934,12 @@ fill_fs_info (struct grub_dirhook_info *info, err = zio_read (bp, dn.endian, &sahdrp, NULL, data); if (err) - return; + return err; } else { grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - return; + return grub_errno; } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); @@ -3741,111 +3952,141 @@ fill_fs_info (struct grub_dirhook_info *info, info->mtimeset = 1; info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); } - return; + return 0; +} + +/* Helper for grub_zfs_dir. */ +static int +iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) +{ + grub_err_t err; + struct grub_dirhook_info info; + + dnode_end_t dn; + grub_memset (&info, 0, sizeof (info)); + + dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data); + + if (dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; + int hdrsize; + + if (dn.dn.dn_bonuslen != 0) + { + sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn); + } + else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dn.dn.dn_spill; + + err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data); + if (err) + { + grub_print_error (); + return 0; + } + } + else + { + grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + grub_print_error (); + return 0; + } + + hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.case_insensitive = ctx->data->subvol.case_insensitive; + } + + if (dn.dn.dn_bonustype == DMU_OT_ZNODE) + { + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], + dn.endian); + } + info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); + grub_dprintf ("zfs", "type=%d, name=%s\n", + (int)dn.dn.dn_type, (char *)name); + return ctx->hook (name, &info, ctx->hook_data); +} + +/* Helper for grub_zfs_dir. */ +static int +iterate_zap_fs (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx) +{ + grub_err_t err; + struct grub_dirhook_info info; + + dnode_end_t mdn; + err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + if (mdn.dn.dn_type != DMU_OT_DSL_DIR) + return 0; + + err = fill_fs_info (&info, mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + return ctx->hook (name, &info, ctx->hook_data); +} + +/* Helper for grub_zfs_dir. */ +static int +iterate_zap_snap (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx) +{ + grub_err_t err; + struct grub_dirhook_info info; + char *name2; + int ret; + + dnode_end_t mdn; + + err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + + if (mdn.dn.dn_type != DMU_OT_DSL_DATASET) + return 0; + + err = fill_fs_info (&info, mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + + name2 = grub_malloc (grub_strlen (name) + 2); + name2[0] = '@'; + grub_memcpy (name2 + 1, name, grub_strlen (name) + 1); + ret = ctx->hook (name2, &info, ctx->hook_data); + grub_free (name2); + return ret; } static grub_err_t grub_zfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *, const struct grub_dirhook_info *)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_zfs_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; struct grub_zfs_data *data; grub_err_t err; int isfs; - auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val); - auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, - grub_uint64_t val); - auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, - grub_uint64_t val); - - int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val) - { - struct grub_dirhook_info info; - dnode_end_t dn; - grub_memset (&info, 0, sizeof (info)); - - dnode_get (&(data->subvol.mdn), val, 0, &dn, data); - - if (dn.dn.dn_bonustype == DMU_OT_SA) - { - void *sahdrp; - int hdrsize; - - if (dn.dn.dn_bonuslen != 0) - { - sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn); - } - else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) - { - blkptr_t *bp = &dn.dn.dn_spill; - - err = zio_read (bp, dn.endian, &sahdrp, NULL, data); - if (err) - { - grub_print_error (); - return 0; - } - } - else - { - grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - grub_print_error (); - return 0; - } - - hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); - info.case_insensitive = data->subvol.case_insensitive; - } - - if (dn.dn.dn_bonustype == DMU_OT_ZNODE) - { - info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], - dn.endian); - } - info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); - grub_dprintf ("zfs", "type=%d, name=%s\n", - (int)dn.dn.dn_type, (char *)name); - return hook (name, &info); - } - - int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val) - { - struct grub_dirhook_info info; - dnode_end_t mdn; - err = dnode_get (&(data->mos), val, 0, &mdn, data); - if (err) - return 0; - if (mdn.dn.dn_type != DMU_OT_DSL_DIR) - return 0; - - fill_fs_info (&info, mdn, data); - return hook (name, &info); - } - int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val) - { - struct grub_dirhook_info info; - char *name2; - int ret; - dnode_end_t mdn; - - err = dnode_get (&(data->mos), val, 0, &mdn, data); - if (err) - return 0; - - if (mdn.dn.dn_type != DMU_OT_DSL_DATASET) - return 0; - - fill_fs_info (&info, mdn, data); - - name2 = grub_malloc (grub_strlen (name) + 2); - name2[0] = '@'; - grub_memcpy (name2 + 1, name, grub_strlen (name) + 1); - ret = hook (name2, &info); - grub_free (name2); - return ret; - } data = zfs_mount (device); if (! data) @@ -3856,6 +4097,8 @@ grub_zfs_dir (grub_device_t device, const char *path, zfs_unmount (data); return err; } + ctx.data = data; + if (isfs) { grub_uint64_t childobj, headobj; @@ -3863,9 +4106,18 @@ grub_zfs_dir (grub_device_t device, const char *path, dnode_end_t dn; struct grub_dirhook_info info; - fill_fs_info (&info, data->dnode, data); - hook ("@", &info); - + err = fill_fs_info (&info, data->dnode, data); + if (err) + { + zfs_unmount (data); + return err; + } + if (hook ("@", &info, hook_data)) + { + zfs_unmount (data); + return GRUB_ERR_NONE; + } + childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian); headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian); err = dnode_get (&(data->mos), childobj, @@ -3876,7 +4128,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate_u64 (&dn, iterate_zap_fs, data); + zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx); err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data); if (err) @@ -3895,7 +4147,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate_u64 (&dn, iterate_zap_snap, data); + zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx); } else { @@ -3904,12 +4156,74 @@ grub_zfs_dir (grub_device_t device, const char *path, zfs_unmount (data); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } - zap_iterate_u64 (&(data->dnode), iterate_zap, data); + zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx); } zfs_unmount (data); return grub_errno; } +static int +check_feature (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx __attribute__((unused))) +{ + int i; + if (val == 0) + return 0; + if (name[0] == 0) + return 0; + for (i = 0; spa_feature_names[i] != NULL; i++) + if (grub_strcmp (name, spa_feature_names[i]) == 0) + return 0; + return 1; +} + +/* + * Checks whether the MOS features that are active are supported by this + * (GRUB's) implementation of ZFS. + * + * Return: + * 0: Success. + * errnum: Failure. + */ + +static int +check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) +{ + grub_uint64_t objnum; + grub_uint8_t errnum = 0; + dnode_end_t dn,mosmdn; + mzap_phys_t* mzp; + grub_zfs_endian_t endianzap; + int size; + grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t)); + mosmdn.endian=endian; + errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT, + DMU_OT_OBJECT_DIRECTORY, &dn,data); + if (errnum != 0) + return errnum; + + /* + * Find the object number for 'features_for_read' and retrieve its + * corresponding dnode. Note that we don't check features_for_write + * because GRUB is not opening the pool for write. + */ + errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0); + if (errnum != 0) + return errnum; + + errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data); + if (errnum != 0) + return errnum; + + errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data); + if (errnum != 0) + return errnum; + + size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT; + return mzap_iterate (mzp,endianzap, size, check_feature,NULL); +} + + #ifdef GRUB_UTIL static grub_err_t grub_zfs_embed (grub_device_t device __attribute__ ((unused)), @@ -3924,7 +4238,7 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ZFS currently supports only PC-BIOS embedding"); - if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors) + if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("your core.img is unusually large. " "It won't fit in the embedding area")); diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c new file mode 100644 index 000000000..dde2c7195 --- /dev/null +++ b/grub-core/fs/zfs/zfs_lz4.c @@ -0,0 +1,284 @@ +/* + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2013, Yann Collet. + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at : + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + * - LZ4 source repository : http://code.google.com/p/lz4/ + */ + +#include +#include +#include +#include + +static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, + int isize, int maxOutputSize); + +/* + * CPU Feature Detection + */ + +/* 32 or 64 bits ? */ +#if (GRUB_CPU_SIZEOF_VOID_P == 8) +#define LZ4_ARCH64 1 +#else +#define LZ4_ARCH64 0 +#endif + +/* + * Compiler Options + */ + + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#if (GCC_VERSION >= 302) || (defined (__INTEL_COMPILER) && __INTEL_COMPILER >= 800) || defined(__clang__) +#define expect(expr, value) (__builtin_expect((expr), (value))) +#else +#define expect(expr, value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + +/* Basic types */ +#define BYTE grub_uint8_t +#define U16 grub_uint16_t +#define U32 grub_uint32_t +#define S32 grub_int32_t +#define U64 grub_uint64_t +typedef grub_size_t size_t; + +typedef struct _U16_S { + U16 v; +} __attribute__ ((packed)) U16_S; +typedef struct _U32_S { + U32 v; +} __attribute__ ((packed)) U32_S; +typedef struct _U64_S { + U64 v; +} __attribute__ ((packed)) U64_S; + +#define A64(x) (((U64_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A16(x) (((U16_S *)(x))->v) + +/* + * Constants + */ +#define MINMATCH 4 + +#define COPYLENGTH 8 +#define LASTLITERALS 5 + +#define ML_BITS 4 +#define ML_MASK ((1U< s_len) + return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."); + + /* + * Returns 0 on success (decompression function returned non-negative) + * and appropriate error on failure (decompression function returned negative). + */ + return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz, + d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0; +} + +static int +LZ4_uncompress_unknownOutputSize(const char *source, + char *dest, int isize, int maxOutputSize) +{ + /* Local Variables */ + const BYTE * ip = (const BYTE *) source; + const BYTE *const iend = ip + isize; + const BYTE * ref; + + BYTE * op = (BYTE *) dest; + BYTE *const oend = op + maxOutputSize; + BYTE *cpy; + + size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 }; + + /* Main Loop */ + while (ip < iend) { + BYTE token; + int length; + + /* get runlength */ + token = *ip++; + if ((length = (token >> ML_BITS)) == RUN_MASK) { + int s = 255; + while ((ip < iend) && (s == 255)) { + s = *ip++; + length += s; + } + } + /* copy literals */ + cpy = op + length; + if ((cpy > oend - COPYLENGTH) || + (ip + length > iend - COPYLENGTH)) { + if (cpy > oend) + /* + * Error: request to write beyond destination + * buffer. + */ + goto _output_error; + if (ip + length > iend) + /* + * Error : request to read beyond source + * buffer. + */ + goto _output_error; + grub_memcpy(op, ip, length); + op += length; + ip += length; + if (ip < iend) + /* Error : LZ4 format violation */ + goto _output_error; + /* Necessarily EOF, due to parsing restrictions. */ + break; + } + LZ4_WILDCOPY(ip, op, cpy); + ip -= (op - cpy); + op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); + ip += 2; + if (ref < (BYTE * const) dest) + /* + * Error: offset creates reference outside of + * destination buffer. + */ + goto _output_error; + + /* get matchlength */ + if ((length = (token & ML_MASK)) == ML_MASK) { + while (ip < iend) { + int s = *ip++; + length += s; + if (s == 255) + continue; + break; + } + } + /* copy repeated sequence */ + if unlikely(op - ref < STEPSIZE) { +#if LZ4_ARCH64 + size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 }; + size_t dec2 = dec2table[op - ref]; +#else + const int dec2 = 0; +#endif + *op++ = *ref++; + *op++ = *ref++; + *op++ = *ref++; + *op++ = *ref++; + ref -= dec[op - ref]; + A32(op) = A32(ref); + op += STEPSIZE - 4; + ref -= dec2; + } else { + LZ4_COPYSTEP(ref, op); + } + cpy = op + length - (STEPSIZE - 4); + if (cpy > oend - COPYLENGTH) { + if (cpy > oend) + /* + * Error: request to write outside of + * destination buffer. + */ + goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; + op = cpy; + if (op == oend) + /* + * Check EOF (should never happen, since last + * 5 bytes are supposed to be literals). + */ + break; + continue; + } + LZ4_SECURECOPY(ref, op, cpy); + op = cpy; /* correction */ + } + + /* end of decoding */ + return (int)(((char *)op) - dest); + + /* write overflow error detected */ + _output_error: + return (int)(-(((char *)ip) - source)); +} diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 4ea53b863..88dae72ef 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -143,7 +143,7 @@ grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, return err; if (mac_out) grub_crypto_xor (mac_out, mac, mul, m); - return GRUB_ERR_NONE; + return GPG_ERR_NO_ERROR; } static void @@ -244,7 +244,7 @@ grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher, if (mac_out) grub_crypto_xor (mac_out, mac, mac_xor, m); - return GRUB_ERR_NONE; + return GPG_ERR_NO_ERROR; } @@ -258,13 +258,14 @@ algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, switch (algo) { case 0: - return grub_ccm_decrypt (cipher, out, in, psize, mac_out, nonce, l, m); + return grub_ccm_decrypt (cipher, out, in, psize, + mac_out, nonce, l, m); case 1: - return grub_gcm_decrypt (cipher, out, in, psize, mac_out, nonce, + return grub_gcm_decrypt (cipher, out, in, psize, + mac_out, nonce, 15 - l, m); default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "algorithm %" - PRIuGRUB_UINT64_T " is not supported yet", algo); + return GPG_ERR_CIPHER_ALGO; } } @@ -279,7 +280,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, grub_uint32_t mac[4]; unsigned i; grub_uint32_t sw[4]; - grub_err_t err; + gcry_err_code_t err; grub_memcpy (sw, nonce, 16); if (endian != GRUB_ZFS_BIG_ENDIAN) @@ -295,7 +296,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, size, mac, sw + 1, 3, 12); if (err) - return err; + return grub_crypto_gcry_error (err); for (i = 0; i < 3; i++) if (grub_zfs_to_cpu32 (expected_mac[i], endian) diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index fdb587a4c..c96bf2183 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -132,21 +132,31 @@ print_vdev_info (char *nvlist, int tab) grub_free (path); return GRUB_ERR_NONE; } + char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0); + char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0); - if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) + if (is_mirror || is_raidz) { int nelm, i; nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN); + if(is_mirror){ + grub_puts_ (N_("This VDEV is a mirror")); + } + else if(is_raidz){ + grub_uint64_t parity; + grub_zfs_nvlist_lookup_uint64(nvlist,"nparity",&parity); + grub_printf_ (N_("This VDEV is a RAIDZ%llu\n"),(unsigned long long)parity); + } print_tabs (tab); if (nelm <= 0) { - grub_puts_ (N_("Incorrect mirror")); + grub_puts_ (N_("Incorrect VDEV")); return GRUB_ERR_NONE; } - grub_printf_ (N_("Mirror with %d children\n"), nelm); + grub_printf_ (N_("VDEV with %d children\n"), nelm); print_state (nvlist, tab); for (i = 0; i < nelm; i++) { @@ -162,14 +172,14 @@ print_vdev_info (char *nvlist, int tab) total element number. And the number itself is fine, only the element isn't. */ - grub_printf_ (N_("Mirror element number %d isn't correct\n"), i); + grub_printf_ (N_("VDEV element number %d isn't correct\n"), i); continue; } /* TRANSLATORS: it's the element carying the number %d, not total element number. This is used in enumeration "Element number 1", "Element number 2", ... */ - grub_printf_ (N_("Mirror element number %d:\n"), i); + grub_printf_ (N_("VDEV element number %d:\n"), i); print_vdev_info (child, tab + 1); grub_free (child); diff --git a/grub-core/gdb/cstub.c b/grub-core/gdb/cstub.c index a5c0c4316..c94411b10 100644 --- a/grub-core/gdb/cstub.c +++ b/grub-core/gdb/cstub.c @@ -201,10 +201,10 @@ grub_gdb_hex2int (char **ptr, grub_uint64_t *int_value) } /* This function does all command procesing for interfacing to gdb. */ -void +void __attribute__ ((regparm(3))) grub_gdb_trap (int trap_no) { - int sig_no; + unsigned int sig_no; int stepping; grub_uint64_t addr; grub_uint64_t length; @@ -216,7 +216,7 @@ grub_gdb_trap (int trap_no) grub_backtrace_print_address ((void *) grub_gdb_regs[PC]); grub_printf ("\n"); grub_backtrace_pointer ((void *) grub_gdb_regs[EBP]); - grub_abort (); + grub_fatal ("Unhandled exception"); } sig_no = grub_gdb_trap2sig (trap_no); @@ -264,7 +264,7 @@ grub_gdb_trap (int trap_no) case '?': grub_gdb_outbuf[0] = 'S'; grub_gdb_outbuf[1] = hexchars[sig_no >> 4]; - grub_gdb_outbuf[2] = hexchars[sig_no % 16]; + grub_gdb_outbuf[2] = hexchars[sig_no & 0xf]; grub_gdb_outbuf[3] = 0; break; diff --git a/grub-core/gdb/i386/signal.c b/grub-core/gdb/i386/signal.c index 23b7c3506..1ac3bbd18 100644 --- a/grub-core/gdb/i386/signal.c +++ b/grub-core/gdb/i386/signal.c @@ -24,7 +24,7 @@ /* Converting CPU trap number to UNIX signal number as described in System V ABI i386 Processor Supplement, 3-25. */ -int +unsigned int grub_gdb_trap2sig (int trap_no) { const int signals[] = { diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in index 01ef3e15b..e322d3dc1 100644 --- a/grub-core/gdb_grub.in +++ b/grub-core/gdb_grub.in @@ -22,7 +22,7 @@ define dump_module_sections printf "%s", $mod->name set $segment = $mod->segment while ($segment) - printf " %i 0x%x", $segment->section, $segment->addr + printf " %i 0x%lx", $segment->section, $segment->addr set $segment = $segment->next end printf "\n" @@ -61,7 +61,7 @@ end define load_all_modules set $this = grub_dl_head while ($this != 0) - dump_module_sections $this->mod + dump_module_sections $this set $this = $this->next end match_and_load_symbols diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in index 76df0bbb4..ff5cb19ae 100644 --- a/grub-core/genmod.sh.in +++ b/grub-core/genmod.sh.in @@ -37,7 +37,7 @@ rm -f $tmpfile $outfile if test x@TARGET_APPLE_CC@ != x1; then # stripout .modname and .moddeps sections from input module - @OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile + @TARGET_OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile # Attach .modname and .moddeps sections t1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 @@ -47,17 +47,17 @@ if test x@TARGET_APPLE_CC@ != x1; then for dep in $deps; do printf "$dep\0" >> $t2; done if test -n "$deps"; then - @OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile + @TARGET_OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile else - @OBJCOPY@ --add-section .modname=$t1 $tmpfile + @TARGET_OBJCOPY@ --add-section .modname=$t1 $tmpfile fi rm -f $t1 $t2 if ! test -z "${TARGET_OBJ2ELF}"; then - ./${TARGET_OBJ2ELF} $tmpfile || exit 1 + "${TARGET_OBJ2ELF}" $tmpfile || exit 1 fi if test x@platform@ != xemu; then - @STRIP@ --strip-unneeded \ + @TARGET_STRIP@ --strip-unneeded \ -K grub_mod_init -K grub_mod_fini \ -K _grub_mod_init -K _grub_mod_fini \ -R .note.gnu.gold-version -R .note.GNU-stack \ @@ -87,7 +87,7 @@ else mv $tmpfile2 $tmpfile cp $tmpfile $tmpfile.bin - @OBJCONV@ -f@TARGET_MODULE_FORMAT@ \ + @TARGET_OBJCONV@ -f@TARGET_MODULE_FORMAT@ \ -nr:_grub_mod_init:grub_mod_init \ -nr:_grub_mod_fini:grub_mod_fini \ -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1 diff --git a/grub-core/gensyminfo.sh.in b/grub-core/gensyminfo.sh.in index d383f2640..2e8716b42 100644 --- a/grub-core/gensyminfo.sh.in +++ b/grub-core/gensyminfo.sh.in @@ -22,14 +22,16 @@ module=$1 modname=`echo $module | sed -e 's@\.module.*$@@'` # Print all symbols defined by module -if test x@TARGET_APPLE_CC@ = x1; then - @NM@ -g -P -p $module | \ - grep -E '^[a-zA-Z0-9_]* [TDS]' | \ - sed "s@^\([^ ]*\).*@defined $modname \1@g" +if test x"@TARGET_NMFLAGS_DEFINED_ONLY@" = x && test x"@TARGET_NMFLAGS_MINUS_P@" = x; then + @TARGET_NM@ -g -p $module | \ + sed -n "s@^\([0-9a-fA-F]*\) *[TBRDS] *\([^ ]*\).*@defined $modname \2@p" +elif test x"@TARGET_NMFLAGS_DEFINED_ONLY@" = x; then + @TARGET_NM@ -g @TARGET_NMFLAGS_MINUS_P@ -p $module | \ + sed -n "s@^\([^ ]*\) *[TBRDS] *\([0-9a-fA-F]*\).*@defined $modname \1@p" else - @NM@ -g --defined-only -P -p $module | \ + @TARGET_NM@ -g --defined-only @TARGET_NMFLAGS_MINUS_P@ -p $module | \ sed "s@^\([^ ]*\).*@defined $modname \1@g" fi # Print all undefined symbols used by module -@NM@ -u -P -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" +@TARGET_NM@ -u @TARGET_NMFLAGS_MINUS_P@ -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" diff --git a/grub-core/gensymlist.sh b/grub-core/gensymlist.sh index a13d7cc38..5beaabdd6 100644 --- a/grub-core/gensymlist.sh +++ b/grub-core/gensymlist.sh @@ -59,7 +59,7 @@ EOF | grep -v '^#' \ | sed -n \ -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/ {"\1", \1, 1},/;p;}' \ - -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", \&\1, 0},/;p;}' \ + -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", (void *) \&\1, 0},/;p;}' \ | sort -u cat <device_width; - grub_free (glyph); if (err) return err; } + for (ptr = visual; ptr < visual + visual_len; ptr++) + grub_unicode_destroy_glyph (ptr); grub_free (visual); return GRUB_ERR_NONE; @@ -102,8 +103,9 @@ grub_font_get_string_width (grub_font_t font, const char *str) &glyph); width += grub_font_get_constructed_device_width (font, &glyph); - grub_free (glyph.combining); + grub_unicode_destroy_glyph (&glyph); } + grub_free (logical); return width; } diff --git a/grub-core/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c index 09e86213f..f49fce802 100644 --- a/grub-core/gfxmenu/gfxmenu.c +++ b/grub-core/gfxmenu/gfxmenu.c @@ -53,6 +53,7 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) { grub_gfxmenu_view_t view = NULL; const char *theme_path; + char *full_theme_path = 0; struct grub_menu_viewer *instance; grub_err_t err; struct grub_video_mode_info mode_info; @@ -70,15 +71,27 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) if (err) return err; - if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 + if (theme_path[0] != '/' && theme_path[0] != '(') + { + const char *prefix; + prefix = grub_env_get ("prefix"); + full_theme_path = grub_xasprintf ("%s/themes/%s", + prefix, + theme_path); + } + + if (!cached_view || grub_strcmp (cached_view->theme_path, + full_theme_path ? : theme_path) != 0 || cached_view->screen.width != mode_info.width || cached_view->screen.height != mode_info.height) { - grub_free (cached_view); + grub_gfxmenu_view_destroy (cached_view); /* Create the view. */ - cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width, + cached_view = grub_gfxmenu_view_new (full_theme_path ? : theme_path, + mode_info.width, mode_info.height); } + grub_free (full_theme_path); if (! cached_view) { diff --git a/grub-core/gfxmenu/gui_box.c b/grub-core/gfxmenu/gui_box.c index 38b15f96d..37bab3fbb 100644 --- a/grub-core/gfxmenu/gui_box.c +++ b/grub-core/gfxmenu/gui_box.c @@ -234,14 +234,30 @@ static void box_paint (void *vself, const grub_video_rect_t *region) { grub_gui_box_t self = vself; + struct component_node *cur; grub_video_rect_t vpsave; + grub_video_area_status_t box_area_status; + grub_video_get_area_status (&box_area_status); + grub_gui_set_viewport (&self->bounds, &vpsave); for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) { grub_gui_component_t comp = cur->component; + grub_video_rect_t r; + comp->ops->get_bounds(comp, &r); + + if (!grub_video_have_common_points (region, &r)) + continue; + + /* Paint the child. */ + if (box_area_status == GRUB_VIDEO_AREA_ENABLED + && grub_video_bounds_inside_region (&r, region)) + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); comp->ops->paint (comp, region); + if (box_area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/gui_canvas.c b/grub-core/gfxmenu/gui_canvas.c index b3919c2d3..a05491242 100644 --- a/grub-core/gfxmenu/gui_canvas.c +++ b/grub-core/gfxmenu/gui_canvas.c @@ -80,9 +80,13 @@ static void canvas_paint (void *vself, const grub_video_rect_t *region) { grub_gui_canvas_t self = vself; + struct component_node *cur; grub_video_rect_t vpsave; + grub_video_area_status_t canvas_area_status; + grub_video_get_area_status (&canvas_area_status); + grub_gui_set_viewport (&self->bounds, &vpsave); for (cur = self->components.next; cur; cur = cur->next) { @@ -135,9 +139,16 @@ canvas_paint (void *vself, const grub_video_rect_t *region) r.height = h; comp->ops->set_bounds (comp, &r); + if (!grub_video_have_common_points (region, &r)) + continue; + /* Paint the child. */ - if (grub_video_have_common_points (region, &r)) - comp->ops->paint (comp, region); + if (canvas_area_status == GRUB_VIDEO_AREA_ENABLED + && grub_video_bounds_inside_region (&r, region)) + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + comp->ops->paint (comp, region); + if (canvas_area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/gui_circular_progress.c b/grub-core/gfxmenu/gui_circular_progress.c index 098ae1c92..04f68b8d3 100644 --- a/grub-core/gfxmenu/gui_circular_progress.c +++ b/grub-core/gfxmenu/gui_circular_progress.c @@ -37,7 +37,7 @@ struct grub_gui_circular_progress int start; int end; int value; - int num_ticks; + unsigned num_ticks; int start_angle; int ticks_disappear; char *theme_dir; @@ -138,29 +138,30 @@ circprog_paint (void *vself, const grub_video_rect_t *region) (height - center_height) / 2, 0, 0, center_width, center_height); - int radius = width / 2 - tick_width / 2 - 1; - int nticks; - int tick_begin; - int tick_end; - if (self->end == self->start) + int radius = grub_min (height, width) / 2 - grub_max (tick_height, tick_width) / 2 - 1; + unsigned nticks; + unsigned tick_begin; + unsigned tick_end; + if (self->end <= self->start + || self->value <= self->start) nticks = 0; else - nticks = (self->num_ticks - * (self->value - self->start) - / (self->end - self->start)); + nticks = ((unsigned) (self->num_ticks + * (self->value - self->start))) + / ((unsigned) (self->end - self->start)); /* Do ticks appear or disappear as the value approached the end? */ if (self->ticks_disappear) { tick_begin = nticks; - tick_end = self->num_ticks - 1; + tick_end = self->num_ticks; } else { tick_begin = 0; - tick_end = nticks - 1; + tick_end = nticks; } - int i; + unsigned i; for (i = tick_begin; i < tick_end; i++) { int x; @@ -168,7 +169,8 @@ circprog_paint (void *vself, const grub_video_rect_t *region) int angle; /* Calculate the location of the tick. */ - angle = self->start_angle + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks; + angle = self->start_angle + + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks; x = width / 2 + (grub_cos (angle) * radius / GRUB_TRIG_FRACTION_SCALE); y = height / 2 + (grub_sin (angle) * radius / GRUB_TRIG_FRACTION_SCALE); @@ -223,17 +225,36 @@ circprog_set_state (void *vself, int visible, int start, self->end = end; } +static int +parse_angle (const char *value) +{ + char *ptr; + int angle; + + angle = grub_strtol (value, &ptr, 10); + if (grub_errno) + return 0; + while (grub_isspace (*ptr)) + ptr++; + if (grub_strcmp (ptr, "deg") == 0 + /* Unicode symbol of degrees (a circle, U+b0). Put here in UTF-8 to + avoid potential problem with text file reesncoding */ + || grub_strcmp (ptr, "\xc2\xb0") == 0) + angle = grub_divide_round (angle * 64, 90); + return angle; +} + static grub_err_t circprog_set_property (void *vself, const char *name, const char *value) { circular_progress_t self = vself; if (grub_strcmp (name, "num_ticks") == 0) { - self->num_ticks = grub_strtol (value, 0, 10); + self->num_ticks = grub_strtoul (value, 0, 10); } else if (grub_strcmp (name, "start_angle") == 0) { - self->start_angle = grub_strtol (value, 0, 10); + self->start_angle = parse_angle (value); } else if (grub_strcmp (name, "ticks_disappear") == 0) { diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c index 637578f77..507c01014 100644 --- a/grub-core/gfxmenu/gui_label.c +++ b/grub-core/gfxmenu/gui_label.c @@ -23,6 +23,7 @@ #include #include #include +#include static const char *align_options[] = { diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index 1982d9a40..5d26811f9 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -23,6 +23,13 @@ #include #include #include +#include + +enum scrollbar_slice_mode { + SCROLLBAR_SLICE_WEST, + SCROLLBAR_SLICE_CENTER, + SCROLLBAR_SLICE_EAST +}; struct grub_gui_list_impl { @@ -40,9 +47,10 @@ struct grub_gui_list_impl int item_icon_space; int item_spacing; grub_font_t item_font; + int selected_item_font_inherit; grub_font_t selected_item_font; grub_video_rgba_color_t item_color; - int selected_item_color_set; + int selected_item_color_inherit; grub_video_rgba_color_t selected_item_color; int draw_scrollbar; @@ -51,16 +59,25 @@ struct grub_gui_list_impl char *scrollbar_thumb_pattern; grub_gfxmenu_box_t scrollbar_frame; grub_gfxmenu_box_t scrollbar_thumb; + int scrollbar_thumb_overlay; int scrollbar_width; + enum scrollbar_slice_mode scrollbar_slice; + int scrollbar_left_pad; + int scrollbar_right_pad; + int scrollbar_top_pad; + int scrollbar_bottom_pad; int first_shown_index; int need_to_recreate_boxes; char *theme_dir; char *menu_box_pattern; + char *item_box_pattern; + int selected_item_box_pattern_inherit; char *selected_item_box_pattern; grub_gfxmenu_box_t menu_box; grub_gfxmenu_box_t selected_item_box; + grub_gfxmenu_box_t item_box; grub_gfxmenu_icon_manager_t icon_manager; @@ -76,14 +93,22 @@ list_destroy (void *vself) grub_free (self->theme_dir); grub_free (self->menu_box_pattern); + grub_free (self->item_box_pattern); grub_free (self->selected_item_box_pattern); if (self->menu_box) self->menu_box->destroy (self->menu_box); + if (self->item_box) + self->item_box->destroy (self->item_box); if (self->selected_item_box) self->selected_item_box->destroy (self->selected_item_box); if (self->icon_manager) grub_gfxmenu_icon_manager_destroy (self->icon_manager); - + if (self->scrollbar_thumb) + self->scrollbar_thumb->destroy (self->scrollbar_thumb); + if (self->scrollbar_frame) + self->scrollbar_frame->destroy (self->scrollbar_frame); + grub_free (self->scrollbar_thumb_pattern); + grub_free (self->scrollbar_frame_pattern); grub_free (self); } @@ -97,9 +122,18 @@ get_num_shown_items (list_impl_t self) grub_gfxmenu_box_t box = self->menu_box; int box_top_pad = box->get_top_pad (box); int box_bottom_pad = box->get_bottom_pad (box); - + grub_gfxmenu_box_t itembox = self->item_box; + grub_gfxmenu_box_t selbox = self->selected_item_box; + int item_top_pad = itembox->get_top_pad (itembox); + int item_bottom_pad = itembox->get_bottom_pad (itembox); + int sel_top_pad = selbox->get_top_pad (selbox); + int sel_bottom_pad = selbox->get_bottom_pad (selbox); + int max_top_pad = grub_max (item_top_pad, sel_top_pad); + int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad); + return (self->bounds.height + item_vspace - 2 * boxpad - - box_top_pad - box_bottom_pad) / (item_height + item_vspace); + - max_top_pad - max_bottom_pad + - box_top_pad - box_bottom_pad) / (item_height + item_vspace); } static int @@ -111,6 +145,10 @@ check_boxes (list_impl_t self) self->menu_box_pattern, self->theme_dir); + grub_gui_recreate_box (&self->item_box, + self->item_box_pattern, + self->theme_dir); + grub_gui_recreate_box (&self->selected_item_box, self->selected_item_box_pattern, self->theme_dir); @@ -118,7 +156,8 @@ check_boxes (list_impl_t self) self->need_to_recreate_boxes = 0; } - return (self->menu_box != 0 && self->selected_item_box != 0); + return (self->menu_box != 0 && self->selected_item_box != 0 + && self->item_box != 0); } static int @@ -137,7 +176,34 @@ check_scrollbar (list_impl_t self) self->need_to_recreate_scrollbar = 0; } - return (self->scrollbar_frame != 0 && self->scrollbar_thumb != 0); + if (self->scrollbar_frame == 0 || self->scrollbar_thumb == 0) + return 0; + + /* Sanity checks. */ + grub_gfxmenu_box_t frame = self->scrollbar_frame; + grub_gfxmenu_box_t thumb = self->scrollbar_thumb; + grub_gfxmenu_box_t menu = self->menu_box; + int min_width = frame->get_left_pad (frame) + + frame->get_right_pad (frame); + int min_height = frame->get_top_pad (frame) + + frame->get_bottom_pad (frame) + + self->scrollbar_top_pad + self->scrollbar_bottom_pad + + menu->get_top_pad (menu) + + menu->get_bottom_pad (menu); + if (!self->scrollbar_thumb_overlay) + { + min_width += thumb->get_left_pad (thumb) + + thumb->get_right_pad (thumb); + min_height += thumb->get_top_pad (thumb) + + thumb->get_bottom_pad (thumb); + } + if (min_width <= self->scrollbar_width + && min_height <= (int) self->bounds.height) + return 1; + + /* Unprintable dimenstions. */ + self->draw_scrollbar = 0; + return 0; } static const char * @@ -183,36 +249,73 @@ make_selected_item_visible (list_impl_t self) static void draw_scrollbar (list_impl_t self, int value, int extent, int min, int max, - int rightx, int topy, int height) + int scrollbar_width, int scrollbar_height) { + unsigned thumby, thumbheight; + grub_gfxmenu_box_t frame = self->scrollbar_frame; grub_gfxmenu_box_t thumb = self->scrollbar_thumb; int frame_vertical_pad = (frame->get_top_pad (frame) + frame->get_bottom_pad (frame)); int frame_horizontal_pad = (frame->get_left_pad (frame) + frame->get_right_pad (frame)); - int tracktop = topy + frame->get_top_pad (frame); - int tracklen = height - frame_vertical_pad; - frame->set_content_size (frame, self->scrollbar_width, tracklen); - int thumby = tracktop + tracklen * (value - min) / (max - min); - int thumbheight = tracklen * extent / (max - min) + 1; - thumb->set_content_size (thumb, - self->scrollbar_width - frame_horizontal_pad, - thumbheight - (thumb->get_top_pad (thumb) - + thumb->get_bottom_pad (thumb))); - frame->draw (frame, - rightx - (self->scrollbar_width + frame_horizontal_pad), - topy); - thumb->draw (thumb, - rightx - (self->scrollbar_width - frame->get_right_pad (frame)), - thumby); + unsigned thumb_vertical_pad = (thumb->get_top_pad (thumb) + + thumb->get_bottom_pad (thumb)); + int thumb_horizontal_pad = (thumb->get_left_pad (thumb) + + thumb->get_right_pad (thumb)); + int tracktop = frame->get_top_pad (frame); + unsigned tracklen; + if (scrollbar_height <= frame_vertical_pad) + tracklen = 0; + else + tracklen = scrollbar_height - frame_vertical_pad; + frame->set_content_size (frame, + scrollbar_width - frame_horizontal_pad, + tracklen); + if (self->scrollbar_thumb_overlay) + { + tracklen += thumb_vertical_pad; + tracktop -= thumb->get_top_pad (thumb); + } + if (value <= min || max <= min) + thumby = 0; + else + thumby = ((unsigned) tracklen * (value - min)) + / ((unsigned) (max - min)); + if (max <= min) + thumbheight = 1; + else + thumbheight = ((unsigned) (tracklen * extent) + / ((unsigned) (max - min))) + 1; + /* Rare occasion: too many entries or too low height. */ + if (thumbheight < thumb_vertical_pad) + { + thumbheight = thumb_vertical_pad; + if (value <= min || max <= extent + || tracklen <= thumb_vertical_pad) + thumby = 0; + else + thumby = ((unsigned) ((tracklen - thumb_vertical_pad) * (value - min)) + / ((unsigned)(max - extent))); + } + thumby += tracktop; + int thumbx = frame->get_left_pad (frame); + int thumbwidth = scrollbar_width - frame_horizontal_pad; + if (!self->scrollbar_thumb_overlay) + thumbwidth -= thumb_horizontal_pad; + else + thumbx -= thumb->get_left_pad (thumb); + thumb->set_content_size (thumb, thumbwidth, + thumbheight - thumb_vertical_pad); + frame->draw (frame, 0, 0); + thumb->draw (thumb, thumbx, thumby); } /* Draw the list of items. */ static void draw_menu (list_impl_t self, int num_shown_items) { - if (! self->menu_box || ! self->selected_item_box) + if (! self->menu_box || ! self->selected_item_box || ! self->item_box) return; int boxpad = self->item_padding; @@ -221,14 +324,26 @@ draw_menu (list_impl_t self, int num_shown_items) int ascent = grub_font_get_ascent (self->item_font); int descent = grub_font_get_descent (self->item_font); - int item_height = self->item_height; + int selected_ascent = grub_font_get_ascent (self->selected_item_font); + int selected_descent = grub_font_get_descent (self->selected_item_font); + int text_box_height = self->item_height; make_selected_item_visible (self); + grub_gfxmenu_box_t itembox = self->item_box; grub_gfxmenu_box_t selbox = self->selected_item_box; + int item_leftpad = itembox->get_left_pad (itembox); + int item_rightpad = itembox->get_right_pad (itembox); + int item_border_width = item_leftpad + item_rightpad; + int item_toppad = itembox->get_top_pad (itembox); int sel_leftpad = selbox->get_left_pad (selbox); + int sel_rightpad = selbox->get_right_pad (selbox); + int sel_border_width = sel_leftpad + sel_rightpad; int sel_toppad = selbox->get_top_pad (selbox); - int item_top = sel_toppad; + + int max_leftpad = grub_max (item_leftpad, sel_leftpad); + int max_toppad = grub_max (item_toppad, sel_toppad); + int item_top = 0; int menu_index; int visible_index; struct grub_video_rect oviewport; @@ -240,48 +355,92 @@ draw_menu (list_impl_t self, int num_shown_items) oviewport.width - 2 * boxpad, oviewport.height - 2 * boxpad); + int cwidth = oviewport.width - 2 * boxpad; + + itembox->set_content_size (itembox, cwidth - item_border_width, + text_box_height); + selbox->set_content_size (selbox, cwidth - sel_border_width, + text_box_height); + + int text_left_offset = self->icon_width + icon_text_space; + int item_text_top_offset = (text_box_height - (ascent + descent)) / 2 + ascent; + int sel_text_top_offset = (text_box_height - (selected_ascent + + selected_descent)) / 2 + + selected_ascent; + + grub_video_rect_t svpsave, sviewport; + sviewport.x = max_leftpad + text_left_offset; + int text_viewport_width = cwidth - sviewport.x; + sviewport.height = text_box_height; + + grub_video_color_t item_color; + grub_video_color_t sel_color; + item_color = grub_video_map_rgba_color (self->item_color); + sel_color = grub_video_map_rgba_color (self->selected_item_color); + + int item_box_top_offset = max_toppad - item_toppad; + int sel_box_top_offset = max_toppad - sel_toppad; + int item_viewport_width = text_viewport_width - item_rightpad; + int sel_viewport_width = text_viewport_width - sel_rightpad; + int tmp_icon_top_offset = (text_box_height - self->icon_height) / 2; + int item_icon_top_offset = item_toppad + tmp_icon_top_offset; + int sel_icon_top_offset = sel_toppad + tmp_icon_top_offset; + for (visible_index = 0, menu_index = self->first_shown_index; visible_index < num_shown_items && menu_index < self->view->menu->size; visible_index++, menu_index++) { int is_selected = (menu_index == self->view->selected); struct grub_video_bitmap *icon; + grub_font_t font; + grub_video_color_t color; + int text_top_offset; + int top_pad; + int icon_top_offset; + int viewport_width; if (is_selected) { - int cwidth = oviewport.width - 2 * boxpad - 2; - if (selbox->get_border_width) - cwidth -= selbox->get_border_width (selbox); - selbox->set_content_size (selbox, cwidth, item_height - 1); - selbox->draw (selbox, 0, - item_top - sel_toppad); + selbox->draw (selbox, 0, item_top + sel_box_top_offset); + font = self->selected_item_font; + color = sel_color; + text_top_offset = sel_text_top_offset; + top_pad = sel_toppad; + icon_top_offset = sel_icon_top_offset; + viewport_width = sel_viewport_width; + } + else + { + itembox->draw (itembox, 0, item_top + item_box_top_offset); + font = self->item_font; + color = item_color; + text_top_offset = item_text_top_offset; + top_pad = item_toppad; + icon_top_offset = item_icon_top_offset; + viewport_width = item_viewport_width; } icon = get_item_icon (self, menu_index); if (icon != 0) grub_video_blit_bitmap (icon, GRUB_VIDEO_BLIT_BLEND, - sel_leftpad, - item_top + (item_height - self->icon_height) / 2, + max_leftpad, + item_top + icon_top_offset, 0, 0, self->icon_width, self->icon_height); const char *item_title = grub_menu_get_entry (self->view->menu, menu_index)->title; - grub_font_t font = - (is_selected && self->selected_item_font - ? self->selected_item_font - : self->item_font); - grub_video_rgba_color_t text_color = - ((is_selected && self->selected_item_color_set) - ? self->selected_item_color - : self->item_color); + + sviewport.y = item_top + top_pad; + sviewport.width = viewport_width; + grub_gui_set_viewport (&sviewport, &svpsave); grub_font_draw_string (item_title, font, - grub_video_map_rgba_color (text_color), - sel_leftpad + self->icon_width + icon_text_space, - (item_top + (item_height - (ascent + descent)) - / 2 + ascent)); + color, + 0, + text_top_offset); + grub_gui_restore_viewport (&svpsave); - item_top += item_height + item_vspace; + item_top += text_box_height + item_vspace; } grub_video_set_viewport (oviewport.x, oviewport.y, @@ -302,7 +461,7 @@ list_paint (void *vself, const grub_video_rect_t *region) check_boxes (self); - if (! self->menu_box || ! self->selected_item_box) + if (! self->menu_box || ! self->selected_item_box || ! self->item_box) return; grub_gui_set_viewport (&self->bounds, &vpsave); @@ -317,6 +476,7 @@ list_paint (void *vself, const grub_video_rect_t *region) int drawing_scrollbar = (self->draw_scrollbar && (num_shown_items < self->view->menu->size) && check_scrollbar (self)); + int scrollbar_width = self->scrollbar_width; content_rect.x = box_left_pad; content_rect.y = box_top_pad; @@ -327,18 +487,65 @@ list_paint (void *vself, const grub_video_rect_t *region) box->draw (box, 0, 0); + switch (self->scrollbar_slice) + { + case SCROLLBAR_SLICE_WEST: + content_rect.x += self->scrollbar_right_pad; + content_rect.width -= self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_CENTER: + if (drawing_scrollbar) + content_rect.width -= scrollbar_width + self->scrollbar_left_pad + + self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_EAST: + content_rect.width -= self->scrollbar_left_pad; + break; + } + grub_gui_set_viewport (&content_rect, &vpsave2); draw_menu (self, num_shown_items); grub_gui_restore_viewport (&vpsave2); if (drawing_scrollbar) - draw_scrollbar (self, - self->first_shown_index, num_shown_items, - 0, self->view->menu->size, - self->bounds.width - box_right_pad - + self->scrollbar_width, - box_top_pad, - self->bounds.height - box_top_pad - box_bottom_pad); + { + content_rect.y += self->scrollbar_top_pad; + content_rect.height -= self->scrollbar_top_pad + + self->scrollbar_bottom_pad; + content_rect.width = scrollbar_width; + switch (self->scrollbar_slice) + { + case SCROLLBAR_SLICE_WEST: + if (box_left_pad > scrollbar_width) + { + content_rect.x = box_left_pad - scrollbar_width; + content_rect.width = scrollbar_width; + } + else + { + content_rect.x = 0; + content_rect.width = box_left_pad; + } + break; + case SCROLLBAR_SLICE_CENTER: + content_rect.x = self->bounds.width - box_right_pad + - scrollbar_width - self->scrollbar_right_pad; + content_rect.width = scrollbar_width; + break; + case SCROLLBAR_SLICE_EAST: + content_rect.x = self->bounds.width - box_right_pad; + content_rect.width = box_right_pad; + break; + } + + grub_gui_set_viewport (&content_rect, &vpsave2); + draw_scrollbar (self, + self->first_shown_index, num_shown_items, + 0, self->view->menu->size, + scrollbar_width, + content_rect.height); + grub_gui_restore_viewport (&vpsave2); + } } grub_gui_restore_viewport (&vpsave); @@ -392,21 +599,52 @@ list_get_minimal_size (void *vself, unsigned *width, unsigned *height) unsigned width_s; grub_gfxmenu_box_t selbox = self->selected_item_box; - int sel_toppad = selbox->get_top_pad (selbox); - + int sel_top_pad = selbox->get_top_pad (selbox); + int sel_bottom_pad = selbox->get_bottom_pad (selbox); + int sel_left_pad = selbox->get_left_pad (selbox); + int sel_right_pad = selbox->get_right_pad (selbox); + + grub_gfxmenu_box_t itembox = self->item_box; + int item_top_pad = itembox->get_top_pad (itembox); + int item_bottom_pad = itembox->get_bottom_pad (itembox); + int item_left_pad = itembox->get_left_pad (itembox); + int item_right_pad = itembox->get_right_pad (itembox); + + int max_left_pad = grub_max (item_left_pad, sel_left_pad); + int max_right_pad = grub_max (item_right_pad, sel_right_pad); + int max_top_pad = grub_max (item_top_pad, sel_top_pad); + int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad); + *width = grub_font_get_string_width (self->item_font, "Typical OS"); width_s = grub_font_get_string_width (self->selected_item_font, "Typical OS"); if (*width < width_s) *width = width_s; - *width += 2 * boxpad + box_left_pad + box_right_pad; + *width += 2 * boxpad + box_left_pad + box_right_pad + + max_left_pad + max_right_pad + + self->item_icon_space + self->icon_width; + + switch (self->scrollbar_slice) + { + case SCROLLBAR_SLICE_WEST: + *width += self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_CENTER: + *width += self->scrollbar_width + self->scrollbar_left_pad + + self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_EAST: + *width += self->scrollbar_left_pad; + break; + } /* Set the menu box height to fit the items. */ *height = (item_height * num_items + item_vspace * (num_items - 1) + 2 * boxpad - + box_top_pad + box_bottom_pad + sel_toppad); + + box_top_pad + box_bottom_pad + + max_top_pad + max_bottom_pad); } else { @@ -422,29 +660,48 @@ list_set_property (void *vself, const char *name, const char *value) if (grub_strcmp (name, "item_font") == 0) { self->item_font = grub_font_get (value); + if (self->selected_item_font_inherit) + self->selected_item_font = self->item_font; } else if (grub_strcmp (name, "selected_item_font") == 0) { if (! value || grub_strcmp (value, "inherit") == 0) - self->selected_item_font = 0; + { + self->selected_item_font = self->item_font; + self->selected_item_font_inherit = 1; + } else - self->selected_item_font = grub_font_get (value); + { + self->selected_item_font = grub_font_get (value); + self->selected_item_font_inherit = 0; + } } else if (grub_strcmp (name, "item_color") == 0) { - grub_video_parse_color (value, &self->item_color); + grub_video_rgba_color_t color; + if (grub_video_parse_color (value, &color) == GRUB_ERR_NONE) + { + self->item_color = color; + if (self->selected_item_color_inherit) + self->selected_item_color = self->item_color; + } } else if (grub_strcmp (name, "selected_item_color") == 0) { if (! value || grub_strcmp (value, "inherit") == 0) { - self->selected_item_color_set = 0; + self->selected_item_color = self->item_color; + self->selected_item_color_inherit = 1; } else { - if (grub_video_parse_color (value, &self->selected_item_color) + grub_video_rgba_color_t color; + if (grub_video_parse_color (value, &color) == GRUB_ERR_NONE) - self->selected_item_color_set = 1; + { + self->selected_item_color = color; + self->selected_item_color_inherit = 0; + } } } else if (grub_strcmp (name, "icon_width") == 0) @@ -487,11 +744,33 @@ list_set_property (void *vself, const char *name, const char *value) grub_free (self->menu_box_pattern); self->menu_box_pattern = value ? grub_strdup (value) : 0; } - else if (grub_strcmp (name, "selected_item_pixmap_style") == 0) + else if (grub_strcmp (name, "item_pixmap_style") == 0) { self->need_to_recreate_boxes = 1; - grub_free (self->selected_item_box_pattern); - self->selected_item_box_pattern = value ? grub_strdup (value) : 0; + grub_free (self->item_box_pattern); + self->item_box_pattern = value ? grub_strdup (value) : 0; + if (self->selected_item_box_pattern_inherit) + { + grub_free (self->selected_item_box_pattern); + self->selected_item_box_pattern = value ? grub_strdup (value) : 0; + } + } + else if (grub_strcmp (name, "selected_item_pixmap_style") == 0) + { + if (!value || grub_strcmp (value, "inherit") == 0) + { + grub_free (self->selected_item_box_pattern); + char *tmp = self->item_box_pattern; + self->selected_item_box_pattern = tmp ? grub_strdup (tmp) : 0; + self->selected_item_box_pattern_inherit = 1; + } + else + { + self->need_to_recreate_boxes = 1; + grub_free (self->selected_item_box_pattern); + self->selected_item_box_pattern = value ? grub_strdup (value) : 0; + self->selected_item_box_pattern_inherit = 0; + } } else if (grub_strcmp (name, "scrollbar_frame") == 0) { @@ -505,10 +784,39 @@ list_set_property (void *vself, const char *name, const char *value) grub_free (self->scrollbar_thumb_pattern); self->scrollbar_thumb_pattern = value ? grub_strdup (value) : 0; } + else if (grub_strcmp (name, "scrollbar_thumb_overlay") == 0) + { + self->scrollbar_thumb_overlay = grub_strcmp (value, "true") == 0; + } else if (grub_strcmp (name, "scrollbar_width") == 0) { self->scrollbar_width = grub_strtol (value, 0, 10); } + else if (grub_strcmp (name, "scrollbar_slice") == 0) + { + if (grub_strcmp (value, "west") == 0) + self->scrollbar_slice = SCROLLBAR_SLICE_WEST; + else if (grub_strcmp (value, "center") == 0) + self->scrollbar_slice = SCROLLBAR_SLICE_CENTER; + else if (grub_strcmp (value, "east") == 0) + self->scrollbar_slice = SCROLLBAR_SLICE_EAST; + } + else if (grub_strcmp (name, "scrollbar_left_pad") == 0) + { + self->scrollbar_left_pad = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar_right_pad") == 0) + { + self->scrollbar_right_pad = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar_top_pad") == 0) + { + self->scrollbar_top_pad = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar_bottom_pad") == 0) + { + self->scrollbar_bottom_pad = grub_strtol (value, 0, 10); + } else if (grub_strcmp (name, "scrollbar") == 0) { self->draw_scrollbar = grub_strcmp (value, "false") != 0; @@ -541,6 +849,16 @@ list_set_view_info (void *vself, self->view = view; } +/* Refresh list variables */ +static void +list_refresh_info (void *vself, + grub_gfxmenu_view_t view) +{ + list_impl_t self = vself; + if (view->nested) + self->first_shown_index = 0; +} + static struct grub_gui_component_ops list_comp_ops = { .destroy = list_destroy, @@ -557,7 +875,8 @@ static struct grub_gui_component_ops list_comp_ops = static struct grub_gui_list_ops list_ops = { - .set_view_info = list_set_view_info + .set_view_info = list_set_view_info, + .refresh_list = list_refresh_info }; grub_gui_component_t @@ -586,9 +905,10 @@ grub_gui_list_new (void) self->item_icon_space = 4; self->item_spacing = 16; self->item_font = default_font; - self->selected_item_font = 0; /* Default to using the item_font. */ + self->selected_item_font_inherit = 1; /* Default to using the item_font. */ + self->selected_item_font = default_font; self->item_color = default_fg_color; - self->selected_item_color_set = 0; /* Default to using the item_color. */ + self->selected_item_color_inherit = 1; /* Default to using the item_color. */ self->selected_item_color = default_fg_color; self->draw_scrollbar = 1; @@ -597,15 +917,24 @@ grub_gui_list_new (void) self->scrollbar_thumb = 0; self->scrollbar_frame_pattern = 0; self->scrollbar_thumb_pattern = 0; + self->scrollbar_thumb_overlay = 0; self->scrollbar_width = 16; + self->scrollbar_slice = SCROLLBAR_SLICE_EAST; + self->scrollbar_left_pad = 2; + self->scrollbar_right_pad = 0; + self->scrollbar_top_pad = 0; + self->scrollbar_bottom_pad = 0; self->first_shown_index = 0; self->need_to_recreate_boxes = 0; self->theme_dir = 0; self->menu_box_pattern = 0; + self->item_box_pattern = 0; + self->selected_item_box_pattern_inherit = 1;/*Default to using the item_box.*/ self->selected_item_box_pattern = 0; self->menu_box = grub_gfxmenu_create_box (0, 0); + self->item_box = grub_gfxmenu_create_box (0, 0); self->selected_item_box = grub_gfxmenu_create_box (0, 0); self->icon_manager = grub_gfxmenu_icon_manager_new (); diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c index 7b005f400..605c10997 100644 --- a/grub-core/gfxmenu/gui_progress_bar.c +++ b/grub-core/gfxmenu/gui_progress_bar.c @@ -25,6 +25,7 @@ #include #include #include +#include struct grub_gui_progress_bar { @@ -51,6 +52,7 @@ struct grub_gui_progress_bar char *highlight_pattern; grub_gfxmenu_box_t bar_box; grub_gfxmenu_box_t highlight_box; + int highlight_overlay; }; typedef struct grub_gui_progress_bar *grub_gui_progress_bar_t; @@ -59,6 +61,9 @@ static void progress_bar_destroy (void *vself) { grub_gui_progress_bar_t self = vself; + grub_free (self->theme_dir); + grub_free (self->template); + grub_free (self->id); grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self); grub_free (self); } @@ -139,19 +144,43 @@ draw_pixmap_bar (grub_gui_progress_bar_t self) int bar_b_pad = bar->get_bottom_pad (bar); int bar_h_pad = bar_l_pad + bar_r_pad; int bar_v_pad = bar_t_pad + bar_b_pad; + int hl_l_pad = hl->get_left_pad (hl); + int hl_r_pad = hl->get_right_pad (hl); + int hl_t_pad = hl->get_top_pad (hl); + int hl_b_pad = hl->get_bottom_pad (hl); + int hl_h_pad = hl_l_pad + hl_r_pad; + int hl_v_pad = hl_t_pad + hl_b_pad; int tracklen = w - bar_h_pad; int trackheight = h - bar_v_pad; int barwidth; + int hlheight = trackheight; + int hlx = bar_l_pad; + int hly = bar_t_pad; bar->set_content_size (bar, tracklen, trackheight); - - barwidth = (tracklen * (self->value - self->start) - / (self->end - self->start)); - - hl->set_content_size (hl, barwidth, h - bar_v_pad); - bar->draw (bar, 0, 0); - hl->draw (hl, bar_l_pad, bar_t_pad); + + if (self->highlight_overlay) + { + tracklen += hl_h_pad; + hlx -= hl_l_pad; + hly -= hl_t_pad; + } + else + hlheight -= hl_v_pad; + + if (self->value <= self->start + || self->end <= self->start) + barwidth = 0; + else + barwidth = ((unsigned) (tracklen * (self->value - self->start)) + / ((unsigned) (self->end - self->start))); + + if (barwidth >= hl_h_pad) + { + hl->set_content_size (hl, barwidth - hl_h_pad, hlheight); + hl->draw (hl, hlx, hly); + } } static void @@ -179,6 +208,7 @@ draw_text (grub_gui_progress_bar_t self) int y = ((height - grub_font_get_descent (font)) / 2 + grub_font_get_ascent (font) / 2); grub_font_draw_string (text, font, text_color, x, y); + grub_free (text); } } @@ -240,22 +270,40 @@ static void progress_bar_get_minimal_size (void *vself, unsigned *width, unsigned *height) { - unsigned text_width = 0, text_height = 0; + unsigned min_width = 0; + unsigned min_height = 0; grub_gui_progress_bar_t self = vself; if (self->template) { - text_width = grub_font_get_string_width (self->font, self->template); - text_width += grub_font_get_string_width (self->font, "XXXXXXXXXX"); - text_height = grub_font_get_descent (self->font) - + grub_font_get_ascent (self->font); + min_width = grub_font_get_string_width (self->font, self->template); + min_width += grub_font_get_string_width (self->font, "XXXXXXXXXX"); + min_height = grub_font_get_descent (self->font) + + grub_font_get_ascent (self->font); + } + if (check_pixmaps (self)) + { + grub_gfxmenu_box_t bar = self->bar_box; + grub_gfxmenu_box_t hl = self->highlight_box; + min_width += bar->get_left_pad (bar) + bar->get_right_pad (bar); + min_height += bar->get_top_pad (bar) + bar->get_bottom_pad (bar); + if (!self->highlight_overlay) + { + min_width += hl->get_left_pad (hl) + hl->get_right_pad (hl); + min_height += hl->get_top_pad (hl) + hl->get_bottom_pad (hl); + } + } + else + { + min_height += 2; + min_width += 2; } *width = 200; - if (*width < text_width) - *width = text_width; + if (*width < min_width) + *width = min_width; *height = 28; - if (*height < text_height) - *height = text_height; + if (*height < min_height) + *height = min_height; } static void @@ -326,6 +374,10 @@ progress_bar_set_property (void *vself, const char *name, const char *value) grub_free (self->highlight_pattern); self->highlight_pattern = value ? grub_strdup (value) : 0; } + else if (grub_strcmp (name, "highlight_overlay") == 0) + { + self->highlight_overlay = grub_strcmp (value, "true") == 0; + } else if (grub_strcmp (name, "theme_dir") == 0) { self->need_to_recreate_pixmaps = 1; @@ -386,6 +438,7 @@ grub_gui_progress_bar_new (void) self->border_color = black; self->bg_color = gray; self->fg_color = lightgray; + self->highlight_overlay = 0; return (grub_gui_component_t) self; } diff --git a/grub-core/gfxmenu/icon_manager.c b/grub-core/gfxmenu/icon_manager.c index 45e8f7dea..ff49ab0e0 100644 --- a/grub-core/gfxmenu/icon_manager.c +++ b/grub-core/gfxmenu/icon_manager.c @@ -137,23 +137,19 @@ static struct grub_video_bitmap * try_loading_icon (grub_gfxmenu_icon_manager_t mgr, const char *dir, const char *class_name) { - char *path; - int l; + char *path, *ptr; path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + grub_strlen (icon_extension) + 3); if (! path) return 0; - grub_strcpy (path, dir); - l = grub_strlen (path); - if (path[l-1] != '/') - { - path[l] = '/'; - path[l+1] = 0; - } - grub_strcat (path, class_name); - grub_strcat (path, icon_extension); + ptr = grub_stpcpy (path, dir); + if (path == ptr || ptr[-1] != '/') + *ptr++ = '/'; + ptr = grub_stpcpy (ptr, class_name); + ptr = grub_stpcpy (ptr, icon_extension); + *ptr = '\0'; struct grub_video_bitmap *raw_bitmap; grub_video_bitmap_load (&raw_bitmap, path); diff --git a/grub-core/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c index f9c711d3e..8a7945816 100644 --- a/grub-core/gfxmenu/theme_loader.c +++ b/grub-core/gfxmenu/theme_loader.c @@ -30,6 +30,10 @@ #include #include #include +#include + +static grub_err_t +parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop); /* Construct a new box widget using ABSPATTERN to find the pixmap files for it, storing the new box instance at *BOXPTR. @@ -112,6 +116,24 @@ grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr, return grub_errno; } +static grub_err_t +theme_get_unsigned_int_from_proportional (const char *value, + unsigned absolute_value, + unsigned int *parsed_value) +{ + grub_err_t err; + grub_fixed_signed_t frac; + signed pixels; + err = parse_proportional_spec (value, &pixels, &frac); + if (err != GRUB_ERR_NONE) + return err; + int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels; + if (result < 0) + result = 0; + *parsed_value = result; + return GRUB_ERR_NONE; +} + /* Set the specified property NAME on the view to the given string VALUE. The caller is responsible for the lifetimes of NAME and VALUE. */ static grub_err_t @@ -143,7 +165,6 @@ theme_set_string (grub_gfxmenu_view_t view, else if (! grub_strcmp ("desktop-image", name)) { struct grub_video_bitmap *raw_bitmap; - struct grub_video_bitmap *scaled_bitmap; char *path; path = grub_resolve_relative_path (theme_dir, value); if (! path) @@ -154,20 +175,56 @@ theme_set_string (grub_gfxmenu_view_t view, return grub_errno; } grub_free(path); - grub_video_bitmap_create_scaled (&scaled_bitmap, - view->screen.width, - view->screen.height, - raw_bitmap, - GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); - grub_video_bitmap_destroy (raw_bitmap); - if (! scaled_bitmap) - { - grub_error_push (); - return grub_error (grub_errno, "error scaling desktop image"); - } - - grub_video_bitmap_destroy (view->desktop_image); - view->desktop_image = scaled_bitmap; + grub_video_bitmap_destroy (view->raw_desktop_image); + view->raw_desktop_image = raw_bitmap; + } + else if (! grub_strcmp ("desktop-image-scale-method", name)) + { + if (! value || ! grub_strcmp ("stretch", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH; + else if (! grub_strcmp ("crop", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP; + else if (! grub_strcmp ("padding", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING; + else if (! grub_strcmp ("fitwidth", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH; + else if (! grub_strcmp ("fitheight", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported scale method: %s", + value); + } + else if (! grub_strcmp ("desktop-image-h-align", name)) + { + if (! grub_strcmp ("left", value)) + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT; + else if (! grub_strcmp ("center", value)) + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER; + else if (! grub_strcmp ("right", value)) + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported horizontal align method: %s", + value); + } + else if (! grub_strcmp ("desktop-image-v-align", name)) + { + if (! grub_strcmp ("top", value)) + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP; + else if (! grub_strcmp ("center", value)) + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER; + else if (! grub_strcmp ("bottom", value)) + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported vertical align method: %s", + value); } else if (! grub_strcmp ("desktop-color", name)) grub_video_parse_color (value, &view->desktop_color); @@ -178,6 +235,52 @@ theme_set_string (grub_gfxmenu_view_t view, if (err != GRUB_ERR_NONE) return err; } + else if (! grub_strcmp ("terminal-border", name)) + { + view->terminal_border = grub_strtoul (value, 0, 10); + if (grub_errno) + return grub_errno; + } + else if (! grub_strcmp ("terminal-left", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.width, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.x = tmp; + } + else if (! grub_strcmp ("terminal-top", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.width, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.y = tmp; + } + else if (! grub_strcmp ("terminal-width", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.width, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.width = tmp; + } + else if (! grub_strcmp ("terminal-height", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.width, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.height = tmp; + } else if (! grub_strcmp ("title-text", name)) { grub_free (view->title_text); @@ -362,10 +465,10 @@ read_expression (struct parsebuf *p) } static grub_err_t -parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop) +parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop) { signed num; - char *ptr; + const char *ptr; int sig = 0; *abs = 0; *prop = 0; @@ -381,7 +484,7 @@ parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop) ptr++; } - num = grub_strtoul (ptr, &ptr, 0); + num = grub_strtoul (ptr, (char **) &ptr, 0); if (grub_errno) return grub_errno; if (sig) diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c index 9023fd3c4..ad5e82b81 100644 --- a/grub-core/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -40,7 +40,8 @@ static void init_terminal (grub_gfxmenu_view_t view); -static grub_video_rect_t term_rect; +static void +init_background (grub_gfxmenu_view_t view); static grub_gfxmenu_view_t term_view; /* Create a new view object, loading the theme specified by THEME_PATH and @@ -58,11 +59,28 @@ grub_gfxmenu_view_new (const char *theme_path, if (! view) return 0; + while (grub_gfxmenu_timeout_notifications) + { + struct grub_gfxmenu_timeout_notify *p; + p = grub_gfxmenu_timeout_notifications; + grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next; + grub_free (p); + } + view->screen.x = 0; view->screen.y = 0; view->screen.width = width; view->screen.height = height; + view->need_to_check_sanity = 1; + view->terminal_border = 3; + view->terminal_rect.width = view->screen.width * 7 / 10; + view->terminal_rect.height = view->screen.height * 7 / 10; + view->terminal_rect.x = view->screen.x + (view->screen.width + - view->terminal_rect.width) / 2; + view->terminal_rect.y = view->screen.y + (view->screen.height + - view->terminal_rect.height) / 2; + default_font = grub_font_get ("Unknown Regular 16"); default_fg_color = grub_video_rgba_color_rgb (0, 0, 0); default_bg_color = grub_video_rgba_color_rgb (255, 255, 255); @@ -75,7 +93,11 @@ grub_gfxmenu_view_new (const char *theme_path, view->title_color = default_fg_color; view->message_color = default_bg_color; view->message_bg_color = default_fg_color; - view->desktop_image = 0; + view->raw_desktop_image = 0; + view->scaled_desktop_image = 0; + view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH; + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER; + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER; view->desktop_color = default_bg_color; view->terminal_box = grub_gfxmenu_create_box (0, 0); view->title_text = grub_strdup (_("GRUB Boot Menu")); @@ -105,7 +127,15 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view) { if (!view) return; - grub_video_bitmap_destroy (view->desktop_image); + while (grub_gfxmenu_timeout_notifications) + { + struct grub_gfxmenu_timeout_notify *p; + p = grub_gfxmenu_timeout_notifications; + grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next; + grub_free (p); + } + grub_video_bitmap_destroy (view->raw_desktop_image); + grub_video_bitmap_destroy (view->scaled_desktop_image); if (view->terminal_box) view->terminal_box->destroy (view->terminal_box); grub_free (view->terminal_font_name); @@ -121,9 +151,9 @@ static void redraw_background (grub_gfxmenu_view_t view, const grub_video_rect_t *bounds) { - if (view->desktop_image) + if (view->scaled_desktop_image) { - struct grub_video_bitmap *img = view->desktop_image; + struct grub_video_bitmap *img = view->scaled_desktop_image; grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE, bounds->x, bounds->y, bounds->x - view->screen.x, @@ -183,6 +213,7 @@ redraw_timeouts (struct grub_gfxmenu_view *view) { grub_video_rect_t bounds; cur->self->ops->get_bounds (cur->self, &bounds); + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); grub_gfxmenu_view_redraw (view, &bounds); } } @@ -195,7 +226,7 @@ grub_gfxmenu_print_timeout (int timeout, void *data) if (view->first_timeout == -1) view->first_timeout = timeout; - update_timeouts (1, -(view->first_timeout + 1), -timeout, 0); + update_timeouts (1, -view->first_timeout, -timeout, 0); redraw_timeouts (view); grub_video_swap_buffers (); if (view->double_repaint) @@ -236,6 +267,27 @@ update_menu_components (grub_gfxmenu_view_t view) update_menu_visit, view); } +static void +refresh_menu_visit (grub_gui_component_t component, + void *userdata) +{ + grub_gfxmenu_view_t view; + view = userdata; + if (component->ops->is_instance (component, "list")) + { + grub_gui_list_t list = (grub_gui_list_t) component; + list->ops->refresh_list (list, view); + } +} + +/* Refresh list information (useful for submenus) */ +static void +refresh_menu_components (grub_gfxmenu_view_t view) +{ + grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas, + refresh_menu_visit, view); +} + static void draw_message (grub_gfxmenu_view_t view) { @@ -266,10 +318,15 @@ void grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, const grub_video_rect_t *region) { - if (grub_video_have_common_points (&term_rect, region)) + if (grub_video_have_common_points (&view->terminal_rect, region)) grub_gfxterm_schedule_repaint (); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_area_status_t area_status; + grub_video_get_area_status (&area_status); + if (area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_region (region->x, region->y, + region->width, region->height); redraw_background (view, region); if (view->canvas) @@ -277,6 +334,9 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, draw_title (view); if (grub_video_have_common_points (&view->progress_message_frame, region)) draw_message (view); + + if (area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } void @@ -284,6 +344,8 @@ grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) { init_terminal (view); + init_background (view); + /* Clear the screen; there may be garbage left over in video memory. */ grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), view->screen.x, view->screen.y, @@ -294,12 +356,18 @@ grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) view->screen.x, view->screen.y, view->screen.width, view->screen.height); + refresh_menu_components (view); update_menu_components (view); + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); grub_gfxmenu_view_redraw (view, &view->screen); grub_video_swap_buffers (); if (view->double_repaint) - grub_gfxmenu_view_redraw (view, &view->screen); + { + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + grub_gfxmenu_view_redraw (view, &view->screen); + } + } static void @@ -313,6 +381,7 @@ redraw_menu_visit (grub_gui_component_t component, grub_video_rect_t bounds; component->ops->get_bounds (component, &bounds); + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); grub_gfxmenu_view_redraw (view, &bounds); } } @@ -349,36 +418,167 @@ grub_gfxmenu_draw_terminal_box (void) term_box = term_view->terminal_box; if (!term_box) return; - - term_box->set_content_size (term_box, term_rect.width, - term_rect.height); + + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + + term_box->set_content_size (term_box, term_view->terminal_rect.width, + term_view->terminal_rect.height); term_box->draw (term_box, - term_rect.x - term_box->get_left_pad (term_box), - term_rect.y - term_box->get_top_pad (term_box)); + term_view->terminal_rect.x - term_box->get_left_pad (term_box), + term_view->terminal_rect.y - term_box->get_top_pad (term_box)); +} + +static void +get_min_terminal (grub_font_t terminal_font, + unsigned int border_width, + unsigned int *min_terminal_width, + unsigned int *min_terminal_height) +{ + struct grub_font_glyph *glyph; + glyph = grub_font_get_glyph (terminal_font, 'M'); + *min_terminal_width = (glyph? glyph->device_width : 8) * 80 + + 2 * border_width; + *min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24 + + 2 * border_width; +} + +static void +terminal_sanity_check (grub_gfxmenu_view_t view) +{ + if (!view->need_to_check_sanity) + return; + + /* terminal_font was checked before in the init_terminal function. */ + grub_font_t terminal_font = grub_font_get (view->terminal_font_name); + + /* Non-negative numbers below. */ + int scr_x = view->screen.x; + int scr_y = view->screen.y; + int scr_width = view->screen.width; + int scr_height = view->screen.height; + int term_x = view->terminal_rect.x; + int term_y = view->terminal_rect.y; + int term_width = view->terminal_rect.width; + int term_height = view->terminal_rect.height; + + /* Check that border_width isn't too big. */ + unsigned int border_width = view->terminal_border; + unsigned int min_terminal_width; + unsigned int min_terminal_height; + get_min_terminal (terminal_font, border_width, + &min_terminal_width, &min_terminal_height); + if (border_width > 3 && ((int) min_terminal_width >= scr_width + || (int) min_terminal_height >= scr_height)) + { + border_width = 3; + get_min_terminal (terminal_font, border_width, + &min_terminal_width, &min_terminal_height); + } + + /* Sanity checks. */ + if (term_width > scr_width) + term_width = scr_width; + if (term_height > scr_height) + term_height = scr_height; + + if (scr_width <= (int) min_terminal_width + || scr_height <= (int) min_terminal_height) + { + /* The screen resulution is too low. Use all space, except a small border + to show the user, that it is a window. Then center the window. */ + term_width = scr_width - 6 * border_width; + term_height = scr_height - 6 * border_width; + term_x = scr_x + (scr_width - term_width) / 2; + term_y = scr_y + (scr_height - term_height) / 2; + } + else if (term_width < (int) min_terminal_width + || term_height < (int) min_terminal_height) + { + /* The screen resolution is big enough. Make sure, that terminal screen + dimensions aren't less than minimal values. Then center the window. */ + term_width = (int) min_terminal_width; + term_height = (int) min_terminal_height; + term_x = scr_x + (scr_width - term_width) / 2; + term_y = scr_y + (scr_height - term_height) / 2; + } + + /* At this point w and h are satisfying. */ + if (term_x + term_width > scr_width) + term_x = scr_width - term_width; + if (term_y + term_height > scr_height) + term_y = scr_height - term_height; + + /* Write down corrected data. */ + view->terminal_rect.x = (unsigned int) term_x; + view->terminal_rect.y = (unsigned int) term_y; + view->terminal_rect.width = (unsigned int) term_width; + view->terminal_rect.height = (unsigned int) term_height; + view->terminal_border = border_width; + + view->need_to_check_sanity = 0; } static void init_terminal (grub_gfxmenu_view_t view) { - term_rect.width = view->screen.width * 7 / 10; - term_rect.height = view->screen.height * 7 / 10; + grub_font_t terminal_font; - term_rect.x = view->screen.x + view->screen.width * (10 - 7) / 10 / 2; - term_rect.y = view->screen.y + view->screen.height * (10 - 7) / 10 / 2; + terminal_font = grub_font_get (view->terminal_font_name); + if (!terminal_font) + { + grub_error (GRUB_ERR_BAD_FONT, "no font loaded"); + return; + } + + /* Check that terminal window size and position are sane. */ + terminal_sanity_check (view); term_view = view; /* Note: currently there is no API for changing the gfxterm font on the fly, so whatever font the initially loaded theme specifies will be permanent. */ - grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, term_rect.x, - term_rect.y, - term_rect.width, term_rect.height, - view->double_repaint, view->terminal_font_name, 3); + grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, + view->terminal_rect.x, + view->terminal_rect.y, + view->terminal_rect.width, + view->terminal_rect.height, + view->double_repaint, + terminal_font, + view->terminal_border); grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box; } +static void +init_background (grub_gfxmenu_view_t view) +{ + if (view->scaled_desktop_image) + return; + + struct grub_video_bitmap *scaled_bitmap; + if (view->desktop_image_scale_method == + GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH) + grub_video_bitmap_create_scaled (&scaled_bitmap, + view->screen.width, + view->screen.height, + view->raw_desktop_image, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + else + grub_video_bitmap_scale_proportional (&scaled_bitmap, + view->screen.width, + view->screen.height, + view->raw_desktop_image, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST, + view->desktop_image_scale_method, + view->desktop_image_v_align, + view->desktop_image_h_align); + if (! scaled_bitmap) + return; + view->scaled_desktop_image = scaled_bitmap; + +} + /* FIXME: previously notifications were displayed in special case. Is it necessary? */ diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c index 18e2ef469..b60602889 100644 --- a/grub-core/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -80,9 +80,25 @@ draw (grub_gfxmenu_box_t self, int x, int y) { int height_n; int width_w; + int tmp; - height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); - width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); + /* Count maximum height of NW, N, NE. */ + height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_NW]); + tmp = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); + if (tmp > height_n) + height_n = tmp; + tmp = get_height (self->scaled_pixmaps[BOX_PIXMAP_NE]); + if (tmp > height_n) + height_n = tmp; + + /* Count maximum width of NW, W, SW. */ + width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_NW]); + tmp = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); + if (tmp > width_w) + width_w = tmp; + tmp = get_width (self->scaled_pixmaps[BOX_PIXMAP_SW]); + if (tmp > width_w) + width_w = tmp; /* Draw sides. */ blit (self, BOX_PIXMAP_N, x + width_w, y); diff --git a/grub-core/gnulib-fix-null-deref.diff b/grub-core/gnulib-fix-null-deref.diff new file mode 100644 index 000000000..a2fba8c3b --- /dev/null +++ b/grub-core/gnulib-fix-null-deref.diff @@ -0,0 +1,13 @@ +=== modified file 'grub-core/gnulib/argp-parse.c' +--- grub-core/gnulib/argp-parse.c 2010-04-02 22:45:01 +0000 ++++ grub-core/gnulib/argp-parse.c 2011-04-10 13:25:52 +0000 +@@ -935,7 +935,7 @@ + void * + __argp_input (const struct argp *argp, const struct argp_state *state) + { +- if (state) ++ if (state && state->pstate) + { + struct group *group; + struct parser *parser = state->pstate; + diff --git a/grub-core/gnulib-fix-width.diff b/grub-core/gnulib-fix-width.diff new file mode 100644 index 000000000..ae77af6c9 --- /dev/null +++ b/grub-core/gnulib-fix-width.diff @@ -0,0 +1,231 @@ +diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c +index 7aa317c..02406ff 100644 +--- a/lib/argp-fmtstream.c ++++ b/lib/argp-fmtstream.c +@@ -29,9 +29,11 @@ + #include + #include + #include ++#include + + #include "argp-fmtstream.h" + #include "argp-namefrob.h" ++#include "mbswidth.h" + + #ifndef ARGP_FMTSTREAM_USE_LINEWRAP + +@@ -116,6 +118,51 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free) + #endif + #endif + ++ ++/* Return the pointer to the first character that doesn't fit in l columns. */ ++static inline const ptrdiff_t ++add_width (const char *ptr, const char *end, size_t l) ++{ ++ mbstate_t ps; ++ const char *ptr0 = ptr; ++ ++ memset (&ps, 0, sizeof (ps)); ++ ++ while (ptr < end) ++ { ++ wchar_t wc; ++ size_t s, k; ++ ++ s = mbrtowc (&wc, ptr, end - ptr, &ps); ++ if (s == (size_t) -1) ++ break; ++ if (s == (size_t) -2) ++ { ++ if (1 >= l) ++ break; ++ l--; ++ ptr++; ++ continue; ++ } ++ ++ if (wc == '\e' && ptr + 3 < end ++ && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1') ++ && ptr[3] == 'm') ++ { ++ ptr += 4; ++ continue; ++ } ++ ++ k = wcwidth (wc); ++ ++ if (k >= l) ++ break; ++ l -= k; ++ ptr += s; ++ } ++ return ptr - ptr0; ++} ++ + /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the + end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ + void +@@ -168,14 +215,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + + if (!nl) + { ++ size_t display_width = mbsnwidth (buf, fs->p - buf, MBSW_STOP_AT_NUL); + /* The buffer ends in a partial line. */ + +- if (fs->point_col + len < fs->rmargin) ++ if (fs->point_col + display_width < fs->rmargin) + { + /* The remaining buffer text is a partial line and fits + within the maximum line width. Advance point for the + characters to be written and stop scanning. */ +- fs->point_col += len; ++ fs->point_col += display_width; + break; + } + else +@@ -183,14 +231,18 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + the end of the buffer. */ + nl = fs->p; + } +- else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) +- { +- /* The buffer contains a full line that fits within the maximum +- line width. Reset point and scan the next line. */ +- fs->point_col = 0; +- buf = nl + 1; +- continue; +- } ++ else ++ { ++ size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL); ++ if (display_width < (ssize_t) fs->rmargin) ++ { ++ /* The buffer contains a full line that fits within the maximum ++ line width. Reset point and scan the next line. */ ++ fs->point_col = 0; ++ buf = nl + 1; ++ continue; ++ } ++ } + + /* This line is too long. */ + r = fs->rmargin - 1; +@@ -226,7 +278,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + char *p, *nextline; + int i; + +- p = buf + (r + 1 - fs->point_col); ++ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + while (p >= buf && !isblank ((unsigned char) *p)) + --p; + nextline = p + 1; /* This will begin the next line. */ +@@ -244,7 +296,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + { + /* A single word that is greater than the maximum line width. + Oh well. Put it on an overlong line by itself. */ +- p = buf + (r + 1 - fs->point_col); ++ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + /* Find the end of the long word. */ + if (p < nl) + do +@@ -278,7 +330,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + && fs->p > nextline) + { + /* The margin needs more blanks than we removed. */ +- if (fs->end - fs->p > fs->wmargin + 1) ++ if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL) ++ > fs->wmargin + 1) + /* Make some space for them. */ + { + size_t mv = fs->p - nextline; +diff --git a/lib/argp-help.c b/lib/argp-help.c +index 354f1e2..2914f47 100644 +--- a/lib/argp-help.c ++++ b/lib/argp-help.c +@@ -50,6 +50,7 @@ + #include "argp.h" + #include "argp-fmtstream.h" + #include "argp-namefrob.h" ++#include "mbswidth.h" + + #ifndef SIZE_MAX + # define SIZE_MAX ((size_t) -1) +@@ -1452,7 +1453,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, + + /* Manually do line wrapping so that it (probably) won't get wrapped at + any embedded spaces. */ +- space (stream, 1 + nl - cp); ++ space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL)); + + __argp_fmtstream_write (stream, cp, nl - cp); + } +diff --git a/lib/mbswidth.c b/lib/mbswidth.c +index 7c2dfce..baa4f27 100644 +--- a/lib/mbswidth.c ++++ b/lib/mbswidth.c +@@ -90,6 +90,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags) + p++; + width++; + break; ++ case '\0': ++ if (flags & MBSW_STOP_AT_NUL) ++ return width; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { +@@ -168,6 +171,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags) + { + unsigned char c = (unsigned char) *p++; + ++ if (c == 0 && (flags & MBSW_STOP_AT_NUL)) ++ return width; ++ + if (isprint (c)) + { + if (width == INT_MAX) +diff --git a/lib/mbswidth.h b/lib/mbswidth.h +index e9c0b03..d7207c5 100644 +--- a/lib/mbswidth.h ++++ b/lib/mbswidth.h +@@ -45,6 +45,9 @@ extern "C" { + control characters and 1 otherwise. */ + #define MBSW_REJECT_UNPRINTABLE 2 + ++/* If this bit is set \0 is treated as the end of string. ++ Otherwise it's treated as a normal one column width character. */ ++#define MBSW_STOP_AT_NUL 4 + + /* Returns the number of screen columns needed for STRING. */ + #define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ +diff --git a/modules/argp b/modules/argp +index 125046a..6f14d10 100644 +--- a/modules/argp ++++ b/modules/argp +@@ -40,6 +40,7 @@ stdalign + strerror + memchr + memmove ++mbswidth + + configure.ac: + gl_ARGP +diff --git a/modules/argp-tests b/modules/argp-tests +index 8f92a4d..0463927 100644 +--- a/modules/argp-tests ++++ b/modules/argp-tests +@@ -1,11 +1,13 @@ + Files: + tests/test-argp.c + tests/test-argp-2.sh ++tests/test-argp-2-utf.sh + + Depends-on: + progname + + Makefile.am: + TESTS += test-argp test-argp-2.sh +-check_PROGRAMS += test-argp ++TESTS += test-argp test-argp-2.sh test-argp-2-utf.sh ++check_PROGRAMS += test-argp test-argp-utf8 + test_argp_LDADD = $(LDADD) @LIBINTL@ diff --git a/grub-core/gnulib-no-abort.diff b/grub-core/gnulib-no-abort.diff new file mode 100644 index 000000000..8377338f7 --- /dev/null +++ b/grub-core/gnulib-no-abort.diff @@ -0,0 +1,30 @@ +=== modified file 'grub-core/gnulib/regcomp.c' +--- grub-core/gnulib/regcomp.c 2010-09-20 10:35:33 +0000 ++++ grub-core/gnulib/regcomp.c 2012-03-10 11:31:42 +0000 +@@ -549,13 +549,9 @@ regerror (int errcode, const regex_t *_R + if (BE (errcode < 0 + || errcode >= (int) (sizeof (__re_error_msgid_idx) + / sizeof (__re_error_msgid_idx[0])), 0)) +- /* Only error codes returned by the rest of the code should be passed +- to this routine. If we are given anything else, or if other regex +- code generates an invalid error code, then the program has a bug. +- Dump core so we can fix it. */ +- abort (); +- +- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); ++ msg = gettext ("unknown regexp error"); ++ else ++ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + +@@ -1119,7 +1119,7 @@ + } + break; + default: +- abort (); ++ break; + } + + if (mb_chars || has_period) + diff --git a/grub-core/gnulib-no-gets.diff b/grub-core/gnulib-no-gets.diff new file mode 100644 index 000000000..1a9487e84 --- /dev/null +++ b/grub-core/gnulib-no-gets.diff @@ -0,0 +1,10 @@ +--- /tmp/x.diff 2013-04-11 16:51:42.777873536 +0200 ++++ grub-core/gnulib/stdio.in.h 2013-04-11 16:51:49.917873298 +0200 +@@ -700,7 +700,6 @@ + removed it. */ + #undef gets + #if HAVE_RAW_DECL_GETS +-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); + #endif + + diff --git a/grub-core/gnulib/Makefile.am b/grub-core/gnulib/Makefile.am index fb1525f00..3444397fe 100644 --- a/grub-core/gnulib/Makefile.am +++ b/grub-core/gnulib/Makefile.am @@ -1,17 +1,29 @@ ## DO NOT EDIT! GENERATED AUTOMATICALLY! ## Process this file with automake to produce Makefile.in. -# Copyright (C) 2002-2010 Free Software Foundation, Inc. +# Copyright (C) 2002-2013 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 +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this file. If not, see . +# +# 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 +# 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-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname regex -AUTOMAKE_OPTIONS = 1.5 gnits +AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects SUBDIRS = noinst_HEADERS = @@ -39,12 +51,12 @@ EXTRA_libgnu_a_SOURCES = ## begin gnulib module alloca +libgnu_a_LIBADD += @ALLOCA@ +libgnu_a_DEPENDENCIES += @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 @@ -53,42 +65,23 @@ 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 +if GL_GENERATE_ALLOCA_H +alloca.h: alloca.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ cat $(srcdir)/alloca.in.h; \ } > $@-t && \ mv -f $@-t $@ +else +alloca.h: $(top_builddir)/config.status + rm -f $@ +endif 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 \ @@ -107,47 +100,10 @@ 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. +# Listed in the same order as the GNU makefile conventions, and +# provided by autoconf 2.59c+. # The Automake-defined pkg* macros are appended, in the order # listed in the Automake 1.10a+ documentation. configmake.h: Makefile @@ -181,11 +137,7 @@ configmake.h: Makefile 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 + mv -f $@-t $@ BUILT_SOURCES += configmake.h CLEANFILES += configmake.h configmake.h-t @@ -194,24 +146,33 @@ CLEANFILES += configmake.h configmake.h-t ## begin gnulib module dirname-lgpl +libgnu_a_SOURCES += dirname-lgpl.c basename-lgpl.c stripslash.c -EXTRA_DIST += basename-lgpl.c dirname-lgpl.c dirname.h stripslash.c - -EXTRA_libgnu_a_SOURCES += basename-lgpl.c dirname-lgpl.c stripslash.c +EXTRA_DIST += dirname.h ## end gnulib module dirname-lgpl +## begin gnulib module dosname + + +EXTRA_DIST += dosname.h + +## end gnulib module dosname + ## 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 +if GL_GENERATE_ERRNO_H +errno.h: errno.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \ -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \ -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \ @@ -222,6 +183,10 @@ errno.h: errno.in.h < $(srcdir)/errno.in.h; \ } > $@-t && \ mv $@-t $@ +else +errno.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += errno.h errno.h-t EXTRA_DIST += errno.in.h @@ -243,18 +208,28 @@ 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 +if GL_GENERATE_FLOAT_H +float.h: float.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ + -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ < $(srcdir)/float.in.h; \ } > $@-t && \ mv $@-t $@ +else +float.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += float.h float.h-t -EXTRA_DIST += float.in.h +EXTRA_DIST += float.c float.in.h itold.c + +EXTRA_libgnu_a_SOURCES += float.c itold.c ## end gnulib module float @@ -264,13 +239,18 @@ 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) +if GL_GENERATE_FNMATCH_H +fnmatch.h: fnmatch.in.h $(top_builddir)/config.status $(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 $@ +else +fnmatch.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t EXTRA_DIST += fnmatch.c fnmatch.in.h fnmatch_loop.c @@ -303,12 +283,14 @@ 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) +getopt.h: getopt.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ < $(srcdir)/getopt.in.h; \ @@ -364,14 +346,16 @@ 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) +langinfo.h: langinfo.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_LANGINFO_H''@|$(NEXT_LANGINFO_H)|g' \ - -e 's|@''GNULIB_NL_LANGINFO''@|$(GNULIB_NL_LANGINFO)|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' \ @@ -463,6 +447,50 @@ EXTRA_DIST += config.charset ref-add.sin ref-del.sin ## end gnulib module localcharset +## begin gnulib module locale + +BUILT_SOURCES += locale.h + +# We need the following in order to create when the system +# doesn't have one that provides all definitions. +locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ + -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ + -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ + -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ + -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ + -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ + -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ + -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ + -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|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)/locale.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += locale.h locale.h-t + +EXTRA_DIST += locale.in.h + +## end gnulib module locale + +## begin gnulib module localeconv + + +EXTRA_DIST += localeconv.c + +EXTRA_libgnu_a_SOURCES += localeconv.c + +## end gnulib module localeconv + ## begin gnulib module malloc-gnu @@ -502,12 +530,27 @@ EXTRA_libgnu_a_SOURCES += mbsinit.c ## begin gnulib module mbsrtowcs -EXTRA_DIST += mbsrtowcs-state.c mbsrtowcs.c +EXTRA_DIST += mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c EXTRA_libgnu_a_SOURCES += mbsrtowcs-state.c mbsrtowcs.c ## end gnulib module mbsrtowcs +## begin gnulib module mbswidth + +libgnu_a_SOURCES += mbswidth.h mbswidth.c + +## end gnulib module mbswidth + +## begin gnulib module mbtowc + + +EXTRA_DIST += mbtowc-impl.h mbtowc.c + +EXTRA_libgnu_a_SOURCES += mbtowc.c + +## end gnulib module mbtowc + ## begin gnulib module memchr @@ -526,6 +569,24 @@ EXTRA_libgnu_a_SOURCES += mempcpy.c ## end gnulib module mempcpy +## begin gnulib module msvc-inval + + +EXTRA_DIST += msvc-inval.c msvc-inval.h + +EXTRA_libgnu_a_SOURCES += msvc-inval.c + +## end gnulib module msvc-inval + +## begin gnulib module msvc-nothrow + + +EXTRA_DIST += msvc-nothrow.c msvc-nothrow.h + +EXTRA_libgnu_a_SOURCES += msvc-nothrow.c + +## end gnulib module msvc-nothrow + ## begin gnulib module nl_langinfo @@ -583,18 +644,127 @@ EXTRA_libgnu_a_SOURCES += sleep.c ## end gnulib module sleep +## begin gnulib module snippet/_Noreturn + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all Makefile.am that +# need it. This is ensured by the applicability 'all' defined above. + +_NORETURN_H=$(top_srcdir)/build-aux/snippet/_Noreturn.h + +EXTRA_DIST += $(top_srcdir)/build-aux/snippet/_Noreturn.h + +## end gnulib module snippet/_Noreturn + +## begin gnulib module snippet/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/snippet/arg-nonnull.h, except that it has the copyright header cut +# off. +arg-nonnull.h: $(top_srcdir)/build-aux/snippet/arg-nonnull.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/GL_ARG_NONNULL/,$$p' \ + < $(top_srcdir)/build-aux/snippet/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/snippet/arg-nonnull.h + +## end gnulib module snippet/arg-nonnull + +## begin gnulib module snippet/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/snippet/c++defs.h, except that it has the copyright header cut off. +c++defs.h: $(top_srcdir)/build-aux/snippet/c++defs.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/_GL_CXXDEFS/,$$p' \ + < $(top_srcdir)/build-aux/snippet/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/snippet/c++defs.h + +## end gnulib module snippet/c++defs + +## begin gnulib module snippet/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/snippet/warn-on-use.h, except that it has the copyright header cut +# off. +warn-on-use.h: $(top_srcdir)/build-aux/snippet/warn-on-use.h + $(AM_V_GEN)rm -f $@-t $@ && \ + sed -n -e '/^.ifndef/,$$p' \ + < $(top_srcdir)/build-aux/snippet/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/snippet/warn-on-use.h + +## end gnulib module snippet/warn-on-use + +## begin gnulib module stdalign + +BUILT_SOURCES += $(STDALIGN_H) + +# We need the following in order to create when the system +# doesn't have one that works. +if GL_GENERATE_STDALIGN_H +stdalign.h: stdalign.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/stdalign.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdalign.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdalign.h stdalign.h-t + +EXTRA_DIST += stdalign.in.h + +## end gnulib module stdalign + ## 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 +if GL_GENERATE_STDBOOL_H +stdbool.h: stdbool.in.h $(top_builddir)/config.status $(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 $@ +else +stdbool.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += stdbool.h stdbool.h-t EXTRA_DIST += stdbool.in.h @@ -607,17 +777,24 @@ 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 +if GL_GENERATE_STDDEF_H +stddef.h: stddef.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|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 $@ +else +stddef.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += stddef.h stddef.h-t EXTRA_DIST += stddef.in.h @@ -630,17 +807,21 @@ 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 +if GL_GENERATE_STDINT_H +stdint.h: stdint.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|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_WCHAR_H''@/$(HAVE_WCHAR_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' \ @@ -660,6 +841,10 @@ stdint.h: stdint.in.h < $(srcdir)/stdint.in.h; \ } > $@-t && \ mv $@-t $@ +else +stdint.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += stdint.h stdint.h-t EXTRA_DIST += stdint.in.h @@ -672,55 +857,71 @@ 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) +stdio.h: stdio.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|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' \ + -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \ + -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \ + -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \ + -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \ + -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \ + -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/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_FREAD''@/$(GNULIB_FREAD)/g' \ + -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \ + -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/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_GETC''@/$(GNULIB_GETC)/g' \ + -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/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_PCLOSE''@/$(GNULIB_PCLOSE)/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_SCANF''@/$(GNULIB_SCANF)/g' \ + -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \ + -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/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_VFSCANF''@/$(GNULIB_VFSCANF)/g' \ + -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/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_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \ + -e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|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' \ @@ -729,11 +930,14 @@ stdio.h: stdio.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ + -e 's|@''HAVE_PCLOSE''@|$(HAVE_PCLOSE)|g' \ + -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|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_FDOPEN''@|$(REPLACE_FDOPEN)|g' \ -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \ -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ @@ -754,6 +958,7 @@ stdio.h: stdio.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -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_READ_FUNCS''@|$(REPLACE_STDIO_READ_FUNCS)|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' \ @@ -770,9 +975,7 @@ stdio.h: stdio.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) mv $@-t $@ MOSTLYCLEANFILES += stdio.h stdio.h-t -EXTRA_DIST += stdio-write.c stdio.in.h - -EXTRA_libgnu_a_SOURCES += stdio-write.c +EXTRA_DIST += stdio.in.h ## end gnulib module stdio @@ -782,38 +985,49 @@ 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) +stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ + $(_NORETURN_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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|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/@''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_MBTOWC''@/$(GNULIB_MBTOWC)/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_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \ + -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ + -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ + -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/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_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/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_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \ + -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \ + -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \ + -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \ + < $(srcdir)/stdlib.in.h | \ + sed -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' \ @@ -824,33 +1038,42 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ + -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ + -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|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_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ + -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_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|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_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_MBTOWC''@|$(REPLACE_MBTOWC)|g' \ -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \ + -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \ -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ + -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|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 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _Noreturn/r $(_NORETURN_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; \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ } > $@-t && \ mv $@-t $@ MOSTLYCLEANFILES += stdlib.h stdlib.h-t @@ -893,54 +1116,70 @@ EXTRA_libgnu_a_SOURCES += strerror.c ## end gnulib module strerror +## begin gnulib module strerror-override + + +EXTRA_DIST += strerror-override.c strerror-override.h + +EXTRA_libgnu_a_SOURCES += strerror-override.c + +## end gnulib module strerror-override + ## 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) +string.h: string.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|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' \ + -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \ + -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/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_STRERROR_R''@/$(GNULIB_STRERROR_R)/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' \ + sed -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \ + -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \ + -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' \ @@ -956,15 +1195,18 @@ string.h: string.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -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_STRERROR_R''@|$(HAVE_DECL_STRERROR_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_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|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_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \ -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ @@ -989,14 +1231,20 @@ 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) +strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_STRINGS_H''@|$(HAVE_STRINGS_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \ + -e 's|@''GNULIB_FFS''@|$(GNULIB_FFS)|g' \ + -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \ -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|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)/strings.in.h; \ @@ -1032,28 +1280,30 @@ libgnu_a_SOURCES += strnlen1.h strnlen1.c ## end gnulib module strnlen1 -## begin gnulib module sys_wait +## begin gnulib module sys_types -BUILT_SOURCES += sys/wait.h +BUILT_SOURCES += sys/types.h -# We need the following in order to create when the system -# has one that is incomplete. -sys/wait.h: sys_wait.in.h +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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; \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + < $(srcdir)/sys_types.in.h; \ } > $@-t && \ mv $@-t $@ -MOSTLYCLEANFILES += sys/wait.h sys/wait.h-t -MOSTLYCLEANDIRS += sys +MOSTLYCLEANFILES += sys/types.h sys/types.h-t -EXTRA_DIST += sys_wait.in.h +EXTRA_DIST += sys_types.in.h -## end gnulib module sys_wait +## end gnulib module sys_types ## begin gnulib module sysexits @@ -1061,16 +1311,23 @@ 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 +if GL_GENERATE_SYSEXITS_H +sysexits.h: sysexits.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_SYSEXITS_H''@|$(NEXT_SYSEXITS_H)|g' \ < $(srcdir)/sysexits.in.h; \ } > $@-t && \ mv -f $@-t $@ +else +sysexits.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += sysexits.h sysexits.h-t EXTRA_DIST += sysexits.in.h @@ -1080,56 +1337,69 @@ EXTRA_DIST += sysexits.in.h ## begin gnulib module unistd BUILT_SOURCES += unistd.h +libgnu_a_SOURCES += unistd.c # 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) +unistd.h: unistd.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|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' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ + -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ + -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/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_FDATASYNC''@/$(GNULIB_FDATASYNC)/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_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \ + -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/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_PIPE''@/$(GNULIB_PIPE)/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_READ''@/$(GNULIB_READ)/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_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/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''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ + -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/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' \ @@ -1138,48 +1408,61 @@ unistd.h: unistd.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ + -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|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_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|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_PIPE''@|$(HAVE_PIPE)|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_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|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_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \ + -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \ + -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|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_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \ + -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|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' \ + | \ + sed -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_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \ -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ + -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \ + -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \ -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ + -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|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_READ''@|$(REPLACE_READ)|g' \ -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ @@ -1202,6 +1485,48 @@ EXTRA_DIST += unistd.in.h ## end gnulib module unistd +## begin gnulib module unitypes + +BUILT_SOURCES += $(LIBUNISTRING_UNITYPES_H) + +unitypes.h: unitypes.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unitypes.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += unitypes.h unitypes.h-t + +EXTRA_DIST += unitypes.in.h + +## end gnulib module unitypes + +## begin gnulib module uniwidth/base + +BUILT_SOURCES += $(LIBUNISTRING_UNIWIDTH_H) + +uniwidth.h: uniwidth.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniwidth.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += uniwidth.h uniwidth.h-t + +EXTRA_DIST += localcharset.h uniwidth.in.h + +## end gnulib module uniwidth/base + +## begin gnulib module uniwidth/width + +if LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH +libgnu_a_SOURCES += uniwidth/width.c +endif + +EXTRA_DIST += uniwidth/cjk.h + +## end gnulib module uniwidth/width + ## begin gnulib module vasnprintf @@ -1213,7 +1538,8 @@ EXTRA_libgnu_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c ## begin gnulib module verify -libgnu_a_SOURCES += verify.h + +EXTRA_DIST += verify.h ## end gnulib module verify @@ -1226,50 +1552,63 @@ 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) +wchar.h: wchar.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|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/@''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/@''GNULIB_WMEMCHR''@/$(GNULIB_WMEMCHR)/g' \ + -e 's/@''GNULIB_WMEMCMP''@/$(GNULIB_WMEMCMP)/g' \ + -e 's/@''GNULIB_WMEMCPY''@/$(GNULIB_WMEMCPY)/g' \ + -e 's/@''GNULIB_WMEMMOVE''@/$(GNULIB_WMEMMOVE)/g' \ + -e 's/@''GNULIB_WMEMSET''@/$(GNULIB_WMEMSET)/g' \ + -e 's/@''GNULIB_WCSLEN''@/$(GNULIB_WCSLEN)/g' \ + -e 's/@''GNULIB_WCSNLEN''@/$(GNULIB_WCSNLEN)/g' \ + -e 's/@''GNULIB_WCSCPY''@/$(GNULIB_WCSCPY)/g' \ + -e 's/@''GNULIB_WCPCPY''@/$(GNULIB_WCPCPY)/g' \ + -e 's/@''GNULIB_WCSNCPY''@/$(GNULIB_WCSNCPY)/g' \ + -e 's/@''GNULIB_WCPNCPY''@/$(GNULIB_WCPNCPY)/g' \ + -e 's/@''GNULIB_WCSCAT''@/$(GNULIB_WCSCAT)/g' \ + -e 's/@''GNULIB_WCSNCAT''@/$(GNULIB_WCSNCAT)/g' \ + -e 's/@''GNULIB_WCSCMP''@/$(GNULIB_WCSCMP)/g' \ + -e 's/@''GNULIB_WCSNCMP''@/$(GNULIB_WCSNCMP)/g' \ + -e 's/@''GNULIB_WCSCASECMP''@/$(GNULIB_WCSCASECMP)/g' \ + -e 's/@''GNULIB_WCSNCASECMP''@/$(GNULIB_WCSNCASECMP)/g' \ + -e 's/@''GNULIB_WCSCOLL''@/$(GNULIB_WCSCOLL)/g' \ + -e 's/@''GNULIB_WCSXFRM''@/$(GNULIB_WCSXFRM)/g' \ + -e 's/@''GNULIB_WCSDUP''@/$(GNULIB_WCSDUP)/g' \ + -e 's/@''GNULIB_WCSCHR''@/$(GNULIB_WCSCHR)/g' \ + -e 's/@''GNULIB_WCSRCHR''@/$(GNULIB_WCSRCHR)/g' \ + -e 's/@''GNULIB_WCSCSPN''@/$(GNULIB_WCSCSPN)/g' \ + -e 's/@''GNULIB_WCSSPN''@/$(GNULIB_WCSSPN)/g' \ + -e 's/@''GNULIB_WCSPBRK''@/$(GNULIB_WCSPBRK)/g' \ + -e 's/@''GNULIB_WCSSTR''@/$(GNULIB_WCSSTR)/g' \ + -e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \ + -e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \ + < $(srcdir)/wchar.in.h | \ + sed -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' \ @@ -1279,9 +1618,38 @@ wchar.h: wchar.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \ -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \ -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \ + -e 's|@''HAVE_WMEMCHR''@|$(HAVE_WMEMCHR)|g' \ + -e 's|@''HAVE_WMEMCMP''@|$(HAVE_WMEMCMP)|g' \ + -e 's|@''HAVE_WMEMCPY''@|$(HAVE_WMEMCPY)|g' \ + -e 's|@''HAVE_WMEMMOVE''@|$(HAVE_WMEMMOVE)|g' \ + -e 's|@''HAVE_WMEMSET''@|$(HAVE_WMEMSET)|g' \ + -e 's|@''HAVE_WCSLEN''@|$(HAVE_WCSLEN)|g' \ + -e 's|@''HAVE_WCSNLEN''@|$(HAVE_WCSNLEN)|g' \ + -e 's|@''HAVE_WCSCPY''@|$(HAVE_WCSCPY)|g' \ + -e 's|@''HAVE_WCPCPY''@|$(HAVE_WCPCPY)|g' \ + -e 's|@''HAVE_WCSNCPY''@|$(HAVE_WCSNCPY)|g' \ + -e 's|@''HAVE_WCPNCPY''@|$(HAVE_WCPNCPY)|g' \ + -e 's|@''HAVE_WCSCAT''@|$(HAVE_WCSCAT)|g' \ + -e 's|@''HAVE_WCSNCAT''@|$(HAVE_WCSNCAT)|g' \ + -e 's|@''HAVE_WCSCMP''@|$(HAVE_WCSCMP)|g' \ + -e 's|@''HAVE_WCSNCMP''@|$(HAVE_WCSNCMP)|g' \ + -e 's|@''HAVE_WCSCASECMP''@|$(HAVE_WCSCASECMP)|g' \ + -e 's|@''HAVE_WCSNCASECMP''@|$(HAVE_WCSNCASECMP)|g' \ + -e 's|@''HAVE_WCSCOLL''@|$(HAVE_WCSCOLL)|g' \ + -e 's|@''HAVE_WCSXFRM''@|$(HAVE_WCSXFRM)|g' \ + -e 's|@''HAVE_WCSDUP''@|$(HAVE_WCSDUP)|g' \ + -e 's|@''HAVE_WCSCHR''@|$(HAVE_WCSCHR)|g' \ + -e 's|@''HAVE_WCSRCHR''@|$(HAVE_WCSRCHR)|g' \ + -e 's|@''HAVE_WCSCSPN''@|$(HAVE_WCSCSPN)|g' \ + -e 's|@''HAVE_WCSSPN''@|$(HAVE_WCSSPN)|g' \ + -e 's|@''HAVE_WCSPBRK''@|$(HAVE_WCSPBRK)|g' \ + -e 's|@''HAVE_WCSSTR''@|$(HAVE_WCSSTR)|g' \ + -e 's|@''HAVE_WCSTOK''@|$(HAVE_WCSTOK)|g' \ + -e 's|@''HAVE_WCSWIDTH''@|$(HAVE_WCSWIDTH)|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' \ + | \ + sed -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' \ @@ -1293,10 +1661,10 @@ wchar.h: wchar.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \ -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \ -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \ + -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|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; \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ } > $@-t && \ mv $@-t $@ MOSTLYCLEANFILES += wchar.h wchar.h-t @@ -1314,24 +1682,35 @@ EXTRA_libgnu_a_SOURCES += wcrtomb.c ## end gnulib module wcrtomb -## begin gnulib module wctype +## begin gnulib module wctype-h BUILT_SOURCES += wctype.h +libgnu_a_SOURCES += wctype-h.c # 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) +wctype.h: wctype.in.h $(top_builddir)/config.status $(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' \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -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|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \ + -e 's/@''GNULIB_ISWBLANK''@/$(GNULIB_ISWBLANK)/g' \ + -e 's/@''GNULIB_WCTYPE''@/$(GNULIB_WCTYPE)/g' \ + -e 's/@''GNULIB_ISWCTYPE''@/$(GNULIB_ISWCTYPE)/g' \ + -e 's/@''GNULIB_WCTRANS''@/$(GNULIB_WCTRANS)/g' \ + -e 's/@''GNULIB_TOWCTRANS''@/$(GNULIB_TOWCTRANS)/g' \ -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \ -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \ + -e 's/@''HAVE_WCTYPE_T''@/$(HAVE_WCTYPE_T)/g' \ + -e 's/@''HAVE_WCTRANS_T''@/$(HAVE_WCTRANS_T)/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 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/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; \ @@ -1341,11 +1720,20 @@ MOSTLYCLEANFILES += wctype.h wctype.h-t EXTRA_DIST += wctype.in.h -## end gnulib module wctype +## end gnulib module wctype-h + +## begin gnulib module wcwidth + + +EXTRA_DIST += wcwidth.c + +EXTRA_libgnu_a_SOURCES += wcwidth.c + +## end gnulib module wcwidth ## begin gnulib module xsize -libgnu_a_SOURCES += xsize.h +libgnu_a_SOURCES += xsize.h xsize.c ## end gnulib module xsize diff --git a/grub-core/gnulib/alloca.c b/grub-core/gnulib/alloca.c index 75afdb960..ee0f01886 100644 --- a/grub-core/gnulib/alloca.c +++ b/grub-core/gnulib/alloca.c @@ -93,26 +93,15 @@ long i00afunc (); static int stack_dir; /* 1 or -1 once known. */ # define STACK_DIR stack_dir -static void -find_stack_direction (void) +static int +find_stack_direction (int *addr, int depth) { - 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. */ - } + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; } # endif /* STACK_DIRECTION == 0 */ @@ -155,7 +144,7 @@ alloca (size_t size) # if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); + STACK_DIR = find_stack_direction (NULL, (size & 1) + 20); # endif /* Reclaim garbage, defined as all alloca'd storage that @@ -486,4 +475,4 @@ i00afunc (long address) # endif /* CRAY */ # endif /* no alloca */ -#endif /* not GCC version 3 */ +#endif /* not GCC 2 */ diff --git a/grub-core/gnulib/alloca.in.h b/grub-core/gnulib/alloca.in.h index 44f20b7a1..72d28ee30 100644 --- a/grub-core/gnulib/alloca.in.h +++ b/grub-core/gnulib/alloca.in.h @@ -1,6 +1,6 @@ /* Memory allocation on the stack. - Copyright (C) 1995, 1999, 2001-2004, 2006-2010 Free Software Foundation, + Copyright (C) 1995, 1999, 2001-2004, 2006-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it @@ -14,9 +14,9 @@ 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. */ + License along with this program; if not, see + . + */ /* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H means there is a real alloca function. */ @@ -44,6 +44,13 @@ # define alloca _alloca # elif defined __DECC && defined __VMS # define alloca __ALLOCA +# elif defined __TANDEM && defined _TNS_E_TARGET +# ifdef __cplusplus +extern "C" +# endif +void *_alloca (unsigned short); +# pragma intrinsic (_alloca) +# define alloca _alloca # else # include # ifdef __cplusplus diff --git a/grub-core/gnulib/argp-ba.c b/grub-core/gnulib/argp-ba.c index 95feabb86..5abc9d00a 100644 --- a/grub-core/gnulib/argp-ba.c +++ b/grub-core/gnulib/argp-ba.c @@ -1,5 +1,5 @@ /* Default definition for ARGP_PROGRAM_BUG_ADDRESS. - Copyright (C) 1996, 1997, 1999, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1996-1997, 1999, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -19,11 +19,11 @@ /* If set by the user program, it should point to string that is the bug-reporting address for the program. It will be printed by argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help - messages), embedded in a sentence that says something like `Report bugs to - ADDR.'. */ + messages), embedded in a sentence that says something like "Report bugs to + ADDR." */ const char *argp_program_bug_address /* This variable should be zero-initialized. On most systems, putting it into - BSS is sufficient. Not so on MacOS X 10.3 and 10.4, see + BSS is sufficient. Not so on Mac OS X 10.3 and 10.4, see . */ #if defined __ELF__ diff --git a/grub-core/gnulib/argp-eexst.c b/grub-core/gnulib/argp-eexst.c index 115a8cd5d..a8bb77fcf 100644 --- a/grub-core/gnulib/argp-eexst.c +++ b/grub-core/gnulib/argp-eexst.c @@ -1,5 +1,5 @@ /* Default definition for ARGP_ERR_EXIT_STATUS - Copyright (C) 1997, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1997, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . diff --git a/grub-core/gnulib/argp-fmtstream.c b/grub-core/gnulib/argp-fmtstream.c index 248a09a3b..02406ff2a 100644 --- a/grub-core/gnulib/argp-fmtstream.c +++ b/grub-core/gnulib/argp-fmtstream.c @@ -1,5 +1,5 @@ /* Word-wrapping and line-truncating streams - Copyright (C) 1997-1999, 2001-2003, 2005, 2009-2010 Free Software + Copyright (C) 1997-1999, 2001-2003, 2005, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* This package emulates glibc `line_wrap_stream' semantics for systems that +/* This package emulates glibc 'line_wrap_stream' semantics for systems that don't have that. */ #ifdef HAVE_CONFIG_H @@ -33,6 +33,7 @@ #include "argp-fmtstream.h" #include "argp-namefrob.h" +#include "mbswidth.h" #ifndef ARGP_FMTSTREAM_USE_LINEWRAP @@ -118,37 +119,16 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free) #endif -size_t -__argp_get_display_len (const char *beg, const char *end) +/* Return the pointer to the first character that doesn't fit in l columns. */ +static inline const ptrdiff_t +add_width (const char *ptr, const char *end, size_t l) { - const char *ptr; - size_t r = 0; mbstate_t ps; + const char *ptr0 = ptr; memset (&ps, 0, sizeof (ps)); - for (ptr = beg; ptr < end && *ptr; ) - { - wchar_t wc; - size_t s; - - s = mbrtowc (&wc, ptr, end - ptr, &ps); - if (s == (size_t) -1) - break; - r += wcwidth (wc); - ptr += s; - } - return r; -} - -static inline char * -add_length (char *ptr, char *end, size_t l) -{ - mbstate_t ps; - - memset (&ps, 0, sizeof (ps)); - - while (ptr < end && *ptr) + while (ptr < end) { wchar_t wc; size_t s, k; @@ -156,13 +136,31 @@ add_length (char *ptr, char *end, size_t l) s = mbrtowc (&wc, ptr, end - ptr, &ps); if (s == (size_t) -1) break; + if (s == (size_t) -2) + { + if (1 >= l) + break; + l--; + ptr++; + continue; + } + + if (wc == '\e' && ptr + 3 < end + && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1') + && ptr[3] == 'm') + { + ptr += 4; + continue; + } + k = wcwidth (wc); + if (k >= l) break; l -= k; ptr += s; } - return ptr; + return ptr - ptr0; } /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the @@ -217,15 +215,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs) if (!nl) { - size_t display_len = __argp_get_display_len (buf, fs->p); + size_t display_width = mbsnwidth (buf, fs->p - buf, MBSW_STOP_AT_NUL); /* The buffer ends in a partial line. */ - if (fs->point_col + display_len < fs->rmargin) + if (fs->point_col + display_width < fs->rmargin) { /* The remaining buffer text is a partial line and fits within the maximum line width. Advance point for the characters to be written and stop scanning. */ - fs->point_col += display_len; + fs->point_col += display_width; break; } else @@ -235,8 +233,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs) } else { - size_t display_len = __argp_get_display_len (buf, nl); - if (display_len < (ssize_t) fs->rmargin) + size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL); + if (display_width < (ssize_t) fs->rmargin) { /* The buffer contains a full line that fits within the maximum line width. Reset point and scan the next line. */ @@ -280,7 +278,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) char *p, *nextline; int i; - p = add_length (buf, fs->p, (r + 1 - fs->point_col)); + p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); while (p >= buf && !isblank ((unsigned char) *p)) --p; nextline = p + 1; /* This will begin the next line. */ @@ -298,7 +296,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) { /* A single word that is greater than the maximum line width. Oh well. Put it on an overlong line by itself. */ - p = add_length (buf, fs->p, (r + 1 - fs->point_col)); + p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); /* Find the end of the long word. */ if (p < nl) do @@ -332,7 +330,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs) && fs->p > nextline) { /* The margin needs more blanks than we removed. */ - if (__argp_get_display_len (fs->p, fs->end) > fs->wmargin + 1) + if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL) + > fs->wmargin + 1) /* Make some space for them. */ { size_t mv = fs->p - nextline; diff --git a/grub-core/gnulib/argp-fmtstream.h b/grub-core/gnulib/argp-fmtstream.h index 8a67817b1..000090ea6 100644 --- a/grub-core/gnulib/argp-fmtstream.h +++ b/grub-core/gnulib/argp-fmtstream.h @@ -1,5 +1,5 @@ /* Word-wrapping and line-truncating streams. - Copyright (C) 1997, 2006-2010 Free Software Foundation, Inc. + Copyright (C) 1997, 2006-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* This package emulates glibc `line_wrap_stream' semantics for systems that +/* This package emulates glibc 'line_wrap_stream' semantics for systems that don't have that. If the system does have it, it is just a wrapper for that. This header file is only used internally while compiling argp, and shouldn't be installed. */ @@ -28,16 +28,16 @@ #include #include -#ifndef __attribute__ /* The __attribute__ feature is available in gcc versions 2.5 and later. The __-protected variants of the attributes 'format' and 'printf' are accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because + We enable _GL_ATTRIBUTE_FORMAT 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 +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ #endif #if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ @@ -128,12 +128,12 @@ extern void argp_fmtstream_free (argp_fmtstream_t __fs); extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, const char *__fmt, ...) - __attribute__ ((__format__ (printf, 2, 3))); + _GL_ATTRIBUTE_FORMAT ((printf, 2, 3)); extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, const char *__fmt, ...) - __attribute__ ((__format__ (printf, 2, 3))); + _GL_ATTRIBUTE_FORMAT ((printf, 2, 3)); -#if _LIBC || !defined __OPTIMIZE__ +#if _LIBC extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); @@ -154,7 +154,7 @@ extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, #define __argp_fmtstream_rmargin argp_fmtstream_rmargin #define __argp_fmtstream_wmargin argp_fmtstream_wmargin -#if _LIBC || !defined __OPTIMIZE__ +#if _LIBC /* Set __FS's left margin to LMARGIN and return the old value. */ extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin); @@ -184,7 +184,7 @@ extern void __argp_fmtstream_update (argp_fmtstream_t __fs); extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); -#ifdef __OPTIMIZE__ +#if !_LIBC || defined __OPTIMIZE__ /* Inline versions of above routines. */ #if !_LIBC @@ -197,6 +197,10 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); #define __argp_fmtstream_point argp_fmtstream_point #define __argp_fmtstream_update _argp_fmtstream_update #define __argp_fmtstream_ensure _argp_fmtstream_ensure +_GL_INLINE_HEADER_BEGIN +#ifndef ARGP_FS_EI +# define ARGP_FS_EI _GL_INLINE +#endif #endif #ifndef ARGP_FS_EI @@ -335,9 +339,6 @@ __argp_fmtstream_point (argp_fmtstream_t __fs) return __fs->point_col >= 0 ? __fs->point_col : 0; } -size_t -__argp_get_display_len (const char *beg, const char *end); - #if !_LIBC #undef __argp_fmtstream_putc #undef __argp_fmtstream_puts @@ -348,9 +349,10 @@ __argp_get_display_len (const char *beg, const char *end); #undef __argp_fmtstream_point #undef __argp_fmtstream_update #undef __argp_fmtstream_ensure +_GL_INLINE_HEADER_END #endif -#endif /* __OPTIMIZE__ */ +#endif /* !_LIBC || __OPTIMIZE__ */ #endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ diff --git a/grub-core/gnulib/argp-fs-xinl.c b/grub-core/gnulib/argp-fs-xinl.c index 2c683f914..35547d93d 100644 --- a/grub-core/gnulib/argp-fs-xinl.c +++ b/grub-core/gnulib/argp-fs-xinl.c @@ -1,5 +1,5 @@ /* Real definitions for extern inline functions in argp-fmtstream.h - Copyright (C) 1997, 2003, 2004, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1997, 2003-2004, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -20,7 +20,11 @@ # include #endif -#define ARGP_FS_EI +#ifdef _LIBC +# define ARGP_FS_EI +#else +# define ARGP_FS_EI _GL_EXTERN_INLINE +#endif #undef __OPTIMIZE__ #define __OPTIMIZE__ 1 #include "argp-fmtstream.h" diff --git a/grub-core/gnulib/argp-help.c b/grub-core/gnulib/argp-help.c index c82e38e75..2914f4723 100644 --- a/grub-core/gnulib/argp-help.c +++ b/grub-core/gnulib/argp-help.c @@ -1,5 +1,5 @@ -/* Hierarchial argument parsing help output - Copyright (C) 1995-2005, 2007, 2009-2010 Free Software Foundation, Inc. +/* Hierarchical argument parsing help output + Copyright (C) 1995-2005, 2007, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ #include "argp.h" #include "argp-fmtstream.h" #include "argp-namefrob.h" +#include "mbswidth.h" #ifndef SIZE_MAX # define SIZE_MAX ((size_t) -1) @@ -56,7 +58,7 @@ /* User-selectable (using an environment variable) formatting parameters. - These may be specified in an environment variable called `ARGP_HELP_FMT', + These may be specified in an environment variable called 'ARGP_HELP_FMT', with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 Where VALn must be a positive integer. The list of variables is in the UPARAM_NAMES vector, below. */ @@ -73,13 +75,13 @@ #define RMARGIN 79 /* right margin used for wrapping */ /* User-selectable (using an environment variable) formatting parameters. - They must all be of type `int' for the parsing code to work. */ + They must all be of type 'int' for the parsing code to work. */ struct uparams { /* If true, arguments for an option are shown with both short and long - options, even when a given option has both, e.g. `-x ARG, --longx=ARG'. + options, even when a given option has both, e.g. '-x ARG, --longx=ARG'. If false, then if an option has both, the argument is only shown with - the long one, e.g., `-x, --longx=ARG', and a message indicating that + the long one, e.g., '-x, --longx=ARG', and a message indicating that this really means both is printed below the options. */ int dup_args; @@ -111,7 +113,7 @@ static struct uparams uparams = { struct uparam_name { const char *name; /* User name. */ - int is_bool; /* Whether it's `boolean'. */ + int is_bool; /* Whether it's 'boolean'. */ size_t uparams_offs; /* Location of the (int) field in UPARAMS. */ }; @@ -154,7 +156,7 @@ ARGP_HELP_FMT: %s value is less than or equal to %s"), uparams.valid = 1; } -/* Read user options from the environment, and fill in UPARAMS appropiately. */ +/* Read user options from the environment, and fill in UPARAMS appropriately. */ static void fill_in_uparams (const struct argp_state *state) { @@ -259,7 +261,7 @@ fill_in_uparams (const struct argp_state *state) /* Returns true if OPT is an alias for an earlier option. */ #define oalias(opt) ((opt)->flags & OPTION_ALIAS) -/* Returns true if OPT is an documentation-only entry. */ +/* Returns true if OPT is a documentation-only entry. */ #define odoc(opt) ((opt)->flags & OPTION_DOC) /* Returns true if OPT should not be translated */ @@ -277,11 +279,11 @@ fill_in_uparams (const struct argp_state *state) -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... Where ARG will be omitted if there's no argument, for this option, or - will be surrounded by "[" and "]" appropiately if the argument is - optional. The documentation string is word-wrapped appropiately, and if + will be surrounded by "[" and "]" appropriately if the argument is + optional. The documentation string is word-wrapped appropriately, and if the list of options is long enough, it will be started on a separate line. If there are no short options for a given option, the first long option is - indented slighly in a way that's supposed to make most long options appear + indented slightly in a way that's supposed to make most long options appear to be in a separate column. For example, the following output (from ps): @@ -359,7 +361,7 @@ struct hol_entry /* A pointers into the HOL's short_options field, to the first short option letter for this entry. The order of the characters following this point corresponds to the order of options pointed to by OPT, and there are at - most NUM. A short option recorded in a option following OPT is only + most NUM. A short option recorded in an option following OPT is only valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's probably been shadowed by some other entry). */ char *short_options; @@ -570,7 +572,9 @@ hol_entry_short_iterate (const struct hol_entry *entry, } static inline int +#if __GNUC__ >= 3 __attribute__ ((always_inline)) +#endif hol_entry_long_iterate (const struct hol_entry *entry, int (*func)(const struct argp_option *opt, const struct argp_option *real, @@ -711,7 +715,7 @@ hol_cluster_is_child (const struct hol_cluster *cl1, return cl1 == cl2; } -/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail +/* Given the name of an OPTION_DOC option, modifies NAME to start at the tail that should be used for comparisons, and returns true iff it should be treated as a non-option. */ static int @@ -726,7 +730,7 @@ canon_doc_option (const char **name) /* Skip initial whitespace. */ while (isspace ((unsigned char) **name)) (*name)++; - /* Decide whether this looks like an option (leading `-') or not. */ + /* Decide whether this looks like an option (leading '-') or not. */ non_opt = (**name != '-'); /* Skip until part of name used for sorting. */ while (**name && !isalnum ((unsigned char) **name)) @@ -751,9 +755,9 @@ hol_entry_cmp (const struct hol_entry *entry1, if (entry1->cluster != entry2->cluster) { /* The entries are not within the same cluster, so we can't compare them - directly, we have to use the appropiate clustering level too. */ + directly, we have to use the appropriate clustering level too. */ if (! entry1->cluster) - /* ENTRY1 is at the `base level', not in a cluster, so we have to + /* ENTRY1 is at the "base level", not in a cluster, so we have to compare it's group number with that of the base cluster in which ENTRY2 resides. Note that if they're in the same group, the clustered option always comes laster. */ @@ -783,7 +787,7 @@ hol_entry_cmp (const struct hol_entry *entry1, doc2 = canon_doc_option (&long2); if (doc1 != doc2) - /* `documentation' options always follow normal options (or + /* "documentation" options always follow normal options (or documentation options that *look* like normal options). */ return doc1 - doc2; else if (!short1 && !short2 && long1 && long2) @@ -889,7 +893,8 @@ hol_append (struct hol *hol, struct hol *more) /* Fix up the short options pointers from HOL. */ for (e = entries, left = hol->num_entries; left > 0; e++, left--) - e->short_options += (short_options - hol->short_options); + e->short_options = + short_options + (e->short_options - hol->short_options); /* Now add the short options from MORE, fixing up its entries too. */ @@ -1020,7 +1025,7 @@ filter_doc (const char *doc, int key, const struct argp *argp, return doc; } -/* Prints STR as a header line, with the margin lines set appropiately, and +/* Prints STR as a header line, with the margin lines set appropriately, and notes the fact that groups should be separated with a blank line. ARGP is the argp that should dictate any user doc filtering to take place. Note that the previous wrap margin isn't restored, but the left margin is reset @@ -1142,7 +1147,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, /* Now, long options. */ if (odoc (real)) - /* A `documentation' option. */ + /* A "documentation" option. */ { __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); for (opt = real, num = entry->num; num > 0; opt++, num--) @@ -1436,7 +1441,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, const char *cp = fdoc; nl = __strchrnul (cp, '\n'); if (*nl != '\0') - /* This is a `multi-level' args doc; advance to the correct position + /* This is a "multi-level" args doc; advance to the correct position as determined by our state in LEVELS, and update LEVELS. */ { int i; @@ -1448,7 +1453,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, /* Manually do line wrapping so that it (probably) won't get wrapped at any embedded spaces. */ - space (stream, 1 + __argp_get_display_len (cp, nl)); + space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL)); __argp_fmtstream_write (stream, cp, nl - cp); } @@ -1477,9 +1482,9 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, } /* Print the documentation for ARGP to STREAM; if POST is false, then - everything preceeding a `\v' character in the documentation strings (or + everything preceding a '\v' character in the documentation strings (or the whole string, for those with none) is printed, otherwise, everything - following the `\v' character (nothing for strings without). Each separate + following the '\v' character (nothing for strings without). Each separate bit of documentation is separated a blank line, and if PRE_BLANK is true, then the first is as well. If FIRST_ONLY is true, only the first occurrence is output. Returns true if anything was output. */ @@ -1549,7 +1554,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state, free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ if (post && argp->help_filter) - /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ + /* Now see if we have to output an ARGP_KEY_HELP_EXTRA text. */ { text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); if (text) @@ -1576,8 +1581,8 @@ argp_doc (const struct argp *argp, const struct argp_state *state, } /* Output a usage message for ARGP to STREAM. If called from - argp_state_help, STATE is the relevent parsing state. FLAGS are from the - set ARGP_HELP_*. NAME is what to use wherever a `program name' is + argp_state_help, STATE is the relevant parsing state. FLAGS are from the + set ARGP_HELP_*. NAME is what to use wherever a "program name" is needed. */ static void _help (const struct argp *argp, const struct argp_state *state, FILE *stream, @@ -1618,7 +1623,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, } if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) - /* Print a short `Usage:' message. */ + /* Print a short "Usage:" message. */ { int first_pattern = 1, more_patterns; size_t num_pattern_levels = argp_args_levels (argp); @@ -1678,7 +1683,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, if (flags & ARGP_HELP_SEE) { __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ -Try `%s --help' or `%s --usage' for more information.\n"), +Try '%s --help' or '%s --usage' for more information.\n"), name, name); anything = 1; } @@ -1721,7 +1726,7 @@ Try `%s --help' or `%s --usage' for more information.\n"), } /* Output a usage message for ARGP to STREAM. FLAGS are from the set - ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */ + ARGP_HELP_*. NAME is what to use wherever a "program name" is needed. */ void __argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name) { @@ -1779,7 +1784,7 @@ weak_alias (__argp_state_help, argp_state_help) #endif /* If appropriate, print the printf string FMT and following args, preceded - by the program name and `:', to stderr, and followed by a `Try ... --help' + by the program name and ':', to stderr, and followed by a "Try ... --help" message, then exit (1). */ void __argp_error (const struct argp_state *state, const char *fmt, ...) @@ -1915,7 +1920,7 @@ __argp_failure (const struct argp_state *state, int status, int errnum, char const *s = NULL; putc_unlocked (':', stream); putc_unlocked (' ', stream); -#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P) +#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P && !defined strerror_r) s = __strerror_r (errnum, buf, sizeof buf); #elif HAVE_DECL_STRERROR_R if (__strerror_r (errnum, buf, sizeof buf) == 0) diff --git a/grub-core/gnulib/argp-namefrob.h b/grub-core/gnulib/argp-namefrob.h index 24581a626..6333958c6 100644 --- a/grub-core/gnulib/argp-namefrob.h +++ b/grub-core/gnulib/argp-namefrob.h @@ -1,5 +1,5 @@ /* Name frobnication for compiling argp outside of glibc - Copyright (C) 1997, 2003, 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1997, 2003, 2007, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -100,45 +100,45 @@ #endif #if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED # define feof_unlocked(x) feof (x) -# endif +#endif #if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED # define ferror_unlocked(x) ferror (x) -# endif +#endif #if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED # define fflush_unlocked(x) fflush (x) -# endif +#endif #if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED # define fgets_unlocked(x,y,z) fgets (x,y,z) -# endif +#endif #if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED # define fputc_unlocked(x,y) fputc (x,y) -# endif +#endif #if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED # define fputs_unlocked(x,y) fputs (x,y) -# endif +#endif #if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED # define fread_unlocked(w,x,y,z) fread (w,x,y,z) -# endif +#endif #if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED # define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) -# endif +#endif #if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED # define getc_unlocked(x) getc (x) -# endif +#endif #if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED # define getchar_unlocked() getchar () -# endif +#endif #if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED # define putc_unlocked(x,y) putc (x,y) -# endif +#endif #if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED # define putchar_unlocked(x) putchar (x) -# endif +#endif #endif /* !_LIBC */ #ifndef __set_errno -#define __set_errno(e) (errno = (e)) +# define __set_errno(e) (errno = (e)) #endif #if defined GNULIB_ARGP_DISABLE_DIRNAME diff --git a/grub-core/gnulib/argp-parse.c b/grub-core/gnulib/argp-parse.c index 9c054653c..67ea32c54 100644 --- a/grub-core/gnulib/argp-parse.c +++ b/grub-core/gnulib/argp-parse.c @@ -1,5 +1,5 @@ -/* Hierarchial argument parsing, layered over getopt - Copyright (C) 1995-2000, 2002-2004, 2009-2010 Free Software Foundation, Inc. +/* Hierarchical argument parsing, layered over getopt + Copyright (C) 1995-2000, 2002-2004, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -21,6 +21,7 @@ #endif #include +#include #include #include #include @@ -42,7 +43,6 @@ #include "argp.h" #include "argp-namefrob.h" -#define alignof(type) offsetof (struct { char c; type x; }, x) #define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) /* Getopt return values. */ @@ -154,8 +154,9 @@ argp_version_parser (int key, char *arg, struct argp_state *state) else if (argp_program_version) fprintf (state->out_stream, "%s\n", argp_program_version); else - __argp_error (state, dgettext (state->root_argp->argp_domain, - "(PROGRAM ERROR) No version known!?")); + __argp_error (state, "%s", + dgettext (state->root_argp->argp_domain, + "(PROGRAM ERROR) No version known!?")); if (! (state->flags & ARGP_NO_EXIT)) exit (0); break; @@ -187,7 +188,7 @@ find_long_option (struct option *long_options, const char *name) } -/* The state of a `group' during parsing. Each group corresponds to a +/* The state of a "group" during parsing. Each group corresponds to a particular argp structure from the tree of such descending from the top level argp passed to argp_parse. */ struct group @@ -203,7 +204,7 @@ struct group particular short options is from. */ char *short_end; - /* The number of non-option args sucessfully handled by this parser. */ + /* The number of non-option args successfully handled by this parser. */ unsigned args_processed; /* This group's parser's parent's group. */ @@ -254,7 +255,7 @@ struct parser struct group *groups; /* The end of the GROUPS array. */ struct group *egroup; - /* An vector containing storage for the CHILD_INPUTS field in all groups. */ + /* A vector containing storage for the CHILD_INPUTS field in all groups. */ void **child_inputs; /* True if we think using getopt is still useful; if false, then @@ -385,7 +386,7 @@ convert_options (const struct argp *argp, return group; } -/* Find the merged set of getopt options, with keys appropiately prefixed. */ +/* Find the merged set of getopt options, with keys appropriately prefixed. */ static void parser_convert (struct parser *parser, const struct argp *argp, int flags) { @@ -439,7 +440,7 @@ calc_sizes (const struct argp *argp, struct parser_sizes *szs) int num_opts = 0; while (!__option_is_end (opt++)) num_opts++; - szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ + szs->short_len += num_opts * 3; /* opt + up to 2 ':'s */ szs->long_len += num_opts; } } @@ -781,7 +782,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) if (parser->state.quoted && parser->state.next < parser->state.quoted) /* The next argument pointer has been moved to before the quoted - region, so pretend we never saw the quoting `--', and give getopt + region, so pretend we never saw the quoting "--", and give getopt another chance. If the user hasn't removed it, getopt will just process it again. */ parser->state.quoted = 0; @@ -813,7 +814,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) == 0) /* Not only is this the end of the options, but it's a - `quoted' region, which may have args that *look* like + "quoted" region, which may have args that *look* like options, so we definitely shouldn't try to use getopt past here, whatever happens. */ parser->state.quoted = parser->state.next; @@ -879,11 +880,11 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, #ifndef _LIBC if (!(flags & ARGP_PARSE_ARGV0)) { -#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME +#if HAVE_DECL_PROGRAM_INVOCATION_NAME if (!program_invocation_name) program_invocation_name = argv[0]; #endif -#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME if (!program_invocation_short_name) program_invocation_short_name = __argp_base_name (argv[0]); #endif diff --git a/grub-core/gnulib/argp-pin.c b/grub-core/gnulib/argp-pin.c index eda4d958e..78cbb355b 100644 --- a/grub-core/gnulib/argp-pin.c +++ b/grub-core/gnulib/argp-pin.c @@ -1,5 +1,5 @@ /* Full and short program names for argp module - Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,4 +24,3 @@ char *program_invocation_short_name = 0; #ifndef HAVE_PROGRAM_INVOCATION_NAME char *program_invocation_name = 0; #endif - diff --git a/grub-core/gnulib/argp-pv.c b/grub-core/gnulib/argp-pv.c index e3227d322..c74070d12 100644 --- a/grub-core/gnulib/argp-pv.c +++ b/grub-core/gnulib/argp-pv.c @@ -1,5 +1,5 @@ /* Default definition for ARGP_PROGRAM_VERSION. - Copyright (C) 1996, 1997, 1999, 2006, 2009, 2010 Free Software Foundation, + Copyright (C) 1996-1997, 1999, 2006, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -23,7 +23,7 @@ ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ const char *argp_program_version /* This variable should be zero-initialized. On most systems, putting it into - BSS is sufficient. Not so on MacOS X 10.3 and 10.4, see + BSS is sufficient. Not so on Mac OS X 10.3 and 10.4, see . */ #if defined __ELF__ diff --git a/grub-core/gnulib/argp-pvh.c b/grub-core/gnulib/argp-pvh.c index fb98fc21c..885ff4b75 100644 --- a/grub-core/gnulib/argp-pvh.c +++ b/grub-core/gnulib/argp-pvh.c @@ -1,5 +1,5 @@ /* Default definition for ARGP_PROGRAM_VERSION_HOOK. - Copyright (C) 1996, 1997, 1999, 2004, 2009, 2010 Free Software Foundation, + Copyright (C) 1996-1997, 1999, 2004, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . diff --git a/grub-core/gnulib/argp-xinl.c b/grub-core/gnulib/argp-xinl.c index 6e7e20bba..04d8cf703 100644 --- a/grub-core/gnulib/argp-xinl.c +++ b/grub-core/gnulib/argp-xinl.c @@ -1,5 +1,5 @@ /* Real definitions for extern inline functions in argp.h - Copyright (C) 1997, 1998, 2004, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1997-1998, 2004, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -27,7 +27,11 @@ #ifndef __USE_EXTERN_INLINES # define __USE_EXTERN_INLINES 1 #endif -#define ARGP_EI +#ifdef _LIBC +# define ARGP_EI +#else +# define ARGP_EI _GL_EXTERN_INLINE +#endif #undef __OPTIMIZE__ #define __OPTIMIZE__ 1 #include "argp.h" diff --git a/grub-core/gnulib/argp.h b/grub-core/gnulib/argp.h index 3667224a9..c4094a40c 100644 --- a/grub-core/gnulib/argp.h +++ b/grub-core/gnulib/argp.h @@ -1,5 +1,5 @@ -/* Hierarchial argument parsing, layered over getopt. - Copyright (C) 1995-1999, 2003-2010 Free Software Foundation, Inc. +/* Hierarchical argument parsing, layered over getopt. + Copyright (C) 1995-1999, 2003-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -34,16 +34,16 @@ # define __NTH(fct) fct __THROW #endif -#ifndef __attribute__ /* The __attribute__ feature is available in gcc versions 2.5 and later. The __-protected variants of the attributes 'format' and 'printf' are accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because + We enable _GL_ATTRIBUTE_FORMAT 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 +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ #endif /* GCC 2.95 and later have "__restrict"; C99 compilers have @@ -94,7 +94,7 @@ struct argp_option /* The doc string for this option. If both NAME and KEY are 0, This string will be printed outdented from the normal option column, making it useful as a group header (it will be the first thing printed in its - group); in this usage, it's conventional to end the string with a `:'. + group); in this usage, it's conventional to end the string with a ':'. Write the initial value as N_("TEXT") if you want xgettext to collect it into a POT file. */ @@ -124,21 +124,21 @@ struct argp_option /* This option isn't actually an option (and so should be ignored by the actual option parser), but rather an arbitrary piece of documentation that should be displayed in much the same manner as the options. If this flag - is set, then the option NAME field is displayed unmodified (e.g., no `--' + is set, then the option NAME field is displayed unmodified (e.g., no '--' prefix is added) at the left-margin (where a *short* option would normally be displayed), and the documentation string in the normal place. The NAME field will be translated using gettext, unless OPTION_NO_TRANS is set (see below). For purposes of sorting, any leading whitespace and punctuation is - ignored, except that if the first non-whitespace character is not `-', this + ignored, except that if the first non-whitespace character is not '-', this entry is displayed after all options (and OPTION_DOC entries with a leading - `-') in the same group. */ + '-') in the same group. */ #define OPTION_DOC 0x8 -/* This option shouldn't be included in `long' usage messages (but is still +/* This option shouldn't be included in "long" usage messages (but is still included in help messages). This is mainly intended for options that are completely documented in an argp's ARGS_DOC field, in which case including the option in the generic usage list would be redundant. For instance, - if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to + if ARGS_DOC is "FOO BAR\n-x BLAH", and the '-x' option's purpose is to distinguish these two cases, -x should probably be marked OPTION_NO_USAGE. */ #define OPTION_NO_USAGE 0x10 @@ -167,7 +167,7 @@ typedef error_t (*argp_parser_t) (int key, char *arg, ARGP_ERR_UNKNOWN should be returned if they aren't understood. The sequence of keys to a parsing function is either (where each - uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key): + uppercased word should be prefixed by 'ARGP_KEY_' and opt is a user key): INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed @@ -238,15 +238,15 @@ struct argp argp_parser_t parser; /* A string describing what other arguments are wanted by this program. It - is only used by argp_usage to print the `Usage:' message. If it + is only used by argp_usage to print the "Usage:" message. If it contains newlines, the strings separated by them are considered alternative usage patterns, and printed on separate lines (lines after - the first are prefix by ` or: ' instead of `Usage:'). */ + the first are prefix by " or: " instead of "Usage:"). */ const char *args_doc; /* If non-NULL, a string containing extra text to be printed before and after the options in a long help message (separated by a vertical tab - `\v' character). + '\v' character). Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if you want xgettext to collect the two pieces of text into a POT file. */ const char *doc; @@ -265,7 +265,7 @@ struct argp defines, below, describing which other help text TEXT is. The function should return either TEXT, if it should be used as-is, a replacement string, which should be malloced, and will be freed by argp, or NULL, - meaning `print nothing'. The value for TEXT is *after* any translation + meaning "print nothing". The value for TEXT is *after* any translation has been done, so if any of the replacement text also needs translation, that should be done by the filter function. INPUT is either the input supplied to argp_parse, or NULL, if argp_help was called directly. */ @@ -278,7 +278,7 @@ struct argp }; /* Possible KEY arguments to a help filter function. */ -#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */ +#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceding options. */ #define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ #define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ #define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; @@ -304,7 +304,7 @@ struct argp_child printing a header string, use a value of "". */ const char *header; - /* Where to group the child options relative to the other (`consolidated') + /* Where to group the child options relative to the other ("consolidated") options in the parent argp; the values are the same as the GROUP field in argp_option structs, but all child-groupings follow parent options at a particular group level. If both this field and HEADER are zero, then @@ -337,7 +337,7 @@ struct argp_state unsigned arg_num; /* If non-zero, the index in ARGV of the first argument following a special - `--' argument (which prevents anything following being interpreted as an + '--' argument (which prevents anything following being interpreted as an option). Only set once argument parsing has proceeded past this point. */ int quoted; @@ -399,7 +399,7 @@ struct argp_state /* Don't exit on errors (they may still result in error messages). */ #define ARGP_NO_EXIT 0x20 -/* Use the gnu getopt `long-only' rules for parsing arguments. */ +/* Use the gnu getopt "long-only" rules for parsing arguments. */ #define ARGP_LONG_ONLY 0x40 /* Turns off any message-printing/exiting options. */ @@ -456,7 +456,7 @@ extern void (*argp_program_version_hook) (FILE *__restrict __stream, the bug-reporting address for the program. It will be printed by argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help messages), embedded in a sentence that says something like - `Report bugs to ADDR.'. */ + "Report bugs to ADDR." */ extern const char *argp_program_bug_address; /* The exit status that argp will use when exiting due to a parsing error. @@ -467,7 +467,7 @@ extern error_t argp_err_exit_status; /* Flags for argp_help. */ #define ARGP_HELP_USAGE 0x01 /* a Usage: message. */ #define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */ -#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */ +#define ARGP_HELP_SEE 0x04 /* a "Try ... for more help" message. */ #define ARGP_HELP_LONG 0x08 /* a long help message. */ #define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */ #define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */ @@ -506,7 +506,7 @@ extern void __argp_help (const struct argp *__restrict __argp, parsing routine (thus taking an argp_state structure as the first argument). They may or may not print an error message and exit, depending on the flags in STATE -- in any case, the caller should be prepared for - them *not* to exit, and should return an appropiate error after calling + them *not* to exit, and should return an appropriate error after calling them. [argp_usage & argp_error should probably be called argp_state_..., but they're used often enough that they should be short] */ @@ -519,21 +519,21 @@ extern void __argp_state_help (const struct argp_state *__restrict __state, FILE *__restrict __stream, unsigned int __flags); -#if _LIBC || !defined __USE_EXTERN_INLINES +#if _LIBC /* Possibly output the standard usage message for ARGP to stderr and exit. */ extern void argp_usage (const struct argp_state *__state); extern void __argp_usage (const struct argp_state *__state); #endif /* If appropriate, print the printf string FMT and following args, preceded - by the program name and `:', to stderr, and followed by a `Try ... --help' + by the program name and ':', to stderr, and followed by a "Try ... --help" message, then exit (1). */ extern void argp_error (const struct argp_state *__restrict __state, const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 3)); extern void __argp_error (const struct argp_state *__restrict __state, const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 3)); /* Similar to the standard gnu error-reporting function error(), but will respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print @@ -546,13 +546,13 @@ extern void __argp_error (const struct argp_state *__restrict __state, extern void argp_failure (const struct argp_state *__restrict __state, int __status, int __errnum, const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 4, 5))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 4, 5)); extern void __argp_failure (const struct argp_state *__restrict __state, int __status, int __errnum, const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 4, 5))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 4, 5)); -#if _LIBC || !defined __USE_EXTERN_INLINES +#if _LIBC /* Returns true if the option OPT is a valid short option. */ extern int _option_is_short (const struct argp_option *__opt) __THROW; extern int __option_is_short (const struct argp_option *__opt) __THROW; @@ -572,13 +572,17 @@ extern void *__argp_input (const struct argp *__restrict __argp, const struct argp_state *__restrict __state) __THROW; -#ifdef __USE_EXTERN_INLINES +#if !_LIBC || defined __USE_EXTERN_INLINES # if !_LIBC # define __argp_usage argp_usage # define __argp_state_help argp_state_help # define __option_is_short _option_is_short # define __option_is_end _option_is_end +_GL_INLINE_HEADER_BEGIN +# ifndef ARGP_EI +# define ARGP_EI _GL_INLINE +# endif # endif # ifndef ARGP_EI @@ -635,6 +639,7 @@ __NTH (__option_is_end (const struct argp_option *__opt)) # undef __argp_state_help # undef __option_is_short # undef __option_is_end +_GL_INLINE_HEADER_END # endif #endif /* Use extern inlines. */ diff --git a/grub-core/gnulib/asnprintf.c b/grub-core/gnulib/asnprintf.c index 3bd2229d5..76e228d86 100644 --- a/grub-core/gnulib/asnprintf.c +++ b/grub-core/gnulib/asnprintf.c @@ -1,5 +1,5 @@ /* Formatted output to strings. - Copyright (C) 1999, 2002, 2006, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2006, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + with this program; if not, see . */ #include diff --git a/grub-core/gnulib/basename-lgpl.c b/grub-core/gnulib/basename-lgpl.c index a35ff01c2..9307e8314 100644 --- a/grub-core/gnulib/basename-lgpl.c +++ b/grub-core/gnulib/basename-lgpl.c @@ -1,6 +1,6 @@ /* basename.c -- return the last element in a file name - Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify diff --git a/grub-core/gnulib/btowc.c b/grub-core/gnulib/btowc.c index 8744602aa..6c7cbec9d 100644 --- a/grub-core/gnulib/btowc.c +++ b/grub-core/gnulib/btowc.c @@ -1,5 +1,5 @@ /* Convert unibyte character to wide character. - Copyright (C) 2008, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2010-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/grub-core/gnulib/config.charset b/grub-core/gnulib/config.charset index aa7d00dba..a991419cd 100644 --- a/grub-core/gnulib/config.charset +++ b/grub-core/gnulib/config.charset @@ -1,7 +1,7 @@ #! /bin/sh # Output a system dependent table of character encoding aliases. # -# Copyright (C) 2000-2004, 2006-2010 Free Software Foundation, Inc. +# Copyright (C) 2000-2004, 2006-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -14,8 +14,7 @@ # GNU 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. +# with this program; if not, see . # # The table consists of lines of the form # ALIAS CANONICAL @@ -30,6 +29,8 @@ # The current list of GNU canonical charset names is as follows. # # name MIME? used by which systems +# (darwin = Mac OS X, woe32 = native Windows) +# # 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 diff --git a/grub-core/gnulib/dirname-lgpl.c b/grub-core/gnulib/dirname-lgpl.c index d4506e060..82f66301f 100644 --- a/grub-core/gnulib/dirname-lgpl.c +++ b/grub-core/gnulib/dirname-lgpl.c @@ -1,6 +1,6 @@ /* dirname.c -- return all but the last element in a file name - Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ /* 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 + even though 'dir_name (FILE)' will return ".". Works properly even if there are trailing slashes (by effectively ignoring them). */ size_t @@ -53,9 +53,9 @@ dir_len (char const *file) } -/* In general, we can't use the builtin `dirname' function if available, +/* 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. + 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 diff --git a/grub-core/gnulib/dirname.h b/grub-core/gnulib/dirname.h index fb19508f7..4ad031200 100644 --- a/grub-core/gnulib/dirname.h +++ b/grub-core/gnulib/dirname.h @@ -1,6 +1,6 @@ /* Take file names apart into directory and base names. - Copyright (C) 1998, 2001, 2003-2006, 2009-2010 Free Software Foundation, + Copyright (C) 1998, 2001, 2003-2006, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -21,53 +21,25 @@ # include # include +# include "dosname.h" # 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); +size_t base_len (char const *file) _GL_ATTRIBUTE_PURE; +size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE; +char *last_component (char const *file) _GL_ATTRIBUTE_PURE; bool strip_trailing_slashes (char *file); diff --git a/grub-core/gnulib/dosname.h b/grub-core/gnulib/dosname.h new file mode 100644 index 000000000..ba63ce4bd --- /dev/null +++ b/grub-core/gnulib/dosname.h @@ -0,0 +1,53 @@ +/* File names on MS-DOS/Windows systems. + + Copyright (C) 2000-2001, 2004-2006, 2009-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + From Paul Eggert and Jim Meyering. */ + +#ifndef _DOSNAME_H +#define _DOSNAME_H + +#if (defined _WIN32 || defined __WIN32__ || \ + defined __MSDOS__ || defined __CYGWIN__ || \ + defined __EMX__ || defined __DJGPP__) + /* 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) +# ifndef __CYGWIN__ +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1 +# endif +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#else +# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 +# define ISSLASH(C) ((C) == '/') +#endif + +#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 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]) || FILE_SYSTEM_PREFIX_LEN (F) != 0) +#endif +#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) + +#endif /* DOSNAME_H_ */ diff --git a/grub-core/gnulib/errno.in.h b/grub-core/gnulib/errno.in.h index 140e5d134..49b35464b 100644 --- a/grub-core/gnulib/errno.in.h +++ b/grub-core/gnulib/errno.in.h @@ -1,6 +1,6 @@ /* A POSIX-like . - Copyright (C) 2008-2010 Free Software Foundation, Inc. + Copyright (C) 2008-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,69 +13,137 @@ GNU 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. */ + along with this program; if not, see . */ -#ifndef _GL_ERRNO_H +#ifndef _@GUARD_PREFIX@_ERRNO_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ /* The include_next requires a split double-inclusion guard. */ #@INCLUDE_NEXT@ @NEXT_ERRNO_H@ -#ifndef _GL_ERRNO_H -#define _GL_ERRNO_H +#ifndef _@GUARD_PREFIX@_ERRNO_H +#define _@GUARD_PREFIX@_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 +/* These are the same values as defined by MSVC 10, for interoperability. */ -/* Values >= 100 seem safe to use. */ -# define ETXTBSY 100 -# define GNULIB_defined_ETXTBSY 1 +# ifndef ENOMSG +# define ENOMSG 122 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 111 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 121 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 134 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 104 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 129 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 117 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 105 +# define GNULIB_defined_ECANCELED 1 +# endif + +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# define GNULIB_defined_EOWNERDEAD 1 +# endif + +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# define EALREADY 103 +# define ENOTSOCK 128 +# define EDESTADDRREQ 109 +# define EMSGSIZE 115 +# define EPROTOTYPE 136 +# define ENOPROTOOPT 123 +# define EPROTONOSUPPORT 135 +# define EOPNOTSUPP 130 +# define EAFNOSUPPORT 102 +# define EADDRINUSE 100 +# define EADDRNOTAVAIL 101 +# define ENETDOWN 116 +# define ENETUNREACH 118 +# define ECONNRESET 108 +# define ENOBUFS 119 +# define EISCONN 113 +# define ENOTCONN 126 +# define ETIMEDOUT 138 +# define ECONNREFUSED 107 +# define ELOOP 114 +# define EHOSTUNREACH 110 +# define EWOULDBLOCK 140 +# define GNULIB_defined_ESOCK 1 +# endif + +# ifndef ETXTBSY +# define ETXTBSY 139 +# define ENODATA 120 /* not required by POSIX */ +# define ENOSR 124 /* not required by POSIX */ +# define ENOSTR 125 /* not required by POSIX */ +# define ETIME 137 /* not required by POSIX */ +# define EOTHER 131 /* not required by POSIX */ +# define GNULIB_defined_ESTREAMS 1 +# endif /* 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 +# define GNULIB_defined_EWINSOCK 1 # endif @@ -98,6 +166,7 @@ /* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK, EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined. + Likewise, on NonStop Kernel, EDQUOT is not defined. Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151, HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133. @@ -145,16 +214,66 @@ # define GNULIB_defined_ENOTSUP 1 # endif +# ifndef ENETRESET +# define ENETRESET 2011 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 2012 +# define GNULIB_defined_ECONNABORTED 1 +# endif + # ifndef ESTALE # define ESTALE 2009 # define GNULIB_defined_ESTALE 1 # endif +# ifndef EDQUOT +# define EDQUOT 2010 +# define GNULIB_defined_EDQUOT 1 +# endif + # ifndef ECANCELED # define ECANCELED 2008 # define GNULIB_defined_ECANCELED 1 # endif +/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not + defined. */ -#endif /* _GL_ERRNO_H */ -#endif /* _GL_ERRNO_H */ +# ifndef EOWNERDEAD +# if defined __sun + /* Use the same values as defined for Solaris >= 8, for + interoperability. */ +# define EOWNERDEAD 58 +# define ENOTRECOVERABLE 59 +# elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* We have a conflict here: pthreads-win32 defines these values + differently than MSVC 10. It's hairy to decide which one to use. */ +# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS + /* Use the same values as defined by pthreads-win32, for + interoperability. */ +# define EOWNERDEAD 43 +# define ENOTRECOVERABLE 44 +# else + /* Use the same values as defined by MSVC 10, for + interoperability. */ +# define EOWNERDEAD 133 +# define ENOTRECOVERABLE 127 +# endif +# else +# define EOWNERDEAD 2013 +# define ENOTRECOVERABLE 2014 +# endif +# define GNULIB_defined_EOWNERDEAD 1 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EILSEQ +# define EILSEQ 2015 +# define GNULIB_defined_EILSEQ 1 +# endif + +#endif /* _@GUARD_PREFIX@_ERRNO_H */ +#endif /* _@GUARD_PREFIX@_ERRNO_H */ diff --git a/grub-core/gnulib/error.c b/grub-core/gnulib/error.c index ed9dba0d2..865b29340 100644 --- a/grub-core/gnulib/error.c +++ b/grub-core/gnulib/error.c @@ -1,5 +1,5 @@ /* Error handler for noninteractive utilities - Copyright (C) 1990-1998, 2000-2007, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 1990-1998, 2000-2007, 2009-2013 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 @@ -54,7 +54,7 @@ function without parameters instead. */ void (*error_print_progname) (void); -/* This variable is incremented each time `error' is called. */ +/* This variable is incremented each time 'error' is called. */ unsigned int error_message_count; #ifdef _LIBC @@ -65,7 +65,7 @@ unsigned int error_message_count; # include # include -/* In GNU libc we want do not want to use the common name `error' directly. +/* In GNU libc we want do not want to use the common name 'error' directly. Instead make it a weak alias. */ extern void __error (int status, int errnum, const char *message, ...) __attribute__ ((__format__ (__printf__, 3, 4))); @@ -89,19 +89,25 @@ extern void __error_at_line (int status, int errnum, const char *file_name, # include # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Get declarations of the Win32 API functions. */ +/* Get declarations of the native Windows API functions. */ # define WIN32_LEAN_AND_MEAN # include +/* Get _get_osfhandle. */ +# include "msvc-nothrow.h" # endif /* The gnulib override of fcntl is not needed in this file. */ # undef fcntl -# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P +# if !HAVE_DECL_STRERROR_R # ifndef HAVE_DECL_STRERROR_R "this configure-time declaration test was not run" # endif +# if STRERROR_R_CHAR_P char *strerror_r (); +# else +int strerror_r (); +# endif # endif /* The calling program should define program_name and set it to the @@ -115,13 +121,14 @@ extern char *program_name; #if !_LIBC /* Return non-zero if FD is open. */ -static inline int +static 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. */ + /* On native Windows: 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 @@ -132,7 +139,7 @@ is_open (int fd) } #endif -static inline void +static void flush_stdout (void) { #if !_LIBC diff --git a/grub-core/gnulib/error.h b/grub-core/gnulib/error.h index 9deef02d2..afcb0e10c 100644 --- a/grub-core/gnulib/error.h +++ b/grub-core/gnulib/error.h @@ -1,6 +1,6 @@ /* Declaration for error-reporting function - Copyright (C) 1995, 1996, 1997, 2003, 2006, 2008, 2009, 2010 Free Software - Foundation, Inc. + Copyright (C) 1995-1997, 2003, 2006, 2008-2013 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 @@ -19,39 +19,39 @@ #ifndef _ERROR_H #define _ERROR_H 1 -#ifndef __attribute__ /* The __attribute__ feature is available in gcc versions 2.5 and later. The __-protected variants of the attributes 'format' and 'printf' are accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because + We enable _GL_ATTRIBUTE_FORMAT 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 +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ #endif #ifdef __cplusplus extern "C" { #endif -/* Print a message with `fprintf (stderr, FORMAT, ...)'; +/* Print a message with 'fprintf (stderr, FORMAT, ...)'; if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ + If STATUS is nonzero, terminate the program with 'exit (STATUS)'. */ extern void error (int __status, int __errnum, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4)); extern void error_at_line (int __status, int __errnum, const char *__fname, unsigned int __lineno, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 5, 6))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 5, 6)); /* If NULL, error will flush stdout, then print on stderr the program name, a colon and a space. Otherwise, error will call this function without parameters instead. */ extern void (*error_print_progname) (void); -/* This variable is incremented each time `error' is called. */ +/* This variable is incremented each time 'error' is called. */ extern unsigned int error_message_count; /* Sometimes we want to have at most one error per line. This diff --git a/grub-core/gnulib/float+.h b/grub-core/gnulib/float+.h index b55e5e6de..32fb790bb 100644 --- a/grub-core/gnulib/float+.h +++ b/grub-core/gnulib/float+.h @@ -1,5 +1,5 @@ /* Supplemental information about the floating-point formats. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2007. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ #ifndef _FLOATPLUS_H #define _FLOATPLUS_H @@ -141,8 +140,8 @@ #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]; +typedef int verify_sizeof_flt[SIZEOF_FLT <= sizeof (float) ? 1 : -1]; +typedef int verify_sizeof_dbl[SIZEOF_DBL <= sizeof (double) ? 1 : - 1]; +typedef int verify_sizeof_ldbl[SIZEOF_LDBL <= sizeof (long double) ? 1 : - 1]; #endif /* _FLOATPLUS_H */ diff --git a/grub-core/gnulib/float.c b/grub-core/gnulib/float.c new file mode 100644 index 000000000..366945fa3 --- /dev/null +++ b/grub-core/gnulib/float.c @@ -0,0 +1,33 @@ +/* Auxiliary definitions for . + Copyright (C) 2011-2013 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the 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 (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ +const union gl_long_double_union gl_LDBL_MAX = + { { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } }; +#elif defined __i386__ +const union gl_long_double_union gl_LDBL_MAX = + { { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } }; +#else +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; +#endif diff --git a/grub-core/gnulib/float.in.h b/grub-core/gnulib/float.in.h index caf822f1d..84e1950f9 100644 --- a/grub-core/gnulib/float.in.h +++ b/grub-core/gnulib/float.in.h @@ -1,6 +1,6 @@ /* A correct . - Copyright (C) 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2007-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,19 +15,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef _GL_FLOAT_H +#ifndef _@GUARD_PREFIX@_FLOAT_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ /* The include_next requires a split double-inclusion guard. */ #@INCLUDE_NEXT@ @NEXT_FLOAT_H@ -#ifndef _GL_FLOAT_H -#define _GL_FLOAT_H +#ifndef _@GUARD_PREFIX@_FLOAT_H +#define _@GUARD_PREFIX@_FLOAT_H /* 'long double' properties. */ + #if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) /* Number of mantissa units, in base FLT_RADIX. */ # undef LDBL_MANT_DIG @@ -58,5 +60,129 @@ # define LDBL_MAX_10_EXP 4932 #endif -#endif /* _GL_FLOAT_H */ -#endif /* _GL_FLOAT_H */ +/* On FreeBSD/x86 6.4, the 'long double' type really has only 53 bits of + precision in the compiler but 64 bits of precision at runtime. See + . */ +#if defined __i386__ && defined __FreeBSD__ +/* 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.084202172485504434007452800869941711426e-19L /* 2^-63 */ +/* 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.3621031431120935E-4932L /* = 0x1p-16382L */ +/* Maximum representable finite number. */ +# undef LDBL_MAX +/* LDBL_MAX is represented as { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }. + But the largest literal that GCC allows us to write is + 0x0.fffffffffffff8p16384L = { 0xFFFFF800, 0xFFFFFFFF, 32766 }. + So, define it like this through a reference to an external variable + + const unsigned int LDBL_MAX[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }; + extern const long double LDBL_MAX; + + Unfortunately, this is not a constant expression. */ +union gl_long_double_union + { + struct { unsigned int lo; unsigned int hi; unsigned int exponent; } xd; + long double ld; + }; +extern const union gl_long_double_union gl_LDBL_MAX; +# define LDBL_MAX (gl_LDBL_MAX.ld) +/* 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 + +/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are + wrong. + On Linux/PowerPC with gcc 4.4, the value of LDBL_MAX is wrong. */ +#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP DBL_MIN_10_EXP +# undef LDBL_MIN +# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +#endif +#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MAX +/* LDBL_MAX is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xFFFFFFFF }. + It is not easy to define: + #define LDBL_MAX 1.79769313486231580793728971405302307166e308L + is too small, whereas + #define LDBL_MAX 1.79769313486231580793728971405302307167e308L + is too large. Apparently a bug in GCC decimal-to-binary conversion. + Also, I can't get values larger than + #define LDBL63 ((long double) (1ULL << 63)) + #define LDBL882 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL945 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL1008 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL_MAX (LDBL1008 * 65535.0L + LDBL945 * (long double) 9223372036821221375ULL + LDBL882 * (long double) 4611686018427387904ULL) + which is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xF8000000 }. + So, define it like this through a reference to an external variable + + const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }; + extern const long double LDBL_MAX; + + or through a pointer cast + + #define LDBL_MAX \ + (*(const long double *) (double[]) { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }) + + Unfortunately, this is not a constant expression, and the latter expression + does not work well when GCC is optimizing.. */ +union gl_long_double_union + { + struct { double hi; double lo; } dd; + long double ld; + }; +extern const union gl_long_double_union gl_LDBL_MAX; +# define LDBL_MAX (gl_LDBL_MAX.ld) +#endif + +/* On IRIX 6.5, with cc, the value of LDBL_MANT_DIG is wrong. + On IRIX 6.5, with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_EPSILON + are wrong. */ +#if defined __sgi && (LDBL_MANT_DIG >= 106) +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 106 +# if defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP DBL_MIN_10_EXP +# undef LDBL_MIN +# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 2.46519032881566189191165176650870696773e-32L /* 2^-105 */ +# endif +#endif + +#if @REPLACE_ITOLD@ +/* Pull in a function that fixes the 'int' to 'long double' conversion + of glibc 2.7. */ +extern +# ifdef __cplusplus +"C" +# endif +void _Qp_itoq (long double *, int); +static void (*_gl_float_fix_itold) (long double *, int) = _Qp_itoq; +#endif + +#endif /* _@GUARD_PREFIX@_FLOAT_H */ +#endif /* _@GUARD_PREFIX@_FLOAT_H */ diff --git a/grub-core/gnulib/fnmatch.c b/grub-core/gnulib/fnmatch.c index d73e47dae..6a09e1a9b 100644 --- a/grub-core/gnulib/fnmatch.c +++ b/grub-core/gnulib/fnmatch.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993, 1996-2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +11,7 @@ GNU 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. */ + along with this program; if not, see . */ #ifndef _LIBC # include @@ -43,7 +41,7 @@ (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \ && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY)) -/* For platform which support the ISO C amendement 1 functionality we +/* For platform which support the ISO C amendment 1 functionality we support user defined character classes. */ #if defined _LIBC || WIDE_CHAR_SUPPORT # include @@ -79,7 +77,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, + program understand 'configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU @@ -93,7 +91,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); # if defined _LIBC || WIDE_CHAR_SUPPORT /* The GNU C library provides support for user-defined character classes - and the functions from ISO C amendement 1. */ + and the functions from ISO C amendment 1. */ # ifdef CHARCLASS_NAME_MAX # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX # else @@ -120,7 +118,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags); # endif # else -# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, 'xdigit'. */ # define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ @@ -169,7 +167,6 @@ static int posixly_correct; # endif # endif # define MEMCHR(S, C, N) memchr (S, C, N) -# define STRCOLL(S1, S2) strcoll (S1, S2) # include "fnmatch_loop.c" @@ -197,7 +194,6 @@ static int posixly_correct; # endif # endif # define MEMCHR(S, C, N) wmemchr (S, C, N) -# define STRCOLL(S1, S2) wcscoll (S1, S2) # define WIDE_CHAR_VERSION 1 # undef IS_CHAR_CLASS diff --git a/grub-core/gnulib/fnmatch.in.h b/grub-core/gnulib/fnmatch.in.h index 8caab1959..d39ce2f1c 100644 --- a/grub-core/gnulib/fnmatch.in.h +++ b/grub-core/gnulib/fnmatch.in.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003, - 2005, 2007, 2009, 2010 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993, 1996-1999, 2001-2003, 2005, 2007, 2009-2013 Free + Software Foundation, Inc. This file is part of the GNU C Library. @@ -14,8 +14,7 @@ GNU 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. */ + along with this program; if not, see . */ #ifndef _FNMATCH_H #define _FNMATCH_H 1 @@ -32,23 +31,23 @@ extern "C" { #undef FNM_NOESCAPE #undef FNM_PERIOD -/* Bits set in the FLAGS argument to `fnmatch'. */ -#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +/* 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_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_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. */ +/* Value returned by 'fnmatch' if STRING does not match PATTERN. */ #define FNM_NOMATCH 1 /* This value is returned if the implementation does not support - `fnmatch'. Since this is not the case here it will never be + '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 diff --git a/grub-core/gnulib/fnmatch_loop.c b/grub-core/gnulib/fnmatch_loop.c index 741c993ef..f57cd63f9 100644 --- a/grub-core/gnulib/fnmatch_loop.c +++ b/grub-core/gnulib/fnmatch_loop.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2009, 2010 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993, 1996-2006, 2009-2013 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 @@ -13,8 +12,7 @@ GNU 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. */ + along with this program; if not, see . */ /* Match STRING against the file name pattern PATTERN, returning zero if it matches, nonzero if not. */ @@ -201,6 +199,8 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, case L_('['): { /* Nonzero if the sense of the character class is inverted. */ + const CHAR *p_init = p; + const CHAR *n_init = n; register bool not; CHAR cold; UCHAR fn; @@ -215,7 +215,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, return FNM_NOMATCH; if (*n == L_('/') && (flags & FNM_FILE_NAME)) - /* `/' cannot be matched. */ + /* '/' cannot be matched. */ return FNM_NOMATCH; not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^'))); @@ -381,7 +381,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, { /* We found a table entry. Now see whether the character we are currently at has the same - equivalance class value. */ + equivalence class value. */ int len = weights[idx & 0xffffff]; int32_t idx2; const UCHAR *np = (const UCHAR *) n; @@ -411,8 +411,13 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, } #endif else if (c == L_('\0')) - /* [ (unterminated) loses. */ - return FNM_NOMATCH; + { + /* [ unterminated, treat as normal character. */ + p = p_init; + n = n_init; + c = L_('['); + goto normal_match; + } else { bool is_range = false; @@ -630,7 +635,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, UCHAR cend = *p++; # ifdef WIDE_CHAR_VERSION - /* Search in the `names' array for the characters. */ + /* Search in the 'names' array for the characters. */ fcollseq = __collseq_table_lookup (collseq, fn); if (fcollseq == ~((uint32_t) 0)) /* XXX We don't know anything about the character @@ -833,7 +838,7 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, #else /* We use a boring value comparison of the character values. This is better than comparing using - `strcoll' since the latter would have surprising + 'strcoll' since the latter would have surprising and sometimes fatal consequences. */ UCHAR cend = *p++; @@ -1150,7 +1155,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, case L_('@'): do - /* I cannot believe it but `strcat' is actually acceptable + /* I cannot believe it but 'strcat' is actually acceptable here. Match the entire string with the prefix from the pattern list and the rest of the pattern following the pattern list. */ @@ -1208,7 +1213,6 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, #undef END #undef MEMPCPY #undef MEMCHR -#undef STRCOLL #undef STRLEN #undef STRCAT #undef L_ diff --git a/grub-core/gnulib/getdelim.c b/grub-core/gnulib/getdelim.c index 66d07b9ae..fdbcde2a2 100644 --- a/grub-core/gnulib/getdelim.c +++ b/grub-core/gnulib/getdelim.c @@ -1,6 +1,6 @@ /* getdelim.c --- Implementation of replacement getdelim function. - Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2013 Free Software + Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -13,18 +13,16 @@ 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. */ + along with this program; if not, see . */ /* Ported from glibc by Simon Josefsson. */ -#include - /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ #define _GL_ARG_NONNULL(params) +#include + #include #include diff --git a/grub-core/gnulib/getline.c b/grub-core/gnulib/getline.c index 30c076e87..1aa07b9c7 100644 --- a/grub-core/gnulib/getline.c +++ b/grub-core/gnulib/getline.c @@ -1,5 +1,5 @@ /* getline.c --- Implementation of replacement getline function. - Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005-2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -12,9 +12,7 @@ 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. */ + along with this program; if not, see . */ /* Written by Simon Josefsson. */ diff --git a/grub-core/gnulib/getopt.c b/grub-core/gnulib/getopt.c index 3791f1293..ef0f4ceec 100644 --- a/grub-core/gnulib/getopt.c +++ b/grub-core/gnulib/getopt.c @@ -2,7 +2,7 @@ NOTE: getopt is part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! - Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2010 Free Software + Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -41,15 +41,15 @@ # include #endif -/* This version of `getopt' appears to the caller like standard Unix `getopt' +/* This version of 'getopt' appears to the caller like standard Unix 'getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. - As `getopt_long' works, it permutes the elements of ARGV so that, + As 'getopt_long' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. - Using `getopt' or setting the environment variable POSIXLY_CORRECT + Using 'getopt' or setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. @@ -58,24 +58,24 @@ #include "getopt_int.h" -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, + Also, when 'ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller - and for communication between successive calls to `getopt'. + and for communication between successive calls to 'getopt'. - On entry to `getopt', zero means this is the first call; initialize. + On entry to 'getopt', zero means this is the first call; initialize. - When `getopt' returns -1, this is the index of the first of the + When 'getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. - Otherwise, `optind' communicates from one call to the next + Otherwise, 'optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ @@ -137,7 +137,7 @@ extern char *__getopt_nonoption_flags; The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. - `first_nonopt' and `last_nonopt' are relocated so that they describe + 'first_nonopt' and 'last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void @@ -154,7 +154,7 @@ exchange (char **argv, struct _getopt_data *d) but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' + /* First make sure the handling of the '__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) @@ -291,48 +291,48 @@ _getopt_initialize (int argc _GL_UNUSED, If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' + (aside from the initial '-') are option characters. If 'getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can + If 'getopt' finds another option character, it returns that character, + updating 'optind' and 'nextchar' so that the next call to 'getopt' can resume the scan with the following option character or ARGV-element. - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element + If there are no more option characters, 'getopt' returns -1. + Then 'optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to + return '?' after printing an error message. If you set 'opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that + ARGV-element, is returned in 'optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. + it is returned in 'optarg', otherwise 'optarg' is set to zero. - If OPTSTRING starts with `-' or `+', it requests different methods of + If OPTSTRING starts with '-' or '+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - Long-named options begin with `--' instead of `-'. + Long-named options begin with '--' instead of '-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. + from the option name by a '=', or else the in next ARGV-element. + When 'getopt' finds a long-named option, it returns 0 if that option's + 'flag' field is nonzero, the value of the option's 'val' field + if the 'flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. - LONGOPTS is a vector of `struct option' terminated by an + LONGOPTS is a vector of 'struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. @@ -409,7 +409,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, d->__last_nonopt = d->optind; } - /* The special ARGV-element `--' means premature end of options. + /* The special ARGV-element '--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ @@ -479,23 +479,28 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, || !strchr (optstring, argv[d->optind][1]))))) { char *nameend; + unsigned int namelen; const struct option *p; const struct option *pfound = NULL; + struct option_list + { + const struct option *p; + struct option_list *next; + } *ambig_list = NULL; int exact = 0; - int ambig = 0; int indfound = -1; int option_index; for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; + namelen = nameend - d->__nextchar; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + if (!strncmp (p->name, d->__nextchar, namelen)) { - if ((unsigned int) (nameend - d->__nextchar) - == (unsigned int) strlen (p->name)) + if (namelen == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -513,35 +518,71 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; + { + /* Second or later nonexact match found. */ + struct option_list *newp = malloc (sizeof (*newp)); + newp->p = p; + newp->next = ambig_list; + ambig_list = newp; + } } - if (ambig && !exact) + if (ambig_list != NULL && !exact) { if (print_errors) { + struct option_list first; + first.p = pfound; + first.next = ambig_list; + ambig_list = &first; + #if defined _LIBC && defined USE_IN_LIBIO - char *buf; + char *buf = NULL; + size_t buflen = 0; - if (__asprintf (&buf, _("%s: option '%s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) + FILE *fp = open_memstream (&buf, &buflen); + if (fp != NULL) { - _IO_flockfile (stderr); + fprintf (fp, + _("%s: option '%s' is ambiguous; possibilities:"), + argv[0], argv[d->optind]); - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + do + { + fprintf (fp, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); - __fxprintf (NULL, "%s", buf); + fputc_unlocked ('\n', fp); - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); + if (__builtin_expect (fclose (fp) != EOF, 1)) + { + _IO_flockfile (stderr); - free (buf); + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } } #else - fprintf (stderr, _("%s: option '%s' is ambiguous\n"), + fprintf (stderr, + _("%s: option '%s' is ambiguous; possibilities:"), argv[0], argv[d->optind]); + do + { + fprintf (stderr, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + + fputc ('\n', stderr); #endif } d->__nextchar += strlen (d->__nextchar); @@ -550,6 +591,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, return '?'; } + while (ambig_list != NULL) + { + struct option_list *pn = ambig_list->next; + free (ambig_list); + ambig_list = pn; + } + if (pfound != NULL) { option_index = indfound; @@ -740,7 +788,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char c = *d->__nextchar++; const char *temp = strchr (optstring, c); - /* Increment `optind' when we start to process its last character. */ + /* Increment 'optind' when we start to process its last character. */ if (*d->__nextchar == '\0') ++d->optind; @@ -791,6 +839,9 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int indfound = 0; int option_index; + if (longopts == NULL) + goto no_longs; + /* This is an option that requires an argument. */ if (*d->__nextchar != '\0') { @@ -836,7 +887,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, return c; } else - /* We already incremented `d->optind' once; + /* We already incremented 'd->optind' once; increment it again when taking next ARGV-elt as argument. */ d->optarg = argv[d->optind++]; @@ -998,8 +1049,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } return pfound->val; } - d->__nextchar = NULL; - return 'W'; /* Let the application handle it. */ + + no_longs: + d->__nextchar = NULL; + return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { @@ -1061,7 +1114,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, c = '?'; } else - /* We already incremented `optind' once; + /* We already incremented 'optind' once; increment it again when taking next ARGV-elt as argument. */ d->optarg = argv[d->optind++]; d->__nextchar = NULL; @@ -1124,7 +1177,7 @@ __posix_getopt (int argc, char *const *argv, const char *optstring) #ifdef TEST /* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ + the above definition of 'getopt'. */ int main (int argc, char **argv) diff --git a/grub-core/gnulib/getopt.in.h b/grub-core/gnulib/getopt.in.h index 57a8e8992..d9c7d8144 100644 --- a/grub-core/gnulib/getopt.in.h +++ b/grub-core/gnulib/getopt.in.h @@ -1,5 +1,5 @@ /* Declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2007, 2009-2010 Free Software + Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2007, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -16,11 +16,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef _GL_GETOPT_H +#ifndef _@GUARD_PREFIX@_GETOPT_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ /* The include_next requires a split double-inclusion guard. We must also inform the replacement unistd.h to not recursively use @@ -31,10 +32,10 @@ # undef _GL_SYSTEM_GETOPT #endif -#ifndef _GL_GETOPT_H +#ifndef _@GUARD_PREFIX@_GETOPT_H #ifndef __need_getopt -# define _GL_GETOPT_H 1 +# define _@GUARD_PREFIX@_GETOPT_H 1 #endif /* Standalone applications should #define __GETOPT_PREFIX to an @@ -48,7 +49,9 @@ linkers. */ #if defined __GETOPT_PREFIX && !defined __need_getopt # if !@HAVE_GETOPT_H@ +# define __need_system_stdlib_h # include +# undef __need_system_stdlib_h # include # include # endif @@ -81,7 +84,7 @@ getopt_long_only can permute argv; this is required for backward compatibility (e.g., for LSB 2.0.1). - This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt', + This used to be '#if defined __GETOPT_PREFIX && !defined __need_getopt', but it caused redefinition warnings if both unistd.h and getopt.h were included, since unistd.h includes getopt.h having previously defined __need_getopt. @@ -127,29 +130,29 @@ extern "C" { #endif -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, + Also, when 'ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller - and for communication between successive calls to `getopt'. + and for communication between successive calls to 'getopt'. - On entry to `getopt', zero means this is the first call; initialize. + On entry to 'getopt', zero means this is the first call; initialize. - When `getopt' returns -1, this is the index of the first of the + When 'getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. - Otherwise, `optind' communicates from one call to the next + Otherwise, 'optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; -/* Callers store zero here to inhibit the error message `getopt' prints +/* Callers store zero here to inhibit the error message 'getopt' prints for unrecognized options. */ extern int opterr; @@ -161,25 +164,26 @@ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is + of 'struct option' terminated by an element containing a name which is zero. - The field `has_arg' is: + The field 'has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but + If the field 'flag' is not NULL, it points to a variable that is set + to the value given in the field 'val' when the option is found, but left unchanged if the option is not found. - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero + To have a long-named option do something other than set an 'int' to + a compiled-in constant, such as set a value from 'optarg', set the + option's 'flag' field to zero and its 'val' field to a nonzero value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ + one). For long options that have a zero 'flag' field, 'getopt' + returns the contents of the 'val' field. */ +# if !GNULIB_defined_struct_option struct option { const char *name; @@ -189,8 +193,10 @@ struct option int *flag; int val; }; +# define GNULIB_defined_struct_option 1 +# endif -/* Names for the values of the `has_arg' field of `struct option'. */ +/* Names for the values of the 'has_arg' field of 'struct option'. */ # define no_argument 0 # define required_argument 1 @@ -204,23 +210,23 @@ struct option Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options - missing arguments, `optopt' is set to the option letter, and '?' is + missing arguments, 'optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in `optarg'. + takes an argument, to be placed in 'optarg'. If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU `getopt'. + optional. This behavior is specific to the GNU 'getopt'. - The argument `--' causes premature termination of argument - scanning, explicitly telling `getopt' that there are no more + The argument '--' causes premature termination of argument + scanning, explicitly telling 'getopt' that there are no more options. - If OPTS begins with `-', then non-option arguments are treated as + If OPTS begins with '-', then non-option arguments are treated as arguments to the option '\1'. This behavior is specific to the GNU - `getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in + 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in the environment, then do not permute arguments. */ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) @@ -245,5 +251,5 @@ extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt -#endif /* getopt.h */ -#endif /* getopt.h */ +#endif /* _@GUARD_PREFIX@_GETOPT_H */ +#endif /* _@GUARD_PREFIX@_GETOPT_H */ diff --git a/grub-core/gnulib/getopt1.c b/grub-core/gnulib/getopt1.c index 046d69f94..55a6b4eae 100644 --- a/grub-core/gnulib/getopt1.c +++ b/grub-core/gnulib/getopt1.c @@ -1,6 +1,6 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, - 1998, 2004, 2006, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1987-1994, 1996-1998, 2004, 2006, 2009-2013 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 @@ -141,11 +141,11 @@ main (int argc, char **argv) break; case 'c': - printf ("option c with value `%s'\n", optarg); + printf ("option c with value '%s'\n", optarg); break; case 'd': - printf ("option d with value `%s'\n", optarg); + printf ("option d with value '%s'\n", optarg); break; case '?': diff --git a/grub-core/gnulib/getopt_int.h b/grub-core/gnulib/getopt_int.h index 980b7507f..a6e4b9ea7 100644 --- a/grub-core/gnulib/getopt_int.h +++ b/grub-core/gnulib/getopt_int.h @@ -1,5 +1,5 @@ /* Internal declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2010 Free Software + Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -40,7 +40,7 @@ extern int _getopt_internal (int ___argc, char **___argv, 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 + 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 @@ -52,12 +52,12 @@ extern int _getopt_internal (int ___argc, char **___argv, 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 + 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. */ + 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 { @@ -99,8 +99,8 @@ struct _getopt_data /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first - of them; `last_nonopt' is the index after the last of them. */ + been skipped. 'first_nonopt' is the index in ARGV of the first + of them; 'last_nonopt' is the index after the last of them. */ int __first_nonopt; int __last_nonopt; @@ -108,7 +108,7 @@ struct _getopt_data #if defined _LIBC && defined USE_NONOPTION_FLAGS int __nonoption_flags_max_len; int __nonoption_flags_len; -# endif +#endif }; /* The initializer is necessary to set OPTIND and OPTERR to their diff --git a/grub-core/gnulib/gettext.h b/grub-core/gnulib/gettext.h index 881ae3304..d0215715a 100644 --- a/grub-core/gnulib/gettext.h +++ b/grub-core/gnulib/gettext.h @@ -1,5 +1,5 @@ /* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2010 Free Software + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 @@ -54,7 +53,7 @@ it now, to make later inclusions of a NOP. */ #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) # include -# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H # include # endif #endif @@ -93,6 +92,12 @@ #endif +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. @@ -178,9 +183,12 @@ npgettext_aux (const char *domain, #include -#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ - (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ - /* || __STDC_VERSION__ >= 199901L */ ) +#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ + /* || __STDC_VERSION__ >= 199901L */ ) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #include diff --git a/grub-core/gnulib/intprops.h b/grub-core/gnulib/intprops.h index 46f4d47d7..b473052d1 100644 --- a/grub-core/gnulib/intprops.h +++ b/grub-core/gnulib/intprops.h @@ -1,7 +1,6 @@ /* intprops.h -- properties of integer types - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010 Free Software - Foundation, Inc. + Copyright (C) 2001-2005, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,66 +17,303 @@ /* Written by Paul Eggert. */ -#ifndef GL_INTPROPS_H -# define GL_INTPROPS_H +#ifndef _GL_INTPROPS_H +#define _GL_INTPROPS_H -# include +#include + +/* Return an integer value, converted to the same type as the integer + expression E after integer type promotion. V is the unconverted value. */ +#define _GL_INT_CONVERT(e, v) (0 * (e) + (v)) + +/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see + . */ +#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v)) /* 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) +#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) +#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 signed integer expression E uses two's complement. */ +#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1) /* True if the arithmetic type T is signed. */ -# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) -/* The maximum and minimum values for the integer type T. These +/* Return 1 if the integer expression E, after integer promotion, has + a signed type. */ +#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) + + +/* Minimum and maximum values for integer types and expressions. 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 +/* The maximum and minimum values for the integer type T. */ +#define TYPE_MINIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) 0 \ + : TYPE_SIGNED_MAGNITUDE (t) \ + ? ~ (t) 0 \ + : ~ TYPE_MAXIMUM (t))) +#define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) + +/* The maximum and minimum values for the type of the expression E, + after integer promotion. E should not have side effects. */ +#define _GL_INT_MINIMUM(e) \ + (_GL_INT_SIGNED (e) \ + ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_CONVERT (e, 0)) +#define _GL_INT_MAXIMUM(e) \ + (_GL_INT_SIGNED (e) \ + ? _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_NEGATE_CONVERT (e, 1)) +#define _GL_SIGNED_INT_MAXIMUM(e) \ + (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1) + + +/* Return 1 if the __typeof__ keyword works. This could be done by + 'configure', but for now it's easier to do it by hand. */ +#if 2 <= __GNUC__ || 0x5110 <= __SUNPRO_C +# define _GL_HAVE___TYPEOF__ 1 +#else +# define _GL_HAVE___TYPEOF__ 0 +#endif + +/* Return 1 if the integer type or expression T might be signed. Return 0 + if it is definitely unsigned. This macro does not evaluate its argument, + and expands to an integer constant expression. */ +#if _GL_HAVE___TYPEOF__ +# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) +#else +# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 +#endif + +/* Bound on length of the string representing an unsigned integer + value representable in B bits. log10 (2.0) < 146/485. The + smallest value of B where this bound is not tight is 2621. */ +#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) /* 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) + Subtract 1 for the sign bit if T is signed, and then add 1 more for + a minus sign if needed. + + Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is + signed, this macro may overestimate the true bound by one byte when + applied to unsigned types of size 2, 4, 16, ... bytes. */ +#define INT_STRLEN_BOUND(t) \ + (INT_BITS_STRLEN_BOUND (sizeof (t) * CHAR_BIT \ + - _GL_SIGNED_TYPE_OR_EXPR (t)) \ + + _GL_SIGNED_TYPE_OR_EXPR (t)) /* 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) +#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) -#endif /* GL_INTPROPS_H */ + +/* Range overflow checks. + + The INT__RANGE_OVERFLOW macros return 1 if the corresponding C + operators might not yield numerically correct answers due to + arithmetic overflow. They do not rely on undefined or + implementation-defined behavior. Their implementations are simple + and straightforward, but they are a bit harder to use than the + INT__OVERFLOW macros described below. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + Restrictions on *_RANGE_OVERFLOW macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, + so the arguments should not have side effects. The arithmetic + arguments (including the MIN and MAX arguments) must be of the same + integer type after the usual arithmetic conversions, and the type + must have minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN of the proper type. + + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (a) < (min) - (b) \ + : (max) - (b) < (a)) + +/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (max) + (b) < (a) \ + : (a) < (min) + (b)) + +/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ + ((min) < 0 \ + ? (a) < - (max) \ + : 0 < (a)) + +/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Avoid && and || as they tickle + bugs in Sun C 5.11 2010/08/13 and other compilers; see + . */ +#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (a) < (max) / (b) \ + : (b) == -1 \ + ? 0 \ + : (min) / (b) < (a)) \ + : (b) == 0 \ + ? 0 \ + : ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a))) + +/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. */ +#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ + ((min) < 0 && (b) == -1 && (a) < - (max)) + +/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. + Mathematically, % should never overflow, but on x86-like hosts + INT_MIN % -1 traps, and the C standard permits this, so treat this + as an overflow too. */ +#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ + INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) + +/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Here, MIN and MAX are for A only, and B need + not be of the same type as the other arguments. The C standard says that + behavior is undefined for shifts unless 0 <= B < wordwidth, and that when + A is negative then A << B has undefined behavior and A >> B has + implementation-defined behavior, but do not check these other + restrictions. */ +#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ + ((a) < 0 \ + ? (a) < (min) >> (b) \ + : (max) >> (b) < (a)) + + +/* The _GL*_OVERFLOW macros have the same restrictions as the + *_RANGE_OVERFLOW macros, except that they do not assume that operands + (e.g., A and B) have the same type as MIN and MAX. Instead, they assume + that the result (e.g., A + B) has that type. */ +#define _GL_ADD_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? (b) <= (a) + (b) \ + : (b) < 0 ? (a) <= (a) + (b) \ + : (a) + (b) < (b)) +#define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? 1 \ + : (b) < 0 ? (a) - (b) <= (a) \ + : (a) < (b)) +#define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (b) <= (a) + (b) - 1 \ + : (b) < 0 && (a) + (b) <= (a)) +#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ + : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) + +/* Return a nonzero value if A is a mathematical multiple of B, where + A is unsigned, B is negative, and MAX is the maximum value of A's + type. A's type must be the same as (A % B)'s type. Normally (A % + -B == 0) suffices, but things get tricky if -B would overflow. */ +#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ + (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ + ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ + ? (a) \ + : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ + : (a) % - (b)) \ + == 0) + + +/* Integer overflow checks. + + The INT__OVERFLOW macros return 1 if the corresponding C operators + might not yield numerically correct answers due to arithmetic overflow. + They work correctly on all known practical hosts, and do not rely + on undefined behavior due to signed arithmetic overflow. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_OVERFLOW (i, j)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, so the + arguments should not have side effects. + + These macros are tuned for their last argument being a constant. + + Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, + A % B, and A << B would overflow, respectively. */ + +#define INT_ADD_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) +#define INT_SUBTRACT_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) +#define INT_NEGATE_OVERFLOW(a) \ + INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) +#define INT_MULTIPLY_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) +#define INT_DIVIDE_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) +#define INT_REMAINDER_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) +#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ + INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ + _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) + +/* Return 1 if the expression A B would overflow, + where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, + assuming MIN and MAX are the minimum and maximum for the result type. + Arguments should be free of side effects. */ +#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ + op_result_overflow (a, b, \ + _GL_INT_MINIMUM (0 * (b) + (a)), \ + _GL_INT_MAXIMUM (0 * (b) + (a))) + +#endif /* _GL_INTPROPS_H */ diff --git a/grub-core/gnulib/itold.c b/grub-core/gnulib/itold.c new file mode 100644 index 000000000..9aabc7e46 --- /dev/null +++ b/grub-core/gnulib/itold.c @@ -0,0 +1,28 @@ +/* Replacement for 'int' to 'long double' conversion routine. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the 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 + +void +_Qp_itoq (long double *result, int a) +{ + /* Convert from 'int' to 'double', then from 'double' to 'long double'. */ + *result = (double) a; +} diff --git a/grub-core/gnulib/langinfo.in.h b/grub-core/gnulib/langinfo.in.h index 3a92647b9..5388ce624 100644 --- a/grub-core/gnulib/langinfo.in.h +++ b/grub-core/gnulib/langinfo.in.h @@ -1,5 +1,5 @@ /* Substitute for and wrapper around . - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,27 +12,27 @@ GNU 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. */ + along with this program; if not, see . */ /* * POSIX for platforms that lack it or have an incomplete one. * */ -#ifndef _GL_LANGINFO_H +#ifndef _@GUARD_PREFIX@_LANGINFO_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ /* 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 +#ifndef _@GUARD_PREFIX@_LANGINFO_H +#define _@GUARD_PREFIX@_LANGINFO_H #if !@HAVE_LANGINFO_H@ @@ -40,7 +40,10 @@ /* A platform that lacks . */ /* Assume that it also lacks and the nl_item type. */ +# if !GNULIB_defined_nl_item typedef int nl_item; +# define GNULIB_defined_nl_item 1 +# endif /* nl_langinfo items of the LC_CTYPE category */ # define CODESET 10000 @@ -169,5 +172,5 @@ _GL_WARN_ON_USE (nl_langinfo, "nl_langinfo is not portable - " #endif -#endif /* _GL_LANGINFO_H */ -#endif /* _GL_LANGINFO_H */ +#endif /* _@GUARD_PREFIX@_LANGINFO_H */ +#endif /* _@GUARD_PREFIX@_LANGINFO_H */ diff --git a/grub-core/gnulib/localcharset.c b/grub-core/gnulib/localcharset.c index fa2207fe1..953cc1e70 100644 --- a/grub-core/gnulib/localcharset.c +++ b/grub-core/gnulib/localcharset.c @@ -1,6 +1,6 @@ /* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2006, 2008-2010 Free Software Foundation, Inc. + Copyright (C) 2000-2006, 2008-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ /* Written by Bruno Haible . */ @@ -30,11 +29,11 @@ #include #if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET -# define DARWIN7 /* Darwin 7 or newer, i.e. MacOS X 10.3 or newer */ +# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */ #endif #if defined _WIN32 || defined __WIN32__ -# define WIN32_NATIVE +# define WINDOWS_NATIVE #endif #if defined __EMX__ @@ -44,7 +43,7 @@ # endif #endif -#if !defined WIN32_NATIVE +#if !defined WINDOWS_NATIVE # include # if HAVE_LANGINFO_CODESET # include @@ -57,7 +56,7 @@ # define WIN32_LEAN_AND_MEAN # include # endif -#elif defined WIN32_NATIVE +#elif defined WINDOWS_NATIVE # define WIN32_LEAN_AND_MEAN # include #endif @@ -83,7 +82,7 @@ #endif #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ - /* Win32, Cygwin, OS/2, DOS */ + /* Native Windows, Cygwin, OS/2, DOS */ # define ISSLASH(C) ((C) == '/' || (C) == '\\') #endif @@ -123,7 +122,7 @@ get_charset_aliases (void) cp = charset_aliases; if (cp == NULL) { -#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__) +#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__) const char *dir; const char *base = "charset.alias"; char *file_name; @@ -228,8 +227,7 @@ get_charset_aliases (void) { /* Out of memory. */ res_size = 0; - if (old_res_ptr != NULL) - free (old_res_ptr); + free (old_res_ptr); break; } strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); @@ -309,7 +307,7 @@ get_charset_aliases (void) "DECKOREAN" "\0" "EUC-KR" "\0"; # endif -# if defined WIN32_NATIVE || defined __CYGWIN__ +# if defined WINDOWS_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. */ @@ -361,7 +359,7 @@ locale_charset (void) const char *codeset; const char *aliases; -#if !(defined WIN32_NATIVE || defined OS2) +#if !(defined WINDOWS_NATIVE || defined OS2) # if HAVE_LANGINFO_CODESET @@ -408,10 +406,10 @@ locale_charset (void) } } - /* 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). + /* The Windows API 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 @@ -454,12 +452,12 @@ locale_charset (void) # endif -#elif defined WIN32_NATIVE +#elif defined WINDOWS_NATIVE static char buf[2 + 10 + 1]; - /* Woe32 has a function returning the locale's codepage as a number: - GetACP(). + /* The Windows API 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. @@ -544,5 +542,12 @@ locale_charset (void) if (codeset[0] == '\0') codeset = "ASCII"; +#ifdef DARWIN7 + /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8" + (the default codeset) does not work when MB_CUR_MAX is 1. */ + if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX <= 1) + codeset = "ASCII"; +#endif + return codeset; } diff --git a/grub-core/gnulib/localcharset.h b/grub-core/gnulib/localcharset.h index 899b3bae7..c20982986 100644 --- a/grub-core/gnulib/localcharset.h +++ b/grub-core/gnulib/localcharset.h @@ -1,5 +1,5 @@ /* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2003, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2000-2003, 2009-2013 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 @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ #ifndef _LOCALCHARSET_H #define _LOCALCHARSET_H diff --git a/grub-core/gnulib/locale.in.h b/grub-core/gnulib/locale.in.h new file mode 100644 index 000000000..264161a6c --- /dev/null +++ b/grub-core/gnulib/locale.in.h @@ -0,0 +1,216 @@ +/* A POSIX . + Copyright (C) 2007-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#ifdef _GL_ALREADY_INCLUDING_LOCALE_H + +/* Special invocation conventions to handle Solaris header files + (through Solaris 10) when combined with gettext's libintl.h. */ + +#@INCLUDE_NEXT@ @NEXT_LOCALE_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_LOCALE_H + +#define _GL_ALREADY_INCLUDING_LOCALE_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_LOCALE_H@ + +#undef _GL_ALREADY_INCLUDING_LOCALE_H + +#ifndef _@GUARD_PREFIX@_LOCALE_H +#define _@GUARD_PREFIX@_LOCALE_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include + +/* Mac OS X 10.5 defines the locale_t type in . */ +#if @HAVE_XLOCALE_H@ +# 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. */ + +/* The LC_MESSAGES locale category is specified in POSIX, but not in ISO C. + On systems that don't define it, use the same value as GNU libintl. */ +#if !defined LC_MESSAGES +# define LC_MESSAGES 1729 +#endif + +/* Bionic libc's 'struct lconv' is just a dummy. */ +#if @REPLACE_STRUCT_LCONV@ +# define lconv rpl_lconv +struct lconv +{ + /* All 'char *' are actually 'const char *'. */ + + /* Members that depend on the LC_NUMERIC category of the locale. See + */ + + /* Symbol used as decimal point. */ + char *decimal_point; + /* Symbol used to separate groups of digits to the left of the decimal + point. */ + char *thousands_sep; + /* Definition of the size of groups of digits to the left of the decimal + point. */ + char *grouping; + + /* Members that depend on the LC_MONETARY category of the locale. See + */ + + /* Symbol used as decimal point. */ + char *mon_decimal_point; + /* Symbol used to separate groups of digits to the left of the decimal + point. */ + char *mon_thousands_sep; + /* Definition of the size of groups of digits to the left of the decimal + point. */ + char *mon_grouping; + /* Sign used to indicate a value >= 0. */ + char *positive_sign; + /* Sign used to indicate a value < 0. */ + char *negative_sign; + + /* For formatting local currency. */ + /* Currency symbol (3 characters) followed by separator (1 character). */ + char *currency_symbol; + /* Number of digits after the decimal point. */ + char frac_digits; + /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char p_cs_precedes; + /* For values >= 0: Position of the sign. */ + char p_sign_posn; + /* For values >= 0: Placement of spaces between currency symbol, sign, and + number. */ + char p_sep_by_space; + /* For values < 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char n_cs_precedes; + /* For values < 0: Position of the sign. */ + char n_sign_posn; + /* For values < 0: Placement of spaces between currency symbol, sign, and + number. */ + char n_sep_by_space; + + /* For formatting international currency. */ + /* Currency symbol (3 characters) followed by separator (1 character). */ + char *int_curr_symbol; + /* Number of digits after the decimal point. */ + char int_frac_digits; + /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char int_p_cs_precedes; + /* For values >= 0: Position of the sign. */ + char int_p_sign_posn; + /* For values >= 0: Placement of spaces between currency symbol, sign, and + number. */ + char int_p_sep_by_space; + /* For values < 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char int_n_cs_precedes; + /* For values < 0: Position of the sign. */ + char int_n_sign_posn; + /* For values < 0: Placement of spaces between currency symbol, sign, and + number. */ + char int_n_sep_by_space; +}; +#endif + +#if @GNULIB_LOCALECONV@ +# if @REPLACE_LOCALECONV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localeconv +# define localeconv rpl_localeconv +# endif +_GL_FUNCDECL_RPL (localeconv, struct lconv *, (void)); +_GL_CXXALIAS_RPL (localeconv, struct lconv *, (void)); +# else +_GL_CXXALIAS_SYS (localeconv, struct lconv *, (void)); +# endif +_GL_CXXALIASWARN (localeconv); +#elif @REPLACE_STRUCT_LCONV@ +# undef localeconv +# define localeconv localeconv_used_without_requesting_gnulib_module_localeconv +#elif defined GNULIB_POSIXCHECK +# undef localeconv +# if HAVE_RAW_DECL_LOCALECONV +_GL_WARN_ON_USE (localeconv, + "localeconv returns too few information on some platforms - " + "use gnulib module localeconv for portability"); +# endif +#endif + +#if @GNULIB_SETLOCALE@ +# if @REPLACE_SETLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setlocale +# define setlocale rpl_setlocale +# define GNULIB_defined_setlocale 1 +# endif +_GL_FUNCDECL_RPL (setlocale, char *, (int category, const char *locale)); +_GL_CXXALIAS_RPL (setlocale, char *, (int category, const char *locale)); +# else +_GL_CXXALIAS_SYS (setlocale, char *, (int category, const char *locale)); +# endif +_GL_CXXALIASWARN (setlocale); +#elif defined GNULIB_POSIXCHECK +# undef setlocale +# if HAVE_RAW_DECL_SETLOCALE +_GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - " + "use gnulib module setlocale for portability"); +# endif +#endif + +#if @GNULIB_DUPLOCALE@ +# if @REPLACE_DUPLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef duplocale +# define duplocale rpl_duplocale +# endif +_GL_FUNCDECL_RPL (duplocale, locale_t, (locale_t locale) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (duplocale, locale_t, (locale_t locale)); +# else +# if @HAVE_DUPLOCALE@ +_GL_CXXALIAS_SYS (duplocale, locale_t, (locale_t locale)); +# endif +# endif +# if @HAVE_DUPLOCALE@ +_GL_CXXALIASWARN (duplocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef duplocale +# if HAVE_RAW_DECL_DUPLOCALE +_GL_WARN_ON_USE (duplocale, "duplocale is buggy on some glibc systems - " + "use gnulib module duplocale for portability"); +# endif +#endif + +#endif /* _@GUARD_PREFIX@_LOCALE_H */ +#endif /* ! _GL_ALREADY_INCLUDING_LOCALE_H */ +#endif /* _@GUARD_PREFIX@_LOCALE_H */ diff --git a/grub-core/gnulib/localeconv.c b/grub-core/gnulib/localeconv.c new file mode 100644 index 000000000..7c7c77cfd --- /dev/null +++ b/grub-core/gnulib/localeconv.c @@ -0,0 +1,103 @@ +/* Query locale dependent information for formatting numbers. + Copyright (C) 2012-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if HAVE_STRUCT_LCONV_DECIMAL_POINT + +/* Override for platforms where 'struct lconv' lacks the int_p_*, int_n_* + members. */ + +struct lconv * +localeconv (void) +{ + static struct lconv result; +# undef lconv +# undef localeconv + struct lconv *sys_result = localeconv (); + + result.decimal_point = sys_result->decimal_point; + result.thousands_sep = sys_result->thousands_sep; + result.grouping = sys_result->grouping; + result.mon_decimal_point = sys_result->mon_decimal_point; + result.mon_thousands_sep = sys_result->mon_thousands_sep; + result.mon_grouping = sys_result->mon_grouping; + result.positive_sign = sys_result->positive_sign; + result.negative_sign = sys_result->negative_sign; + result.currency_symbol = sys_result->currency_symbol; + result.frac_digits = sys_result->frac_digits; + result.p_cs_precedes = sys_result->p_cs_precedes; + result.p_sign_posn = sys_result->p_sign_posn; + result.p_sep_by_space = sys_result->p_sep_by_space; + result.n_cs_precedes = sys_result->n_cs_precedes; + result.n_sign_posn = sys_result->n_sign_posn; + result.n_sep_by_space = sys_result->n_sep_by_space; + result.int_curr_symbol = sys_result->int_curr_symbol; + result.int_frac_digits = sys_result->int_frac_digits; + result.int_p_cs_precedes = sys_result->p_cs_precedes; + result.int_p_sign_posn = sys_result->p_sign_posn; + result.int_p_sep_by_space = sys_result->p_sep_by_space; + result.int_n_cs_precedes = sys_result->n_cs_precedes; + result.int_n_sign_posn = sys_result->n_sign_posn; + result.int_n_sep_by_space = sys_result->n_sep_by_space; + + return &result; +} + +#else + +/* Override for platforms where 'struct lconv' is a dummy. */ + +# include + +struct lconv * +localeconv (void) +{ + static /*const*/ struct lconv result = + { + /* decimal_point */ ".", + /* thousands_sep */ "", + /* grouping */ "", + /* mon_decimal_point */ "", + /* mon_thousands_sep */ "", + /* mon_grouping */ "", + /* positive_sign */ "", + /* negative_sign */ "", + /* currency_symbol */ "", + /* frac_digits */ CHAR_MAX, + /* p_cs_precedes */ CHAR_MAX, + /* p_sign_posn */ CHAR_MAX, + /* p_sep_by_space */ CHAR_MAX, + /* n_cs_precedes */ CHAR_MAX, + /* n_sign_posn */ CHAR_MAX, + /* n_sep_by_space */ CHAR_MAX, + /* int_curr_symbol */ "", + /* int_frac_digits */ CHAR_MAX, + /* int_p_cs_precedes */ CHAR_MAX, + /* int_p_sign_posn */ CHAR_MAX, + /* int_p_sep_by_space */ CHAR_MAX, + /* int_n_cs_precedes */ CHAR_MAX, + /* int_n_sign_posn */ CHAR_MAX, + /* int_n_sep_by_space */ CHAR_MAX + }; + + return &result; +} + +#endif diff --git a/grub-core/gnulib/malloc.c b/grub-core/gnulib/malloc.c index 4fa38ee41..908735d27 100644 --- a/grub-core/gnulib/malloc.c +++ b/grub-core/gnulib/malloc.c @@ -1,6 +1,6 @@ /* malloc() function that is glibc compatible. - Copyright (C) 1997-1998, 2006-2007, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 1997-1998, 2006-2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,11 +13,11 @@ GNU 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. */ + along with this program; if not, see . */ /* written by Jim Meyering and Bruno Haible */ +#define _GL_USE_STDLIB_ALLOC 1 #include /* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */ #ifdef malloc @@ -28,14 +28,10 @@ # 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. */ diff --git a/grub-core/gnulib/mbrtowc.c b/grub-core/gnulib/mbrtowc.c index 5c2650e95..5ee44aea4 100644 --- a/grub-core/gnulib/mbrtowc.c +++ b/grub-core/gnulib/mbrtowc.c @@ -1,5 +1,5 @@ /* Convert multibyte character to wide character. - Copyright (C) 1999-2002, 2005-2010 Free Software Foundation, Inc. + Copyright (C) 1999-2002, 2005-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify @@ -40,9 +40,6 @@ 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; @@ -54,6 +51,10 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) return (size_t)(-2); /* Here n > 0. */ + + if (pstate == NULL) + pstate = internal_state; + { size_t nstate = pstate[0]; char buf[4]; @@ -91,7 +92,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) /* Here m > 0. */ -# if __GLIBC__ +# if __GLIBC__ || defined __UCLIBC__ /* Work around bug */ mbtowc (NULL, NULL, 0); # endif @@ -127,7 +128,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { const char *encoding = locale_charset (); - if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) { /* Cf. unistr/u8-mblen.c. */ unsigned char c = (unsigned char) p[0]; @@ -184,7 +185,8 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) /* 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 (STREQ_OPT (encoding, + "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)) { if (m == 1) { @@ -207,9 +209,12 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } 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 (STREQ_OPT (encoding, + "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, + "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, + "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)) { if (m == 1) { @@ -220,7 +225,8 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) + if (STREQ_OPT (encoding, + "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) { if (m == 1) { @@ -238,7 +244,8 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) + if (STREQ_OPT (encoding, + "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) { if (m == 1) { @@ -271,7 +278,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) } goto invalid; } - if (STREQ (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) + if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) { if (m == 1) { @@ -321,7 +328,7 @@ mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) 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 MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG if (s == NULL) { pwc = NULL; @@ -334,7 +341,7 @@ rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { static mbstate_t internal_state; - /* Override mbrtowc's internal state. We can not call mbsinit() on the + /* Override mbrtowc's internal state. We cannot call mbsinit() on the hidden internal state, but we can call it on our variable. */ if (ps == NULL) ps = &internal_state; @@ -379,7 +386,16 @@ rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) return ret; } # else - return mbrtowc (pwc, s, n, ps); + { +# if MBRTOWC_NULL_ARG1_BUG + wchar_t dummy; + + if (pwc == NULL) + pwc = &dummy; +# endif + + return mbrtowc (pwc, s, n, ps); + } # endif } diff --git a/grub-core/gnulib/mbsinit.c b/grub-core/gnulib/mbsinit.c index 066ddfe5b..26fbb7fa2 100644 --- a/grub-core/gnulib/mbsinit.c +++ b/grub-core/gnulib/mbsinit.c @@ -1,5 +1,5 @@ /* Test for initial conversion state. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify @@ -22,6 +22,18 @@ #include "verify.h" +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ + +/* On native Windows, 'mbstate_t' is defined as 'int'. */ + +int +mbsinit (const mbstate_t *ps) +{ + return ps == NULL || *ps == 0; +} + +#else + /* Platforms that lack mbsinit() also lack mbrlen(), mbrtowc(), mbsrtowcs() and wcrtomb(), wcsrtombs(). We assume that @@ -43,5 +55,7 @@ mbsinit (const mbstate_t *ps) { const char *pstate = (const char *)ps; - return pstate[0] == 0; + return pstate == NULL || pstate[0] == 0; } + +#endif diff --git a/grub-core/gnulib/mbsrtowcs-impl.h b/grub-core/gnulib/mbsrtowcs-impl.h new file mode 100644 index 000000000..b50e9739b --- /dev/null +++ b/grub-core/gnulib/mbsrtowcs-impl.h @@ -0,0 +1,122 @@ +/* Convert string to wide string. + Copyright (C) 2008-2013 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 . */ + +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/mbsrtowcs-state.c b/grub-core/gnulib/mbsrtowcs-state.c index 35045f657..5a0b8882b 100644 --- a/grub-core/gnulib/mbsrtowcs-state.c +++ b/grub-core/gnulib/mbsrtowcs-state.c @@ -1,5 +1,5 @@ /* Convert string to wide string. - Copyright (C) 2008-2010 Free Software Foundation, Inc. + Copyright (C) 2008-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify @@ -22,7 +22,7 @@ /* 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, + On most systems, putting it into BSS is sufficient. Not so on Mac OS 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 diff --git a/grub-core/gnulib/mbsrtowcs.c b/grub-core/gnulib/mbsrtowcs.c index c577f36f2..116ff493b 100644 --- a/grub-core/gnulib/mbsrtowcs.c +++ b/grub-core/gnulib/mbsrtowcs.c @@ -1,5 +1,5 @@ /* Convert string to wide string. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify @@ -29,108 +29,4 @@ 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); - } -} +#include "mbsrtowcs-impl.h" diff --git a/grub-core/gnulib/mbswidth.c b/grub-core/gnulib/mbswidth.c new file mode 100644 index 000000000..baa4f2757 --- /dev/null +++ b/grub-core/gnulib/mbswidth.c @@ -0,0 +1,199 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "mbswidth.h" + +/* Get MB_CUR_MAX. */ +#include + +#include + +/* Get isprint(). */ +#include + +/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ +#include + +/* Get iswcntrl(). */ +#include + +/* Get INT_MAX. */ +#include + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING. If a non-printable character + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. + With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is + the multibyte analogue of the wcswidth function. */ +int +mbswidth (const char *string, int flags) +{ + return mbsnwidth (string, strlen (string), flags); +} + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING of length NBYTES. If a + non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is + specified, -1 is returned. */ +int +mbsnwidth (const char *string, size_t nbytes, int flags) +{ + const char *p = string; + const char *plimit = p + nbytes; + int width; + + width = 0; + if (MB_CUR_MAX > 1) + { + while (p < plimit) + switch (*p) + { + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + /* These characters are printable ASCII characters. */ + p++; + width++; + break; + case '\0': + if (flags & MBSW_STOP_AT_NUL) + return width; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + do + { + wchar_t wc; + size_t bytes; + int w; + + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + + if (bytes == (size_t) -1) + /* An invalid multibyte sequence was encountered. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p++; + width++; + break; + } + else + return -1; + } + + if (bytes == (size_t) -2) + /* An incomplete multibyte character at the end. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p = plimit; + width++; + break; + } + else + return -1; + } + + if (bytes == 0) + /* A null wide character was encountered. */ + bytes = 1; + + w = wcwidth (wc); + if (w >= 0) + /* A printable multibyte character. */ + { + if (w > INT_MAX - width) + goto overflow; + width += w; + } + else + /* An unprintable multibyte character. */ + if (!(flags & MBSW_REJECT_UNPRINTABLE)) + { + if (!iswcntrl (wc)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } + else + return -1; + + p += bytes; + } + while (! mbsinit (&mbstate)); + } + break; + } + return width; + } + + while (p < plimit) + { + unsigned char c = (unsigned char) *p++; + + if (c == 0 && (flags & MBSW_STOP_AT_NUL)) + return width; + + if (isprint (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + else if (!(flags & MBSW_REJECT_UNPRINTABLE)) + { + if (!iscntrl (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } + else + return -1; + } + return width; + + overflow: + return INT_MAX; +} diff --git a/grub-core/gnulib/mbswidth.h b/grub-core/gnulib/mbswidth.h new file mode 100644 index 000000000..d7207c58f --- /dev/null +++ b/grub-core/gnulib/mbswidth.h @@ -0,0 +1,63 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2004, 2007, 2009-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Avoid a clash of our mbswidth() with a function of the same name defined + in UnixWare 7.1.1 . We need this #include before the #define + below. + However, we don't want to #include on all platforms because + - Tru64 with Desktop Toolkit C has a bug: must be included before + . + - BSD/OS 4.1 has a bug: and must be included before + . */ +#if HAVE_DECL_MBSWIDTH_IN_WCHAR_H +# include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Optional flags to influence mbswidth/mbsnwidth behavior. */ + +/* If this bit is set, return -1 upon finding an invalid or incomplete + character. Otherwise, assume invalid characters have width 1. */ +#define MBSW_REJECT_INVALID 1 + +/* If this bit is set, return -1 upon finding a non-printable character. + Otherwise, assume unprintable characters have width 0 if they are + control characters and 1 otherwise. */ +#define MBSW_REJECT_UNPRINTABLE 2 + +/* If this bit is set \0 is treated as the end of string. + Otherwise it's treated as a normal one column width character. */ +#define MBSW_STOP_AT_NUL 4 + +/* Returns the number of screen columns needed for STRING. */ +#define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ +extern int mbswidth (const char *string, int flags); + +/* Returns the number of screen columns needed for the NBYTES bytes + starting at BUF. */ +extern int mbsnwidth (const char *buf, size_t nbytes, int flags); + + +#ifdef __cplusplus +} +#endif diff --git a/grub-core/gnulib/mbtowc-impl.h b/grub-core/gnulib/mbtowc-impl.h new file mode 100644 index 000000000..767ab397c --- /dev/null +++ b/grub-core/gnulib/mbtowc-impl.h @@ -0,0 +1,44 @@ +/* Convert multibyte character to wide character. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the 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 . */ + +/* We don't need a static internal state, because the encoding is not state + dependent, and when mbrtowc returns (size_t)(-2). we throw the result + away. */ + +int +mbtowc (wchar_t *pwc, const char *s, size_t n) +{ + if (s == NULL) + return 0; + else + { + mbstate_t state; + wchar_t wc; + size_t result; + + memset (&state, 0, sizeof (mbstate_t)); + result = mbrtowc (&wc, s, n, &state); + if (result == (size_t)-1 || result == (size_t)-2) + { + errno = EILSEQ; + return -1; + } + if (pwc != NULL) + *pwc = wc; + return (wc == 0 ? 0 : result); + } +} diff --git a/grub-core/gnulib/mbtowc.c b/grub-core/gnulib/mbtowc.c new file mode 100644 index 000000000..632f2e1db --- /dev/null +++ b/grub-core/gnulib/mbtowc.c @@ -0,0 +1,26 @@ +/* Convert multibyte character to wide character. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + Written by Bruno Haible , 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include +#include + +#include "mbtowc-impl.h" diff --git a/grub-core/gnulib/memchr.c b/grub-core/gnulib/memchr.c index 6c2b2d6c7..3db38a94c 100644 --- a/grub-core/gnulib/memchr.c +++ b/grub-core/gnulib/memchr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2010 +/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2013 Free Software Foundation, Inc. Based on strlen implementation by Torbjorn Granlund (tege@sics.se), diff --git a/grub-core/gnulib/mempcpy.c b/grub-core/gnulib/mempcpy.c index b624d69fd..5582368ed 100644 --- a/grub-core/gnulib/mempcpy.c +++ b/grub-core/gnulib/mempcpy.c @@ -1,5 +1,5 @@ /* Copy memory area and return pointer after last written byte. - Copyright (C) 2003, 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + along with this program; if not, see . */ #include diff --git a/grub-core/gnulib/msvc-inval.c b/grub-core/gnulib/msvc-inval.c new file mode 100644 index 000000000..7e57731eb --- /dev/null +++ b/grub-core/gnulib/msvc-inval.c @@ -0,0 +1,129 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 "msvc-inval.h" + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) + +/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler + declaration. */ +# include + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ +} + +# else + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# if defined _MSC_VER + +static void cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# else + +/* An index to thread-local storage. */ +static DWORD tls_index; +static int tls_initialized /* = 0 */; + +/* Used as a fallback only. */ +static struct gl_msvc_inval_per_thread not_per_thread; + +struct gl_msvc_inval_per_thread * +gl_msvc_inval_current (void) +{ + if (!tls_initialized) + { + tls_index = TlsAlloc (); + tls_initialized = 1; + } + if (tls_index == TLS_OUT_OF_INDEXES) + /* TlsAlloc had failed. */ + return ¬_per_thread; + else + { + struct gl_msvc_inval_per_thread *pointer = + (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); + if (pointer == NULL) + { + /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ + pointer = + (struct gl_msvc_inval_per_thread *) + malloc (sizeof (struct gl_msvc_inval_per_thread)); + if (pointer == NULL) + /* Could not allocate memory. Use the global storage. */ + pointer = ¬_per_thread; + TlsSetValue (tls_index, pointer); + } + return pointer; + } +} + +static void cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); + if (current->restart_valid) + longjmp (current->restart, 1); + else + /* An invalid parameter notification from outside the gnulib code. + Give the caller a chance to intervene. */ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# endif + +# endif + +static int gl_msvc_inval_initialized /* = 0 */; + +void +gl_msvc_inval_ensure_handler (void) +{ + if (gl_msvc_inval_initialized == 0) + { + _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); + gl_msvc_inval_initialized = 1; + } +} + +#endif diff --git a/grub-core/gnulib/msvc-inval.h b/grub-core/gnulib/msvc-inval.h new file mode 100644 index 000000000..dcb0353dc --- /dev/null +++ b/grub-core/gnulib/msvc-inval.h @@ -0,0 +1,222 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 _MSVC_INVAL_H +#define _MSVC_INVAL_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines macros that turn such an invalid parameter notification + into a non-local exit. An error code can then be produced at the target + of this exit. You can thus write code like + + TRY_MSVC_INVAL + { + + } + CATCH_MSVC_INVAL + { + + } + DONE_MSVC_INVAL; + + This entire block expands to a single statement. + + The handling of invalid parameters can be done in three ways: + + * The default way, which is reasonable for programs (not libraries): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [DEFAULT_HANDLING]) + + * The way for libraries that make "hairy" calls (like close(-1), or + fclose(fp) where fileno(fp) is closed, or simply getdtablesize()): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [HAIRY_LIBRARY_HANDLING]) + + * The way for libraries that make no "hairy" calls: + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [SANE_LIBRARY_HANDLING]) + */ + +#define DEFAULT_HANDLING 0 +#define HAIRY_LIBRARY_HANDLING 1 +#define SANE_LIBRARY_HANDLING 2 + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) +/* A native Windows platform with the "invalid parameter handler" concept, + and either DEFAULT_HANDLING or HAIRY_LIBRARY_HANDLING. */ + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING +/* Default handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that just returns. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Handling for hairy libraries. */ + +# include + +/* Gnulib can define its own status codes, as described in the page + "Raising Software Exceptions" on microsoft.com + . + Our status codes are composed of + - 0xE0000000, mandatory for all user-defined status codes, + - 0x474E550, a API identifier ("GNU"), + - 0, 1, 2, ..., used to distinguish different status codes from the + same API. */ +# define STATUS_GNULIB_INVALID_PARAMETER (0xE0000000 + 0x474E550 + 0) + +# if defined _MSC_VER +/* A compiler that supports __try/__except, as described in the page + "try-except statement" on microsoft.com + . + With __try/__except, we can use the multithread-safe exception handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + __try +# define CATCH_MSVC_INVAL \ + __except (GetExceptionCode () == STATUS_GNULIB_INVALID_PARAMETER \ + ? EXCEPTION_EXECUTE_HANDLER \ + : EXCEPTION_CONTINUE_SEARCH) +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Any compiler. + We can only use setjmp/longjmp. */ + +# include + +# ifdef __cplusplus +extern "C" { +# endif + +struct gl_msvc_inval_per_thread +{ + /* The restart that will resume execution at the code between + CATCH_MSVC_INVAL and DONE_MSVC_INVAL. It is enabled only between + TRY_MSVC_INVAL and CATCH_MSVC_INVAL. */ + jmp_buf restart; + + /* Tells whether the contents of restart is valid. */ + int restart_valid; +}; + +/* Ensure that the invalid parameter handler in installed that passes + control to the gl_msvc_inval_restart if it is valid, or raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER otherwise. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +/* Return a pointer to the per-thread data for the current thread. */ +extern struct gl_msvc_inval_per_thread *gl_msvc_inval_current (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + struct gl_msvc_inval_per_thread *msvc_inval_current; \ + gl_msvc_inval_ensure_handler (); \ + msvc_inval_current = gl_msvc_inval_current (); \ + /* First, initialize gl_msvc_inval_restart. */ \ + if (setjmp (msvc_inval_current->restart) == 0) \ + { \ + /* Then, mark it as valid. */ \ + msvc_inval_current->restart_valid = 1; +# define CATCH_MSVC_INVAL \ + /* Execution completed. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; \ + } \ + else \ + { \ + /* Execution triggered an invalid parameter notification. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; +# define DONE_MSVC_INVAL \ + } \ + } \ + while (0) + +# endif + +# endif + +#else +/* A platform that does not need to the invalid parameter handler, + or when SANE_LIBRARY_HANDLING is desired. */ + +/* The braces here avoid GCC warnings like + "warning: suggest explicit braces to avoid ambiguous 'else'". */ +# define TRY_MSVC_INVAL \ + do \ + { \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +#endif + +#endif /* _MSVC_INVAL_H */ diff --git a/grub-core/gnulib/msvc-nothrow.c b/grub-core/gnulib/msvc-nothrow.c new file mode 100644 index 000000000..8d65472a8 --- /dev/null +++ b/grub-core/gnulib/msvc-nothrow.c @@ -0,0 +1,49 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 "msvc-nothrow.h" + +/* Get declarations of the native Windows API functions. */ +#define WIN32_LEAN_AND_MEAN +#include + +#include "msvc-inval.h" + +#undef _get_osfhandle + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +intptr_t +_gl_nothrow_get_osfhandle (int fd) +{ + intptr_t result; + + TRY_MSVC_INVAL + { + result = _get_osfhandle (fd); + } + CATCH_MSVC_INVAL + { + result = (intptr_t) INVALID_HANDLE_VALUE; + } + DONE_MSVC_INVAL; + + return result; +} +#endif diff --git a/grub-core/gnulib/msvc-nothrow.h b/grub-core/gnulib/msvc-nothrow.h new file mode 100644 index 000000000..5f521813d --- /dev/null +++ b/grub-core/gnulib/msvc-nothrow.h @@ -0,0 +1,43 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 _MSVC_NOTHROW_H +#define _MSVC_NOTHROW_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines wrappers that turn such an invalid parameter notification + into an error code. */ + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +/* Get original declaration of _get_osfhandle. */ +# include + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER + +/* Override _get_osfhandle. */ +extern intptr_t _gl_nothrow_get_osfhandle (int fd); +# define _get_osfhandle _gl_nothrow_get_osfhandle + +# endif + +#endif + +#endif /* _MSVC_NOTHROW_H */ diff --git a/grub-core/gnulib/nl_langinfo.c b/grub-core/gnulib/nl_langinfo.c index a3d0d11eb..771c9533a 100644 --- a/grub-core/gnulib/nl_langinfo.c +++ b/grub-core/gnulib/nl_langinfo.c @@ -1,6 +1,6 @@ /* nl_langinfo() replacement: query locale dependent information. - Copyright (C) 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2007-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -97,7 +97,7 @@ rpl_nl_langinfo (nl_item item) strings, appended in memory. */ return "\0\0\0\0\0\0\0\0\0\0"; # endif -# if GNULIB_defined_YESEXPR +# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS case YESEXPR: return "^[yY]"; case NOEXPR: @@ -141,7 +141,8 @@ nl_langinfo (nl_item item) { static char buf[2 + 10 + 1]; - /* Woe32 has a function returning the locale's codepage as a number. */ + /* The Windows API has a function returning the locale's codepage as + a number. */ sprintf (buf, "CP%u", GetACP ()); return buf; } diff --git a/grub-core/gnulib/printf-args.c b/grub-core/gnulib/printf-args.c index 46c03a21e..c27e6bc6b 100644 --- a/grub-core/gnulib/printf-args.c +++ b/grub-core/gnulib/printf-args.c @@ -1,5 +1,5 @@ /* Decomposed printf argument list. - Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2010 Free Software + Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ /* This file can be parametrized with the following macros: ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. diff --git a/grub-core/gnulib/printf-args.h b/grub-core/gnulib/printf-args.h index 2536ebafd..2a9c2a3f8 100644 --- a/grub-core/gnulib/printf-args.h +++ b/grub-core/gnulib/printf-args.h @@ -1,5 +1,5 @@ /* Decomposed printf argument list. - Copyright (C) 1999, 2002-2003, 2006-2007, 2009-2010 Free Software + Copyright (C) 1999, 2002-2003, 2006-2007, 2011-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ #ifndef _PRINTF_ARGS_H #define _PRINTF_ARGS_H @@ -136,10 +135,14 @@ typedef struct } argument; +/* Number of directly allocated arguments (no malloc() needed). */ +#define N_DIRECT_ALLOC_ARGUMENTS 7 + typedef struct { size_t count; argument *arg; + argument direct_alloc_arg[N_DIRECT_ALLOC_ARGUMENTS]; } arguments; diff --git a/grub-core/gnulib/printf-parse.c b/grub-core/gnulib/printf-parse.c index f612beb5b..23cacc1da 100644 --- a/grub-core/gnulib/printf-parse.c +++ b/grub-core/gnulib/printf-parse.c @@ -1,5 +1,5 @@ /* Formatted output to strings. - Copyright (C) 1999-2000, 2002-2003, 2006-2010 Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2002-2003, 2006-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + with this program; if not, see . */ /* This file can be parametrized with the following macros: CHAR_T The element type of the format string. @@ -63,6 +62,9 @@ /* malloc(), realloc(), free(). */ #include +/* memcpy(). */ +#include + /* errno. */ #include @@ -80,23 +82,20 @@ STATIC int PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) { - const CHAR_T *cp = format; /* pointer into format */ + 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 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; + d_allocated = N_DIRECT_ALLOC_DIRECTIVES; + d->dir = d->direct_alloc_dir; a->count = 0; - a_allocated = 0; - a->arg = NULL; + a_allocated = N_DIRECT_ALLOC_ARGUMENTS; + a->arg = a->direct_alloc_arg; #define REGISTER_ARG(_index_,_type_) \ { \ @@ -113,12 +112,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) if (size_overflow_p (memory_size)) \ /* Overflow, would lead to out of memory. */ \ goto out_of_memory; \ - memory = (argument *) (a->arg \ + memory = (argument *) (a->arg != a->direct_alloc_arg \ ? realloc (a->arg, memory_size) \ : malloc (memory_size)); \ if (memory == NULL) \ /* Out of memory. */ \ goto out_of_memory; \ + if (a->arg == a->direct_alloc_arg) \ + memcpy (memory, a->arg, a->count * sizeof (argument)); \ a->arg = memory; \ } \ while (a->count <= n) \ @@ -206,6 +207,13 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) dp->flags |= FLAG_ZERO; cp++; } +#if __GLIBC__ >= 2 && !defined __UCLIBC__ + else if (*cp == 'I') + { + dp->flags |= FLAG_LOCALIZED; + cp++; + } +#endif else break; } @@ -393,7 +401,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) cp++; } #if defined __APPLE__ && defined __MACH__ - /* On MacOS X 10.3, PRIdMAX is defined as "qd". + /* On Mac OS 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') @@ -412,7 +420,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) } #endif #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* On native Win32, PRIdMAX is defined as "I64d". + /* On native Windows, 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') @@ -581,10 +589,14 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) if (size_overflow_p (memory_size)) /* Overflow, would lead to out of memory. */ goto out_of_memory; - memory = (DIRECTIVE *) realloc (d->dir, memory_size); + memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir + ? realloc (d->dir, memory_size) + : malloc (memory_size)); if (memory == NULL) /* Out of memory. */ goto out_of_memory; + if (d->dir == d->direct_alloc_dir) + memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE)); d->dir = memory; } } @@ -603,19 +615,18 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) return 0; error: - if (a->arg) + if (a->arg != a->direct_alloc_arg) free (a->arg); - if (d->dir) + if (d->dir != d->direct_alloc_dir) free (d->dir); errno = EINVAL; return -1; out_of_memory: - if (a->arg) + if (a->arg != a->direct_alloc_arg) free (a->arg); - if (d->dir) + if (d->dir != d->direct_alloc_dir) free (d->dir); -out_of_memory_1: errno = ENOMEM; return -1; } diff --git a/grub-core/gnulib/printf-parse.h b/grub-core/gnulib/printf-parse.h index 0f2b70820..d8474bee1 100644 --- a/grub-core/gnulib/printf-parse.h +++ b/grub-core/gnulib/printf-parse.h @@ -1,5 +1,5 @@ /* Parse printf format string. - Copyright (C) 1999, 2002-2003, 2005, 2007, 2009-2010 Free Software + Copyright (C) 1999, 2002-2003, 2005, 2007, 2010-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ #ifndef _PRINTF_PARSE_H #define _PRINTF_PARSE_H @@ -23,6 +22,10 @@ ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. STATIC Set to 'static' to declare the function static. */ +#if HAVE_FEATURES_H +# include /* for __GLIBC__, __UCLIBC__ */ +#endif + #include "printf-args.h" @@ -33,6 +36,9 @@ #define FLAG_SPACE 8 /* space flag */ #define FLAG_ALT 16 /* # flag */ #define FLAG_ZERO 32 +#if __GLIBC__ >= 2 && !defined __UCLIBC__ +# define FLAG_LOCALIZED 64 /* I flag, uses localized digits */ +#endif /* arg_index value indicating that no argument is consumed. */ #define ARG_NONE (~(size_t)0) @@ -40,6 +46,9 @@ /* xxx_directive: A parsed directive. xxx_directives: A parsed format string. */ +/* Number of directly allocated directives (no malloc() needed). */ +#define N_DIRECT_ALLOC_DIRECTIVES 7 + /* A parsed directive. */ typedef struct { @@ -64,6 +73,7 @@ typedef struct char_directive *dir; size_t max_width_length; size_t max_precision_length; + char_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; } char_directives; @@ -93,6 +103,7 @@ typedef struct u8_directive *dir; size_t max_width_length; size_t max_precision_length; + u8_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; } u8_directives; @@ -120,6 +131,7 @@ typedef struct u16_directive *dir; size_t max_width_length; size_t max_precision_length; + u16_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; } u16_directives; @@ -147,6 +159,7 @@ typedef struct u32_directive *dir; size_t max_width_length; size_t max_precision_length; + u32_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; } u32_directives; diff --git a/grub-core/gnulib/progname.c b/grub-core/gnulib/progname.c index 1415e6a55..0c195e521 100644 --- a/grub-core/gnulib/progname.c +++ b/grub-core/gnulib/progname.c @@ -1,5 +1,5 @@ /* Program name management. - Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software: you can redistribute it and/or modify diff --git a/grub-core/gnulib/progname.h b/grub-core/gnulib/progname.h index 5ba303bd0..b4f3c2778 100644 --- a/grub-core/gnulib/progname.h +++ b/grub-core/gnulib/progname.h @@ -1,5 +1,5 @@ /* Program name management. - Copyright (C) 2001-2004, 2006, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2006, 2009-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software: you can redistribute it and/or modify diff --git a/grub-core/gnulib/rawmemchr.c b/grub-core/gnulib/rawmemchr.c index 0a88777d9..a0298ce64 100644 --- a/grub-core/gnulib/rawmemchr.c +++ b/grub-core/gnulib/rawmemchr.c @@ -1,5 +1,5 @@ /* Searching in a string. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/grub-core/gnulib/realloc.c b/grub-core/gnulib/realloc.c index 053208f37..b51010a62 100644 --- a/grub-core/gnulib/realloc.c +++ b/grub-core/gnulib/realloc.c @@ -1,6 +1,6 @@ /* realloc() function that is glibc compatible. - Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2010 Free Software + Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -18,6 +18,7 @@ /* written by Jim Meyering and Bruno Haible */ +#define _GL_USE_STDLIB_ALLOC 1 #include /* Only the AC_FUNC_REALLOC macro defines 'realloc' already in config.h. */ @@ -34,23 +35,10 @@ # 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. */ diff --git a/grub-core/gnulib/ref-add.sin b/grub-core/gnulib/ref-add.sin index dbb61df3d..112bcdc64 100644 --- a/grub-core/gnulib/ref-add.sin +++ b/grub-core/gnulib/ref-add.sin @@ -1,6 +1,6 @@ # Add this package to a list of references stored in a text file. # -# Copyright (C) 2000, 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 2000, 2009-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ # GNU 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. +# with this program; if not, see . # # Written by Bruno Haible . # diff --git a/grub-core/gnulib/ref-del.sin b/grub-core/gnulib/ref-del.sin index 4c31a6eaf..6f7386847 100644 --- a/grub-core/gnulib/ref-del.sin +++ b/grub-core/gnulib/ref-del.sin @@ -1,6 +1,6 @@ # Remove this package from a list of references stored in a text file. # -# Copyright (C) 2000, 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 2000, 2009-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ # GNU 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. +# with this program; if not, see . # # Written by Bruno Haible . # diff --git a/grub-core/gnulib/regcomp.c b/grub-core/gnulib/regcomp.c index ddea3fb65..596e0cf3e 100644 --- a/grub-core/gnulib/regcomp.c +++ b/grub-core/gnulib/regcomp.c @@ -1,22 +1,21 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. + Copyright (C) 2002-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the 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, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax); @@ -95,20 +94,20 @@ static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, Idx *char_class_alloc, - const unsigned char *class_name, + const char *class_name, reg_syntax_t syntax); #else /* not RE_ENABLE_I18N */ static reg_errcode_t build_equiv_class (bitset_t sbcset, const unsigned char *name); static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const unsigned char *class_name, + const char *class_name, reg_syntax_t syntax); #endif /* not RE_ENABLE_I18N */ static bin_tree_t *build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, + const char *class_name, + const char *extra, bool non_match, reg_errcode_t *err); static bin_tree_t *create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, @@ -207,7 +206,7 @@ static const size_t __re_error_msgid_idx[] = compiles PATTERN (of length LENGTH) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. - Assumes the `allocated' (and perhaps `buffer') and `translate' fields + Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields are set in BUFP on entry. */ #ifdef _LIBC @@ -242,7 +241,7 @@ re_compile_pattern (const char *pattern, size_t length, weak_alias (__re_compile_pattern, re_compile_pattern) #endif -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can +/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ /* This has no initializer because initialized variables in Emacs @@ -274,7 +273,7 @@ int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + re_dfa_t *dfa = bufp->buffer; char *fastmap = bufp->fastmap; memset (fastmap, '\0', sizeof (char) * SBC_MAX); @@ -293,7 +292,7 @@ weak_alias (__re_compile_fastmap, re_compile_fastmap) #endif static inline void -__attribute ((always_inline)) +__attribute__ ((always_inline)) re_set_fastmap (char *fastmap, bool icase, int ch) { fastmap[ch] = 1; @@ -308,7 +307,7 @@ static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap) { - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + re_dfa_t *dfa = bufp->buffer; Idx node_cnt; bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) @@ -440,15 +439,15 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + 'buffer' to the compiled pattern; + 'used' to the length of the compiled pattern; + 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' to an allocated space for the fastmap; - `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. + 'newline_anchor' to REG_NEWLINE being set in CFLAGS; + 'fastmap' to an allocated space for the fastmap; + 'fastmap_accurate' to zero; + 're_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. @@ -551,10 +550,6 @@ regerror (int errcode, const regex_t *_Restrict_ preg, if (BE (errcode < 0 || errcode >= (int) (sizeof (__re_error_msgid_idx) / sizeof (__re_error_msgid_idx[0])), 0)) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ msg = gettext ("unknown regexp error"); else msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); @@ -587,19 +582,23 @@ weak_alias (__regerror, regerror) static const bitset_t utf8_sb_map = { /* Set the first 128 bits. */ -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS +# ifdef __GNUC__ + [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX +# else +# if 4 * BITSET_WORD_BITS < ASCII_CHARS +# error "bitset_word_t is narrower than 32 bits" +# elif 3 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS +# elif 2 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS +# elif 1 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, -# endif +# endif (BITSET_WORD_MAX >> (SBC_MAX % BITSET_WORD_BITS == 0 ? 0 : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) +# endif }; #endif @@ -658,7 +657,7 @@ void regfree (preg) regex_t *preg; { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; if (BE (dfa != NULL, 1)) free_dfa_content (dfa); preg->buffer = NULL; @@ -719,7 +718,7 @@ re_comp (s) + __re_error_msgid_idx[(int) REG_ESPACE]); } - /* Since `re_exec' always passes NULL for the `regs' argument, we + /* Since 're_exec' always passes NULL for the 'regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ @@ -730,7 +729,7 @@ re_comp (s) if (!ret) return NULL; - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ + /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */ return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } @@ -765,7 +764,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length, preg->regs_allocated = REGS_UNALLOCATED; /* Initialize the dfa. */ - dfa = (re_dfa_t *) preg->buffer; + dfa = preg->buffer; if (BE (preg->allocated < sizeof (re_dfa_t), 0)) { /* If zero allocated, but buffer is non-null, try to realloc @@ -874,7 +873,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) calculation below, and for similar doubling calculations elsewhere. And it's <= rather than <, because some of the doubling calculations add 1 afterwards. */ - if (BE (SIZE_MAX / max_object_size / 2 <= pat_len, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2 <= pat_len, 0)) return REG_ESPACE; dfa->nodes_alloc = pat_len + 1; @@ -897,8 +896,10 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) != 0); #else codeset_name = nl_langinfo (CODESET); - if (strcasecmp (codeset_name, "UTF-8") == 0 - || strcasecmp (codeset_name, "UTF8") == 0) + if ((codeset_name[0] == 'U' || codeset_name[0] == 'u') + && (codeset_name[1] == 'T' || codeset_name[1] == 't') + && (codeset_name[2] == 'F' || codeset_name[2] == 'f') + && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0) dfa->is_utf8 = 1; /* We check exhaustively in the loop below if this charset is a @@ -948,9 +949,43 @@ static void internal_function init_word_char (re_dfa_t *dfa) { - int i, j, ch; + int i = 0; + int j; + int ch = 0; dfa->word_ops_used = 1; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + if (BE (dfa->map_notascii == 0, 1)) + { + bitset_word_t bits0 = 0x00000000; + bitset_word_t bits1 = 0x03ff0000; + bitset_word_t bits2 = 0x87fffffe; + bitset_word_t bits3 = 0x07fffffe; + if (BITSET_WORD_BITS == 64) + { + dfa->word_char[0] = bits1 << 31 << 1 | bits0; + dfa->word_char[1] = bits3 << 31 << 1 | bits2; + i = 2; + } + else if (BITSET_WORD_BITS == 32) + { + dfa->word_char[0] = bits0; + dfa->word_char[1] = bits1; + dfa->word_char[2] = bits2; + dfa->word_char[3] = bits3; + i = 4; + } + else + goto general_case; + ch = 128; + + if (BE (dfa->is_utf8, 1)) + { + memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8); + return; + } + } + + general_case: + for (; i < BITSET_WORDS; ++i) for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) if (isalnum (ch) || ch == '_') dfa->word_char[i] |= (bitset_word_t) 1 << j; @@ -961,7 +996,7 @@ init_word_char (re_dfa_t *dfa) static void free_workarea_compile (regex_t *preg) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_storage_t *storage, *next; for (storage = dfa->str_tree_storage; storage; storage = next) { @@ -1145,7 +1180,7 @@ optimize_utf8 (re_dfa_t *dfa) static reg_errcode_t analyze (regex_t *preg) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; reg_errcode_t ret; /* Allocate arrays. */ @@ -1326,7 +1361,7 @@ lower_subexps (void *extra, bin_tree_t *node) static bin_tree_t * lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *body = node->left; bin_tree_t *op, *cls, *tree1, *tree; @@ -1660,7 +1695,7 @@ calc_eclosure (re_dfa_t *dfa) /* If we have already calculated, skip it. */ if (dfa->eclosures[node_idx].nelem != 0) continue; - /* Calculate epsilon closure of `node_idx'. */ + /* Calculate epsilon closure of 'node_idx'. */ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); if (BE (err != REG_NOERROR, 0)) return err; @@ -1710,14 +1745,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) { re_node_set eclosure_elem; Idx edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of `edest' is in progress, + /* If calculating the epsilon closure of 'edest' is in progress, return intermediate result. */ if (dfa->eclosures[edest].nelem == REG_MISSING) { incomplete = true; continue; } - /* If we haven't calculated the epsilon closure of `edest' yet, + /* If we haven't calculated the epsilon closure of 'edest' yet, calculate now. Otherwise use calculated epsilon closure. */ if (dfa->eclosures[edest].nelem == 0) { @@ -1727,11 +1762,11 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) } else eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of `edest'. */ + /* Merge the epsilon closure of 'edest'. */ err = re_node_set_merge (&eclosure, &eclosure_elem); if (BE (err != REG_NOERROR, 0)) return err; - /* If the epsilon closure of `edest' is incomplete, + /* If the epsilon closure of 'edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) { @@ -2093,7 +2128,7 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) /* Entry point of the parser. Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. + If an error occurs, ERR is set by error code, and return NULL. This function build the following tree, from regular expression : CAT / \ @@ -2107,7 +2142,7 @@ static bin_tree_t * parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree, *eor, *root; re_token_t current_token; dfa->syntax = syntax; @@ -2135,13 +2170,13 @@ parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, / \ - ALT means alternative, which represents the operator `|'. */ + ALT means alternative, which represents the operator '|'. */ static bin_tree_t * parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree, *branch = NULL; tree = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) @@ -2183,7 +2218,7 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { bin_tree_t *tree, *expr; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; tree = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; @@ -2194,16 +2229,21 @@ parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, expr = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && expr == NULL, 0)) { + if (tree != NULL) + postorder (tree, free_tree, NULL); return NULL; } if (tree != NULL && expr != NULL) { - tree = create_tree (dfa, tree, expr, CONCAT); - if (tree == NULL) + bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT); + if (newtree == NULL) { + postorder (expr, free_tree, NULL); + postorder (tree, free_tree, NULL); *err = REG_ESPACE; return NULL; } + tree = newtree; } else if (tree == NULL) tree = expr; @@ -2222,7 +2262,7 @@ static bin_tree_t * parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree; switch (token->type) { @@ -2378,8 +2418,8 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, case OP_WORD: case OP_NOTWORD: tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "alnum", - (const unsigned char *) "_", + "alnum", + "_", token->type == OP_NOTWORD, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; @@ -2387,8 +2427,8 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, case OP_SPACE: case OP_NOTSPACE: tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "space", - (const unsigned char *) "", + "space", + "", token->type == OP_NOTSPACE, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; @@ -2438,7 +2478,7 @@ static bin_tree_t * parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, Idx nest, reg_errcode_t *err) { - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; bin_tree_t *tree; size_t cur_nsub; cur_nsub = preg->re_nsub++; @@ -2452,7 +2492,11 @@ parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, { tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) - *err = REG_EPAREN; + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + *err = REG_EPAREN; + } if (BE (*err != REG_NOERROR, 0)) return NULL; } @@ -2530,6 +2574,12 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, *err = REG_BADBR; return NULL; } + + if (BE (RE_DUP_MAX < (end == REG_MISSING ? start : end), 0)) + { + *err = REG_ESIZE; + return NULL; + } } else { @@ -2570,7 +2620,10 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, old_tree = NULL; if (elem->token.type == SUBEXP) - postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); + { + uintptr_t subidx = elem->token.opr.idx; + postorder (elem, mark_opt_subexp, (void *) subidx); + } tree = create_tree (dfa, elem, NULL, (end == REG_MISSING ? OP_DUP_ASTERISK : OP_ALT)); @@ -2616,7 +2669,7 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may + mbcset->range_ends, is a pointer argument since we may update it. */ static reg_errcode_t @@ -2655,7 +2708,6 @@ build_range_exp (const reg_syntax_t syntax, wchar_t wc; wint_t start_wc; wint_t end_wc; - wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] @@ -2669,11 +2721,7 @@ build_range_exp (const reg_syntax_t syntax, ? __btowc (end_ch) : end_elem->opr.wch); if (start_wc == WEOF || end_wc == WEOF) return REG_ECOLLATE; - cmp_buf[0] = start_wc; - cmp_buf[4] = end_wc; - - if (BE ((syntax & RE_NO_EMPTY_RANGES) - && wcscoll (cmp_buf, cmp_buf + 4) > 0, 0)) + else if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_wc > end_wc, 0)) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. @@ -2714,9 +2762,7 @@ build_range_exp (const reg_syntax_t syntax, /* Build the table for single byte characters. */ for (wc = 0; wc < SBC_MAX; ++wc) { - cmp_buf[2] = wc; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) + if (start_wc <= wc && wc <= end_wc) bitset_set (sbcset, wc); } } @@ -2750,11 +2796,12 @@ build_range_exp (const reg_syntax_t syntax, static reg_errcode_t internal_function -build_collating_symbol (bitset_t sbcset, # ifdef RE_ENABLE_I18N - re_charset_t *mbcset, Idx *coll_sym_alloc, -# endif - const unsigned char *name) +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name) +# else /* not RE_ENABLE_I18N */ +build_collating_symbol (bitset_t sbcset, const unsigned char *name) +# endif /* not RE_ENABLE_I18N */ { size_t name_len = strlen ((const char *) name); if (BE (name_len != 1, 0)) @@ -2782,42 +2829,31 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, const int32_t *symb_table; const unsigned char *extra; - /* Local function for parse_bracket_exp used in _LIBC environement. - Seek the collating symbol entry correspondings to NAME. - Return the index of the symbol in the SYMB_TABLE. */ + /* Local function for parse_bracket_exp used in _LIBC environment. + Seek the collating symbol entry corresponding to NAME. + Return the index of the symbol in the SYMB_TABLE, + or -1 if not found. */ auto inline int32_t - __attribute ((always_inline)) - seek_collating_symbol_entry (name, name_len) - const unsigned char *name; - size_t name_len; + __attribute__ ((always_inline)) + seek_collating_symbol_entry (const unsigned char *name, size_t name_len) { - int32_t hash = elem_hash ((const char *) name, name_len); - int32_t elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - int32_t second = hash % (table_size - 2) + 1; + int32_t elem; - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - /* Compare the length of the name. */ - && name_len == extra[symb_table[2 * elem + 1]] - /* Compare the name. */ - && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], - name_len) == 0) - { - /* Yep, this is the entry. */ - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - return elem; + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + int32_t idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + if (/* Compare the length of the name. */ + name_len == extra[idx] + /* Compare the name. */ + && memcmp (name, &extra[idx + 1], name_len) == 0) + /* Yep, this is the entry. */ + return elem; + } + return -1; } /* Local function for parse_bracket_exp used in _LIBC environment. @@ -2825,9 +2861,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, Return the value if succeeded, UINT_MAX otherwise. */ auto inline unsigned int - __attribute ((always_inline)) - lookup_collation_sequence_value (br_elem) - bracket_elem_t *br_elem; + __attribute__ ((always_inline)) + lookup_collation_sequence_value (bracket_elem_t *br_elem) { if (br_elem->type == SB_CHAR) { @@ -2855,7 +2890,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, int32_t elem, idx; elem = seek_collating_symbol_entry (br_elem->opr.name, sym_name_len); - if (symb_table[2 * elem] != 0) + if (elem != -1) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; @@ -2873,7 +2908,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, /* Return the collation sequence value. */ return *(unsigned int *) (extra + idx); } - else if (symb_table[2 * elem] == 0 && sym_name_len == 1) + else if (sym_name_len == 1) { /* No valid character. Match it as a single byte character. */ @@ -2886,20 +2921,17 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, return UINT_MAX; } - /* Local function for parse_bracket_exp used in _LIBC environement. + /* Local function for parse_bracket_exp used in _LIBC environment. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may + mbcset->range_ends, is a pointer argument since we may update it. */ auto inline reg_errcode_t - __attribute ((always_inline)) - build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) - re_charset_t *mbcset; - Idx *range_alloc; - bitset_t sbcset; - bracket_elem_t *start_elem, *end_elem; + __attribute__ ((always_inline)) + build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem) { unsigned int ch; uint32_t start_collseq; @@ -2912,6 +2944,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, 0)) return REG_ERANGE; + /* FIXME: Implement rational ranges here, too. */ start_collseq = lookup_collation_sequence_value (start_elem); end_collseq = lookup_collation_sequence_value (end_elem); /* Check start/end collation sequence values. */ @@ -2970,33 +3003,30 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, return REG_NOERROR; } - /* Local function for parse_bracket_exp used in _LIBC environement. + /* Local function for parse_bracket_exp used in _LIBC environment. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument sinse we may update it. */ + pointer argument since we may update it. */ auto inline reg_errcode_t - __attribute ((always_inline)) - build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) - re_charset_t *mbcset; - Idx *coll_sym_alloc; - bitset_t sbcset; - const unsigned char *name; + __attribute__ ((always_inline)) + build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name) { int32_t elem, idx; size_t name_len = strlen ((const char *) name); if (nrules != 0) { elem = seek_collating_symbol_entry (name, name_len); - if (symb_table[2 * elem] != 0) + if (elem != -1) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; } - else if (symb_table[2 * elem] == 0 && name_len == 1) + else if (name_len == 1) { /* No valid character, treat it as a normal character. */ @@ -3076,6 +3106,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, if (BE (sbcset == NULL, 0)) #endif /* RE_ENABLE_I18N */ { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + re_free (mbcset); +#endif *err = REG_ESPACE; return NULL; } @@ -3235,7 +3269,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, #ifdef RE_ENABLE_I18N mbcset, &char_class_alloc, #endif /* RE_ENABLE_I18N */ - start_elem.opr.name, syntax); + (const char *) start_elem.opr.name, + syntax); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; @@ -3414,7 +3449,7 @@ parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, Build the equivalence class which is represented by NAME. The result are written to MBCSET and SBCSET. EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument sinse we may update it. */ + is a pointer argument since we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N @@ -3445,19 +3480,18 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - idx1 = findidx (&cp); - if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) + idx1 = findidx (&cp, -1); + if (BE (idx1 == 0 || *cp != '\0', 0)) /* This isn't a valid character. */ return REG_ECOLLATE; - /* Build single byte matcing table for this equivalence class. */ - char_buf[1] = (unsigned char) '\0'; + /* Build single byte matching table for this equivalence class. */ len = weights[idx1 & 0xffffff]; for (ch = 0; ch < SBC_MAX; ++ch) { char_buf[0] = ch; cp = char_buf; - idx2 = findidx (&cp); + idx2 = findidx (&cp, 1); /* idx2 = table[ch]; */ @@ -3510,20 +3544,20 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) Build the character class which is represented by NAME. The result are written to MBCSET and SBCSET. CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument sinse we may update it. */ + is a pointer argument since we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, Idx *char_class_alloc, - const unsigned char *class_name, reg_syntax_t syntax) + const char *class_name, reg_syntax_t syntax) #else /* not RE_ENABLE_I18N */ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const unsigned char *class_name, reg_syntax_t syntax) + const char *class_name, reg_syntax_t syntax) #endif /* not RE_ENABLE_I18N */ { int i; - const char *name = (const char *) class_name; + const char *name = class_name; /* In case of REG_ICASE "upper" and "lower" match the both of upper and lower cases. */ @@ -3597,8 +3631,8 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, static bin_tree_t * build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, bool non_match, + const char *class_name, + const char *extra, bool non_match, reg_errcode_t *err) { re_bitset_ptr_t sbcset; @@ -3704,8 +3738,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, } /* This is intended for the expressions like "a{1,3}". - Fetch a number from `input', and return the number. + Fetch a number from 'input', and return the number. Return REG_MISSING if the number field is empty like "{,1}". + Return RE_DUP_MAX + 1 if the number field is too large. Return REG_ERROR if an error occurred. */ static Idx @@ -3724,8 +3759,9 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) num = ((token->type != CHARACTER || c < '0' || '9' < c || num == REG_ERROR) ? REG_ERROR - : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0')); - num = (num > RE_DUP_MAX) ? REG_ERROR : num; + : num == REG_MISSING + ? c - '0' + : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); } return num; } @@ -3799,7 +3835,7 @@ create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node) { - Idx idx = (Idx) (long) extra; + Idx idx = (uintptr_t) extra; if (node->token.type == SUBEXP && node->token.opr.idx == idx) node->token.opt_subexp = 1; diff --git a/grub-core/gnulib/regex.c b/grub-core/gnulib/regex.c index ba0eebee7..5a0332e00 100644 --- a/grub-core/gnulib/regex.c +++ b/grub-core/gnulib/regex.c @@ -1,26 +1,35 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation, - Inc. + Copyright (C) 2002-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the 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, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ -#include +#ifndef _LIBC +# include -/* Make sure noone compiles this code with a C++ compiler. */ +# if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +# endif +# if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wold-style-definition" +# pragma GCC diagnostic ignored "-Wtype-limits" +# endif +#endif + +/* Make sure no one compiles this code with a C++ compiler. */ #if defined __cplusplus && defined _LIBC # error "This is C code, use a C compiler" #endif diff --git a/grub-core/gnulib/regex.h b/grub-core/gnulib/regex.h index 1c139d680..854c6edaf 100644 --- a/grub-core/gnulib/regex.h +++ b/grub-core/gnulib/regex.h @@ -1,23 +1,22 @@ /* Definitions for data structures and routines for the regular expression library. - Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1998, - 2000, 2001, 2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation, - Inc. + Copyright (C) 1985, 1989-1993, 1995-1998, 2000-2003, 2005-2013 Free Software + Foundation, Inc. This file is part of the GNU C Library. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the 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, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ #ifndef _REGEX_H #define _REGEX_H 1 @@ -29,13 +28,10 @@ extern "C" { #endif -/* Define __USE_GNU_REGEX to declare GNU extensions that violate the +/* Define __USE_GNU to declare GNU extensions that violate the POSIX name space rules. */ -#undef __USE_GNU_REGEX -#if (defined _GNU_SOURCE \ - || (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \ - && !defined _XOPEN_SOURCE)) -# define __USE_GNU_REGEX 1 +#ifdef _GNU_SOURCE +# define __USE_GNU 1 #endif #ifdef _REGEX_LARGE_OFFSETS @@ -46,16 +42,6 @@ extern "C" { supported within glibc itself, and glibc users should not define _REGEX_LARGE_OFFSETS. */ -/* The type of the offset of a byte within a string. - For historical reasons POSIX 1003.1-2004 requires that regoff_t be - at least as wide as off_t. However, many common POSIX platforms set - regoff_t to the more-sensible ssize_t and the Open Group has - signalled its intention to change the requirement to be that - regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN - 60 (2005-08-25). We don't know of any hosts where ssize_t or - ptrdiff_t is wider than ssize_t, so ssize_t is safe. */ -typedef ssize_t regoff_t; - /* The type of nonnegative object indexes. Traditionally, GNU regex uses 'int' for these. Code that uses __re_idx_t should work regardless of whether the type is signed. */ @@ -70,10 +56,8 @@ typedef size_t __re_long_size_t; #else -/* Use types that are binary-compatible with the traditional GNU regex - implementation, which mishandles strings longer than INT_MAX. */ - -typedef int regoff_t; +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ typedef int __re_idx_t; typedef unsigned int __re_size_t; typedef unsigned long int __re_long_size_t; @@ -94,8 +78,7 @@ typedef unsigned long int active_reg_t; add or remove a bit, only one other definition need change. */ typedef unsigned long int reg_syntax_t; -#ifdef __USE_GNU_REGEX - +#ifdef __USE_GNU /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ # define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) @@ -162,9 +145,9 @@ typedef unsigned long int reg_syntax_t; If not set, newline is literal. */ # define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) -/* If this bit is set, then `{...}' defines an interval, and \{ and \} +/* If this bit is set, then '{...}' defines an interval, and \{ and \} are literals. - If not set, then `\{...\}' defines an interval. */ + If not set, then '\{...\}' defines an interval. */ # define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. @@ -226,8 +209,7 @@ typedef unsigned long int reg_syntax_t; /* If this bit is set, then no_sub will be set to 1 during re_compile_pattern. */ # define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) - -#endif /* defined __USE_GNU_REGEX */ +#endif /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is @@ -235,7 +217,7 @@ typedef unsigned long int reg_syntax_t; already-compiled regexps. */ extern reg_syntax_t re_syntax_options; -#ifdef __USE_GNU_REGEX +#ifdef __USE_GNU /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ @@ -247,16 +229,19 @@ extern reg_syntax_t re_syntax_options; | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CHAR_CLASSES \ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) # define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INVALID_INTERVAL_ORD) \ + & ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) # define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) + | RE_INTERVALS | RE_NO_GNU_OPS \ + | RE_INVALID_INTERVAL_ORD) # define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ @@ -307,13 +292,12 @@ extern reg_syntax_t re_syntax_options; | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ -#endif /* defined __USE_GNU_REGEX */ - -#ifdef __USE_GNU_REGEX - /* Maximum number of duplicates an interval can allow. POSIX-conforming systems might define this in , but we want our value, so remove any previous define. */ +# ifdef _REGEX_INCLUDE_LIMITS_H +# include +# endif # ifdef RE_DUP_MAX # undef RE_DUP_MAX # endif @@ -321,16 +305,15 @@ extern reg_syntax_t re_syntax_options; /* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored the counter as a 2-byte signed integer. This is no longer true, so RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to - ((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined. + ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined. However, there would be a huge performance problem if someone actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains its historical value. */ # define RE_DUP_MAX (0x7fff) - -#endif /* defined __USE_GNU_REGEX */ +#endif -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ +/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ @@ -350,7 +333,7 @@ extern reg_syntax_t re_syntax_options; #define REG_NOSUB (1 << 3) -/* POSIX `eflags' bits (i.e., information for regexec). */ +/* POSIX 'eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the @@ -368,7 +351,7 @@ extern reg_syntax_t re_syntax_options; /* If any error codes are removed, changed, or added, update the - `__re_error_msgid' table in regcomp.c. */ + '__re_error_msgid' table in regcomp.c. */ typedef enum { @@ -393,11 +376,11 @@ typedef enum /* Error codes we've added. */ _REG_EEND, /* Premature end. */ - _REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + _REG_ESIZE, /* Too large (e.g., repeat count too large). */ _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; -#ifdef _XOPEN_SOURCE +#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K # define REG_ENOSYS _REG_ENOSYS #endif #define REG_NOERROR _REG_NOERROR @@ -418,129 +401,127 @@ typedef enum #define REG_ESIZE _REG_ESIZE #define REG_ERPAREN _REG_ERPAREN -/* struct re_pattern_buffer normally uses member names like `buffer' - that POSIX does not allow. In POSIX mode these members have names - with leading `re_' (e.g., `re_buffer'). */ -#ifdef __USE_GNU_REGEX -# define _REG_RE_NAME(id) id -# define _REG_RM_NAME(id) id -#else -# define _REG_RE_NAME(id) re_##id -# define _REG_RM_NAME(id) rm_##id -#endif - -/* The user can specify the type of the re_translate member by - defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned - char *. This pollutes the POSIX name space, so in POSIX mode just - use unsigned char *. */ -#ifdef __USE_GNU_REGEX -# ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE unsigned char * -# endif -# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE -#else -# define REG_TRANSLATE_TYPE unsigned char * -#endif - /* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ + the pattern compiler, the fields 'buffer', 'allocated', 'fastmap', + and 'translate' can be set. After the pattern has been compiled, + the fields 're_nsub', 'not_bol' and 'not_eol' are available. All + other fields are private to the regex routines. */ -struct re_dfa_t; -typedef struct re_dfa_t re_dfa_t; +#ifndef RE_TRANSLATE_TYPE +# define __RE_TRANSLATE_TYPE unsigned char * +# ifdef __USE_GNU +# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE +# endif +#endif + +#ifdef __USE_GNU +# define __REPB_PREFIX(name) name +#else +# define __REPB_PREFIX(name) __##name +#endif struct re_pattern_buffer { - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are sometimes used as - array indexes. */ - re_dfa_t *_REG_RE_NAME (buffer); + /* Space that holds the compiled pattern. The type + 'struct re_dfa_t' is private and is not declared here. */ + struct re_dfa_t *__REPB_PREFIX(buffer); - /* Number of bytes to which `buffer' points. */ - __re_long_size_t _REG_RE_NAME (allocated); + /* Number of bytes to which 'buffer' points. */ + __re_long_size_t __REPB_PREFIX(allocated); - /* Number of bytes actually used in `buffer'. */ - __re_long_size_t _REG_RE_NAME (used); + /* Number of bytes actually used in 'buffer'. */ + __re_long_size_t __REPB_PREFIX(used); /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t _REG_RE_NAME (syntax); + reg_syntax_t __REPB_PREFIX(syntax); /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ - char *_REG_RE_NAME (fastmap); + char *__REPB_PREFIX(fastmap); /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ - REG_TRANSLATE_TYPE _REG_RE_NAME (translate); + __RE_TRANSLATE_TYPE __REPB_PREFIX(translate); /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see whether or + Well, in truth it's used only in 're_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely - perfectly; see `re_compile_fastmap' (the `duplicate' case). */ - unsigned int _REG_RE_NAME (can_be_null) : 1; + perfectly; see 're_compile_fastmap' (the "duplicate" case). */ + unsigned __REPB_PREFIX(can_be_null) : 1; - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. + /* If REGS_UNALLOCATED, allocate space in the 'regs' structure + for 'max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ -#ifdef __USE_GNU_REGEX +#ifdef __USE_GNU # define REGS_UNALLOCATED 0 # define REGS_REALLOCATE 1 # define REGS_FIXED 2 #endif - unsigned int _REG_RE_NAME (regs_allocated) : 2; + unsigned __REPB_PREFIX(regs_allocated) : 2; - /* Set to zero when `re_compile_pattern' compiles a pattern; set to - one by `re_compile_fastmap' if it updates the fastmap. */ - unsigned int _REG_RE_NAME (fastmap_accurate) : 1; + /* Set to zero when 're_compile_pattern' compiles a pattern; set to + one by 're_compile_fastmap' if it updates the fastmap. */ + unsigned __REPB_PREFIX(fastmap_accurate) : 1; - /* If set, `re_match_2' does not return information about + /* If set, 're_match_2' does not return information about subexpressions. */ - unsigned int _REG_RE_NAME (no_sub) : 1; + unsigned __REPB_PREFIX(no_sub) : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ - unsigned int _REG_RE_NAME (not_bol) : 1; + unsigned __REPB_PREFIX(not_bol) : 1; /* Similarly for an end-of-line anchor. */ - unsigned int _REG_RE_NAME (not_eol) : 1; + unsigned __REPB_PREFIX(not_eol) : 1; /* If true, an anchor at a newline matches. */ - unsigned int _REG_RE_NAME (newline_anchor) : 1; - -/* [[[end pattern_buffer]]] */ + unsigned __REPB_PREFIX(newline_anchor) : 1; }; typedef struct re_pattern_buffer regex_t; +/* Type for byte offsets within the string. POSIX mandates this. */ +#ifdef _REGEX_LARGE_OFFSETS +/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as + ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t + is wider than ssize_t, so ssize_t is safe. */ +typedef ssize_t regoff_t; +#else +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ +typedef int regoff_t; +#endif + + +#ifdef __USE_GNU /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { - __re_size_t _REG_RM_NAME (num_regs); - regoff_t *_REG_RM_NAME (start); - regoff_t *_REG_RM_NAME (end); + __re_size_t num_regs; + regoff_t *start; + regoff_t *end; }; -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#if !defined RE_NREGS && defined __USE_GNU_REGEX -# define RE_NREGS 30 +/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + 're_match_2' returns information about at least this many registers + the first time a 'regs' structure is passed. */ +# ifndef RE_NREGS +# define RE_NREGS 30 +# endif #endif /* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a + 're_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { @@ -550,13 +531,19 @@ typedef struct /* Declarations for routines. */ +#ifdef __USE_GNU /* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ + You can also simply assign to the 're_syntax_options' variable. */ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); /* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ + and syntax given by the global 're_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. + + To free the allocated storage, you must call 'regfree' on BUFFER. + Note that the translate table must either have been initialised by + 'regcomp', with a malloc'ed value, or set to NULL before calling + 'regfree'. */ extern const char *re_compile_pattern (const char *__pattern, size_t __length, struct re_pattern_buffer *__buffer); @@ -578,7 +565,7 @@ extern regoff_t re_search (struct re_pattern_buffer *__buffer, struct re_registers *__regs); -/* Like `re_search', but search in the concatenation of STRING1 and +/* Like 're_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, const char *__string1, __re_idx_t __length1, @@ -588,14 +575,14 @@ extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, __re_idx_t __stop); -/* Like `re_search', but return how many characters in STRING the regexp +/* Like 're_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern regoff_t re_match (struct re_pattern_buffer *__buffer, const char *__string, __re_idx_t __length, __re_idx_t __start, struct re_registers *__regs); -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +/* Relates to 're_match' as 're_search_2' relates to 're_search'. */ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, const char *__string1, __re_idx_t __length1, const char *__string2, __re_idx_t __length2, @@ -606,21 +593,22 @@ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least `NUM_REGS * sizeof + allocated with malloc, and must each be at least 'NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using - BUFFER will allocate its own register data, without freeing the old - data. */ + BUFFER will allocate its own register data, without + freeing the old data. */ extern void re_set_registers (struct re_pattern_buffer *__buffer, struct re_registers *__regs, __re_size_t __num_regs, regoff_t *__starts, regoff_t *__ends); +#endif /* Use GNU */ -#if defined _REGEX_RE_COMP || defined _LIBC +#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_BSD) # ifndef _CRAY /* 4.2 bsd compatibility. */ extern char *re_comp (const char *); @@ -648,7 +636,7 @@ extern int re_exec (const char *); #ifndef _Restrict_arr_ # if ((199901L <= __STDC_VERSION__ \ || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \ - && !__STRICT_ANSI__)) \ + && !defined __STRICT_ANSI__)) \ && !defined __GNUG__) # define _Restrict_arr_ _Restrict_ # else diff --git a/grub-core/gnulib/regex_internal.c b/grub-core/gnulib/regex_internal.c index 98b8d5d21..899b0ae67 100644 --- a/grub-core/gnulib/regex_internal.c +++ b/grub-core/gnulib/regex_internal.c @@ -1,22 +1,21 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. + Copyright (C) 2002-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the 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, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ static void re_string_construct_common (const char *str, Idx len, re_string_t *pstr, @@ -135,9 +134,9 @@ re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) { wint_t *new_wcs; - /* Avoid overflow. */ - size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (BE (SIZE_MAX / max_object_size < new_buf_len, 0)) + /* Avoid overflow in realloc. */ + const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_buf_len, 0)) return REG_ESPACE; new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); @@ -237,13 +236,8 @@ build_wcs_buffer (re_string_t *pstr) else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) + if (BE (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len), 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; @@ -252,6 +246,12 @@ build_wcs_buffer (re_string_t *pstr) wc = pstr->trans[wc]; pstr->cur_state = prev_st; } + else if (BE (mbclen == (size_t) -2, 0)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } /* Write wide character and padding. */ pstr->wcs[byte_idx++] = wc; @@ -334,9 +334,11 @@ build_wcs_upper_buffer (re_string_t *pstr) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } - else if (mbclen == (size_t) -1 || mbclen == 0) + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) { - /* It is an invalid character or '\0'. Just use the byte. */ + /* It is an invalid character, an incomplete character + at the end of the string, or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; pstr->mbs[byte_idx] = ch; /* And also cast it to wide char. */ @@ -449,7 +451,8 @@ build_wcs_upper_buffer (re_string_t *pstr) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } - else if (mbclen == (size_t) -1 || mbclen == 0) + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; @@ -496,8 +499,7 @@ re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) rawbuf_idx < new_raw_idx;) { wchar_t wc2; - Idx remain_len; - remain_len = pstr->len - rawbuf_idx; + Idx remain_len = pstr->raw_len - rawbuf_idx; prev_st = pstr->cur_state; mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, remain_len, &pstr->cur_state); @@ -733,21 +735,21 @@ 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]; + const unsigned char *pp = p; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; + pp = buf; } -#endif /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); - mbclen = __mbrtowc (&wc2, (const char *) p, mlen, + mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, &cur_state); if (raw + offset - p <= mbclen && mbclen < (size_t) -2) @@ -832,7 +834,7 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) } static unsigned char -internal_function __attribute ((pure)) +internal_function __attribute__ ((pure)) re_string_peek_byte_case (const re_string_t *pstr, Idx idx) { int ch; @@ -869,7 +871,7 @@ re_string_peek_byte_case (const re_string_t *pstr, Idx idx) } static unsigned char -internal_function __attribute ((pure)) +internal_function re_string_fetch_byte_case (re_string_t *pstr) { if (BE (!pstr->mbs_allocated, 1)) @@ -972,7 +974,7 @@ re_node_set_alloc (re_node_set *set, Idx size) set->alloc = size; set->nelem = 0; set->elems = re_malloc (Idx, size); - if (BE (set->elems == NULL, 0)) + if (BE (set->elems == NULL, 0) && (MALLOC_0_IS_NONNULL || size != 0)) return REG_ESPACE; return REG_NOERROR; } @@ -1352,7 +1354,7 @@ re_node_set_insert_last (re_node_set *set, Idx elem) Return true if SET1 and SET2 are equivalent. */ static bool -internal_function __attribute ((pure)) +internal_function __attribute__ ((pure)) re_node_set_compare (const re_node_set *set1, const re_node_set *set2) { Idx i; @@ -1367,7 +1369,7 @@ re_node_set_compare (const re_node_set *set1, const re_node_set *set2) /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ static Idx -internal_function __attribute ((pure)) +internal_function __attribute__ ((pure)) re_node_set_contains (const re_node_set *set, Idx elem) { __re_size_t idx, right, mid; @@ -1413,13 +1415,12 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) Idx *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures; re_token_t *new_nodes; - size_t max_object_size = - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - /* Avoid overflows. */ - if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) + /* Avoid overflows in realloc. */ + const size_t max_object_size = MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + sizeof (Idx))); + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_nodes_alloc, 0)) return REG_MISSING; new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); @@ -1442,11 +1443,9 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) dfa->nodes[dfa->nodes_len] = token; dfa->nodes[dfa->nodes_len].constraint = 0; #ifdef RE_ENABLE_I18N - { - int type = token.type; dfa->nodes[dfa->nodes_len].accept_mb = - (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; - } + ((token.type == OP_PERIOD && dfa->mb_cur_max > 1) + || token.type == COMPLEX_BRACKET); #endif dfa->nexts[dfa->nodes_len] = REG_MISSING; re_node_set_init_empty (dfa->edests + dfa->nodes_len); @@ -1454,7 +1453,7 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) return dfa->nodes_len++; } -static inline re_hashval_t +static re_hashval_t internal_function calc_state_hash (const re_node_set *nodes, unsigned int context) { @@ -1551,7 +1550,7 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, && re_node_set_compare (state->entrance_nodes, nodes)) return state; } - /* There are no appropriate state in `dfa', create the new one. */ + /* There are no appropriate state in 'dfa', create the new one. */ new_state = create_cd_newstate (dfa, nodes, context, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; @@ -1580,7 +1579,7 @@ register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, { Idx elem = newstate->nodes.elems[i]; if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) + if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem)) return REG_ESPACE; } @@ -1615,7 +1614,7 @@ free_state (re_dfastate_t *state) re_free (state); } -/* Create the new state which is independ of contexts. +/* Create the new state which is independent of contexts. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * diff --git a/grub-core/gnulib/regex_internal.h b/grub-core/gnulib/regex_internal.h index e5b6679d1..c467b2907 100644 --- a/grub-core/gnulib/regex_internal.h +++ b/grub-core/gnulib/regex_internal.h @@ -1,43 +1,36 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. + Copyright (C) 2002-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the 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, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ #ifndef _REGEX_INTERNAL_H #define _REGEX_INTERNAL_H 1 #include #include -#include #include #include #include #include -#ifndef _LIBC -# include "localcharset.h" -#endif -#if defined HAVE_LOCALE_H || defined _LIBC -# include -#endif - +#include #include #include +#include #include #if defined _LIBC # include @@ -67,7 +60,7 @@ # ifdef _LIBC # undef gettext # define gettext(msgid) \ - INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) + __dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES) # endif #else # define gettext(msgid) (msgid) @@ -79,12 +72,7 @@ # define gettext_noop(String) String #endif -/* For loser systems without the definition. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCSCOLL) || _LIBC +#if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCSCOLL) || _LIBC # define RE_ENABLE_I18N #endif @@ -92,9 +80,6 @@ # define BE(expr, val) __builtin_expect (expr, val) #else # define BE(expr, val) (expr) -# ifdef _LIBC -# define inline -# endif #endif /* Number of ASCII characters. */ @@ -111,22 +96,27 @@ /* Rename to standard API for using out of glibc. */ #ifndef _LIBC +# undef __wctype +# undef __iswctype # define __wctype wctype # define __iswctype iswctype # define __btowc btowc -# define __wcrtomb wcrtomb # define __mbrtowc mbrtowc +# define __wcrtomb wcrtomb # define __regfree regfree # define attribute_hidden #endif /* not _LIBC */ -#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define __attribute(arg) __attribute__ (arg) -#else -# define __attribute(arg) +#if __GNUC__ < 3 + (__GNUC_MINOR__ < 1) +# define __attribute__(arg) #endif typedef __re_idx_t Idx; +#ifdef _REGEX_LARGE_OFFSETS +# define IDX_MAX (SIZE_MAX - 2) +#else +# define IDX_MAX INT_MAX +#endif /* Special return value for failure to match. */ #define REG_MISSING ((Idx) -1) @@ -337,7 +327,7 @@ typedef struct Idx idx; /* for BACK_REF */ re_context_type ctx_type; /* for ANCHOR */ } opr; -#if __GNUC__ >= 2 && !__STRICT_ANSI__ +#if __GNUC__ >= 2 && !defined __STRICT_ANSI__ re_token_type_t type : 8; #else re_token_type_t type; @@ -413,27 +403,29 @@ struct re_string_t }; typedef struct re_string_t re_string_t; + +struct re_dfa_t; +typedef struct re_dfa_t re_dfa_t; + #ifndef _LIBC -# if defined __i386__ && !defined __EMX__ -# define internal_function __attribute ((regparm (3), stdcall)) -# else -# define internal_function -# endif +# define internal_function #endif +#ifndef NOT_IN_libc static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) internal_function; -#ifdef RE_ENABLE_I18N +# ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr) internal_function; static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) - internal_function; -#endif /* RE_ENABLE_I18N */ + internal_function; +# endif /* RE_ENABLE_I18N */ static void build_upper_buffer (re_string_t *pstr) internal_function; static void re_string_translate_buffer (re_string_t *pstr) internal_function; static unsigned int re_string_context_at (const re_string_t *input, Idx idx, int eflags) - internal_function __attribute ((pure)); + internal_function __attribute__ ((pure)); +#endif #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) #define re_string_fetch_byte(pstr) \ @@ -451,7 +443,9 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) -#include +#if defined _LIBC || HAVE_ALLOCA +# include +#endif #ifndef _LIBC # if HAVE_ALLOCA @@ -468,9 +462,18 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, # endif #endif +#ifdef _LIBC +# define MALLOC_0_IS_NONNULL 1 +#elif !defined MALLOC_0_IS_NONNULL +# define MALLOC_0_IS_NONNULL 0 +#endif + #ifndef MAX # define MAX(a,b) ((a) < (b) ? (b) : (a)) #endif +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) @@ -486,8 +489,8 @@ struct bin_tree_t re_token_t token; - /* `node_idx' is the index in dfa->nodes, if `type' == 0. - Otherwise `type' indicate the type of this node. */ + /* 'node_idx' is the index in dfa->nodes, if 'type' == 0. + Otherwise 'type' indicate the type of this node. */ Idx node_idx; }; typedef struct bin_tree_t bin_tree_t; @@ -540,9 +543,9 @@ struct re_dfastate_t struct re_dfastate_t **trtable, **word_trtable; unsigned int context : 4; unsigned int halt : 1; - /* If this state can accept `multi byte'. + /* If this state can accept "multi byte". Note that we refer to multibyte characters, and multi character - collating elements as `multi byte'. */ + collating elements as "multi byte". */ unsigned int accept_mb : 1; /* If this state has backreference node(s). */ unsigned int has_backref : 1; @@ -671,7 +674,7 @@ struct re_dfa_t re_bitset_ptr_t sb_char; int str_tree_storage_idx; - /* number of subexpressions `re_nsub' is in regex_t. */ + /* number of subexpressions 're_nsub' is in regex_t. */ re_hashval_t state_hash_mask; Idx init_node; Idx nbackref; /* The number of backreference in this dfa. */ @@ -728,33 +731,33 @@ typedef struct } bracket_elem_t; -/* Inline functions for bitset_t operation. */ +/* Functions for bitset_t operation. */ -static inline void +static void bitset_set (bitset_t set, Idx i) { set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; } -static inline void +static void bitset_clear (bitset_t set, Idx i) { set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); } -static inline bool +static bool bitset_contain (const bitset_t set, Idx i) { return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; } -static inline void +static void bitset_empty (bitset_t set) { memset (set, '\0', sizeof (bitset_t)); } -static inline void +static void bitset_set_all (bitset_t set) { memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); @@ -763,13 +766,13 @@ bitset_set_all (bitset_t set) ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; } -static inline void +static void bitset_copy (bitset_t dest, const bitset_t src) { memcpy (dest, src, sizeof (bitset_t)); } -static inline void +static void __attribute__ ((unused)) bitset_not (bitset_t set) { int bitset_i; @@ -781,7 +784,7 @@ bitset_not (bitset_t set) & ~set[BITSET_WORDS - 1]); } -static inline void +static void __attribute__ ((unused)) bitset_merge (bitset_t dest, const bitset_t src) { int bitset_i; @@ -789,7 +792,7 @@ bitset_merge (bitset_t dest, const bitset_t src) dest[bitset_i] |= src[bitset_i]; } -static inline void +static void __attribute__ ((unused)) bitset_mask (bitset_t dest, const bitset_t src) { int bitset_i; @@ -798,9 +801,9 @@ bitset_mask (bitset_t dest, const bitset_t src) } #ifdef RE_ENABLE_I18N -/* Inline functions for re_string. */ -static inline int -internal_function __attribute ((pure)) +/* Functions for re_string. */ +static int +internal_function __attribute__ ((pure, unused)) re_string_char_size_at (const re_string_t *pstr, Idx idx) { int byte_idx; @@ -812,8 +815,8 @@ re_string_char_size_at (const re_string_t *pstr, Idx idx) return byte_idx; } -static inline wint_t -internal_function __attribute ((pure)) +static wint_t +internal_function __attribute__ ((pure, unused)) re_string_wchar_at (const re_string_t *pstr, Idx idx) { if (pstr->mb_cur_max == 1) @@ -821,15 +824,15 @@ re_string_wchar_at (const re_string_t *pstr, Idx idx) return (wint_t) pstr->wcs[idx]; } +# ifndef NOT_IN_libc static int -internal_function __attribute ((pure)) +internal_function __attribute__ ((pure, unused)) re_string_elem_size_at (const re_string_t *pstr, Idx idx) { -# ifdef _LIBC +# ifdef _LIBC const unsigned char *p, *extra; const int32_t *table, *indirect; - int32_t tmp; -# include +# include uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) @@ -840,13 +843,14 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx) indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); p = pstr->mbs + idx; - tmp = findidx (&p); + findidx (&p, pstr->len - idx); return p - pstr->mbs - idx; } else -# endif /* _LIBC */ +# endif /* _LIBC */ return 1; } +# endif #endif /* RE_ENABLE_I18N */ #ifndef __GNUC_PREREQ diff --git a/grub-core/gnulib/regexec.c b/grub-core/gnulib/regexec.c index dc449ce52..f632cd47b 100644 --- a/grub-core/gnulib/regexec.c +++ b/grub-core/gnulib/regexec.c @@ -1,22 +1,21 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. + Copyright (C) 2002-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the 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, + The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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. */ + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + . */ static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, Idx n) internal_function; @@ -52,9 +51,8 @@ static regoff_t re_search_stub (struct re_pattern_buffer *bufp, regoff_t range, Idx stop, struct re_registers *regs, bool ret_len) internal_function; -static unsigned int re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - Idx nregs, int regs_allocated) - internal_function; +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, + Idx nregs, int regs_allocated) internal_function; static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) internal_function; static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, @@ -201,7 +199,7 @@ static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, static bool check_node_accept (const re_match_context_t *mctx, const re_token_t *node, Idx idx) internal_function; -static reg_errcode_t extend_buffers (re_match_context_t *mctx) +static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len) internal_function; /* Entry point for POSIX code. */ @@ -210,11 +208,11 @@ static reg_errcode_t extend_buffers (re_match_context_t *mctx) string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. - EFLAGS specifies `execution flags' which affect matching: if + EFLAGS specifies "execution flags" which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. @@ -231,7 +229,7 @@ regexec (preg, string, nmatch, pmatch, eflags) reg_errcode_t err; Idx start, length; #ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + re_dfa_t *dfa = preg->buffer; #endif if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) @@ -366,7 +364,6 @@ weak_alias (__re_search_2, re_search_2) #endif static regoff_t -internal_function re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, Idx length1, const char *string2, Idx length2, @@ -414,7 +411,6 @@ re_search_2_stub (struct re_pattern_buffer *bufp, otherwise the position of the match is returned. */ static regoff_t -internal_function re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, Idx start, regoff_t range, Idx stop, struct re_registers *regs, @@ -426,7 +422,7 @@ re_search_stub (struct re_pattern_buffer *bufp, regoff_t rval; int eflags = 0; #ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + re_dfa_t *dfa = bufp->buffer; #endif Idx last_start = start + range; @@ -478,9 +474,9 @@ re_search_stub (struct re_pattern_buffer *bufp, rval = 0; - /* I hope we needn't fill ther regs with -1's when no match was found. */ + /* I hope we needn't fill their regs with -1's when no match was found. */ if (result != REG_NOERROR) - rval = -1; + rval = result == REG_NOMATCH ? -1 : -2; else if (regs != NULL) { /* If caller wants register contents data back, copy them. */ @@ -506,15 +502,14 @@ re_search_stub (struct re_pattern_buffer *bufp, return rval; } -static unsigned int -internal_function +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, int regs_allocated) { int rval = REGS_REALLOCATE; Idx i; Idx need_regs = nregs + 1; - /* We need one extra element beyond `num_regs' for the `-1' marker GNU code + /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code uses. */ /* Have the register data arrays been allocated? */ @@ -637,7 +632,7 @@ re_exec (s) (0 <= LAST_START && LAST_START <= LENGTH) */ static reg_errcode_t -internal_function __attribute_warn_unused_result__ +__attribute_warn_unused_result__ re_search_internal (const regex_t *preg, const char *string, Idx length, Idx start, Idx last_start, Idx stop, @@ -645,7 +640,7 @@ re_search_internal (const regex_t *preg, int eflags) { reg_errcode_t err; - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + const re_dfa_t *dfa = preg->buffer; Idx left_lim, right_lim; int incr; bool fl_longest_match; @@ -720,7 +715,8 @@ re_search_internal (const regex_t *preg, if (nmatch > 1 || dfa->has_mb_node) { /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0)) + if (BE ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) + <= mctx.input.bufs_len), 0)) { err = REG_ESPACE; goto free_return; @@ -740,7 +736,7 @@ re_search_internal (const regex_t *preg, mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF; - /* Check incrementally whether of not the input string match. */ + /* Check incrementally whether the input string matches. */ incr = (last_start < start) ? -1 : 1; left_lim = (last_start < start) ? last_start : start; right_lim = (last_start < start) ? start : last_start; @@ -922,7 +918,7 @@ re_search_internal (const regex_t *preg, goto free_return; } - /* At last, add the offset to the each registers, since we slided + /* At last, add the offset to each register, since we slid the buffers so that we could assume that the matching starts from 0. */ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) @@ -972,7 +968,7 @@ re_search_internal (const regex_t *preg, } static reg_errcode_t -internal_function __attribute_warn_unused_result__ +__attribute_warn_unused_result__ prune_impossible_nodes (re_match_context_t *mctx) { const re_dfa_t *const dfa = mctx->dfa; @@ -988,7 +984,7 @@ prune_impossible_nodes (re_match_context_t *mctx) halt_node = mctx->last_node; /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) <= match_last, 0)) return REG_ESPACE; sifted_states = re_malloc (re_dfastate_t *, match_last + 1); @@ -1068,7 +1064,7 @@ prune_impossible_nodes (re_match_context_t *mctx) since initial states may have constraints like "\<", "^", etc.. */ static inline re_dfastate_t * -__attribute ((always_inline)) internal_function +__attribute__ ((always_inline)) internal_function acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, Idx idx) { @@ -1106,7 +1102,7 @@ acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, FL_LONGEST_MATCH means we want the POSIX longest matching. If P_MATCH_FIRST is not NULL, and the match fails, it is set to the next place where we may want to try matching. - Note that the matcher assume that the maching starts from the current + Note that the matcher assumes that the matching starts from the current index of the buffer. */ static Idx @@ -1175,11 +1171,12 @@ check_matching (re_match_context_t *mctx, bool fl_longest_match, re_dfastate_t *old_state = cur_state; Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; - if (BE (next_char_idx >= mctx->input.bufs_len, 0) + if ((BE (next_char_idx >= mctx->input.bufs_len, 0) + && mctx->input.bufs_len < mctx->input.len) || (BE (next_char_idx >= mctx->input.valid_len, 0) && mctx->input.valid_len < mctx->input.len)) { - err = extend_buffers (mctx); + err = extend_buffers (mctx, next_char_idx + 1); if (BE (err != REG_NOERROR, 0)) { assert (err == REG_ESPACE); @@ -1436,7 +1433,7 @@ internal_function __attribute_warn_unused_result__ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, bool fl_backtrack) { - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + const re_dfa_t *dfa = preg->buffer; Idx idx, cur_node; re_node_set eps_via_nodes; struct re_fail_stack_t *fs; @@ -1608,21 +1605,21 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, and sift the nodes in each states according to the following rules. Updated state_log will be wrote to STATE_LOG. - Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... + Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if... 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If `a' isn't the LAST_NODE and `a' can't epsilon transit to - the LAST_NODE, we throw away the node `a'. - 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts - string `s' and transit to `b': + If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to + the LAST_NODE, we throw away the node 'a'. + 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts + string 's' and transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node `a'. + away the node 'a'. ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node `a'. + thrown away, we throw away the node 'a'. 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node `a'. + node 'a'. ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node `a'. */ + we throw away the node 'a'. */ #define STATE_NODE_CONTAINS(state,node) \ ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) @@ -1695,11 +1692,11 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, Idx i; /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. + We build the next sifted state on 'cur_dest', and update + 'sifted_states[str_idx]' with 'cur_dest'. Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]' + 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'. + 'cur_src' points the node_set of the old 'state_log[str_idx]' (with the epsilon nodes pre-filtered out). */ for (i = 0; i < cur_src->nelem; i++) { @@ -1712,7 +1709,7 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ + /* If the node may accept "multi byte". */ if (dfa->nodes[prev_node].accept_mb) naccepted = sift_states_iter_mb (mctx, sctx, prev_node, str_idx, sctx->last_str_idx); @@ -1753,12 +1750,13 @@ clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) { Idx top = mctx->state_log_top; - if (next_state_log_idx >= mctx->input.bufs_len + if ((next_state_log_idx >= mctx->input.bufs_len + && mctx->input.bufs_len < mctx->input.len) || (next_state_log_idx >= mctx->input.valid_len && mctx->input.valid_len < mctx->input.len)) { reg_errcode_t err; - err = extend_buffers (mctx); + err = extend_buffers (mctx, next_state_log_idx + 1); if (BE (err != REG_NOERROR, 0)) return err; } @@ -2268,17 +2266,17 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, { const re_dfa_t *const dfa = mctx->dfa; int naccepted; - /* Check the node can accept `multi byte'. */ + /* Check the node can accept "multi byte". */ naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); if (naccepted > 0 && str_idx + naccepted <= max_str_idx && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], dfa->nexts[node_idx])) - /* The node can't accept the `multi byte', or the + /* The node can't accept the "multi byte", or the destination was already thrown away, then the node - could't accept the current input `multi byte'. */ + could't accept the current input "multi byte". */ naccepted = 0; /* Otherwise, it is sure that the node could accept - `naccepted' bytes input. */ + 'naccepted' bytes input. */ return naccepted; } #endif /* RE_ENABLE_I18N */ @@ -2457,7 +2455,7 @@ find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) /* From the node set CUR_NODES, pick up the nodes whose types are OP_OPEN_SUBEXP and which have corresponding back references in the regular expression. And register them to use them later for evaluating the - correspoding back references. */ + corresponding back references. */ static reg_errcode_t internal_function @@ -2568,7 +2566,7 @@ transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) if (naccepted == 0) continue; - /* The node can accepts `naccepted' bytes. */ + /* The node can accepts 'naccepted' bytes. */ dest_idx = re_string_cur_idx (&mctx->input) + naccepted; mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted : mctx->max_mb_elem_len); @@ -2620,7 +2618,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) const re_token_t *node = dfa->nodes + node_idx; re_node_set *new_dest_nodes; - /* Check whether `node' is a backreference or not. */ + /* Check whether 'node' is a backreference or not. */ if (node->type != OP_BACK_REF) continue; @@ -2632,14 +2630,14 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) continue; } - /* `node' is a backreference. + /* 'node' is a backreference. Check the substring which the substring matched. */ bkc_idx = mctx->nbkref_ents; err = get_subexp (mctx, node_idx, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; - /* And add the epsilon closures (which is `new_dest_nodes') of + /* And add the epsilon closures (which is 'new_dest_nodes') of the backreference to appropriate state_log. */ #ifdef DEBUG assert (dfa->nexts[node_idx] != REG_MISSING); @@ -2663,7 +2661,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) dest_state = mctx->state_log[dest_str_idx]; prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add `new_dest_node' to state_log. */ + /* Add 'new_dest_node' to state_log. */ if (dest_state == NULL) { mctx->state_log[dest_str_idx] @@ -2815,7 +2813,7 @@ get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) if (bkref_str_off >= mctx->input.len) break; - err = extend_buffers (mctx); + err = extend_buffers (mctx, bkref_str_off + 1); if (BE (err != REG_NOERROR, 0)) return err; @@ -2937,9 +2935,12 @@ check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, { re_dfastate_t **new_array; Idx old_alloc = path->alloc; - Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1; - if (BE (new_alloc < old_alloc, 0) - || BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) + Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1; + Idx new_alloc; + if (BE (IDX_MAX - old_alloc < incr_alloc, 0)) + return REG_ESPACE; + new_alloc = old_alloc + incr_alloc; + if (BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) return REG_ESPACE; new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); if (BE (new_array == NULL, 0)) @@ -3102,7 +3103,7 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ + /* If the node may accept "multi byte". */ if (dfa->nodes[cur_node].accept_mb) { naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, @@ -3359,7 +3360,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) bitset_word_t elem, mask; bool dests_node_malloced = false; bool dest_states_malloced = false; - Idx ndests; /* Number of the destination states from `state'. */ + Idx ndests; /* Number of the destination states from 'state'. */ re_dfastate_t **trtable; re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; re_node_set follows, *dests_node; @@ -3373,8 +3374,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) } *dests_alloc; /* We build DFA states which corresponds to the destination nodes - from `state'. `dests_node[i]' represents the nodes which i-th - destination state contains, and `dests_ch[i]' represents the + from 'state'. 'dests_node[i]' represents the nodes which i-th + destination state contains, and 'dests_ch[i]' represents the characters which i-th destination state accepts. */ if (__libc_use_alloca (sizeof (struct dests_alloc))) dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); @@ -3388,20 +3389,23 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) dests_node = dests_alloc->dests_node; dests_ch = dests_alloc->dests_ch; - /* Initialize transiton table. */ + /* Initialize transition table. */ state->word_trtable = state->trtable = NULL; - /* At first, group all nodes belonging to `state' into several + /* At first, group all nodes belonging to 'state' into several destinations. */ ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); if (BE (! REG_VALID_NONZERO_INDEX (ndests), 0)) { if (dests_node_malloced) free (dests_alloc); + /* Return false in case of an error, true otherwise. */ if (ndests == 0) { state->trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (BE (state->trtable == NULL, 0)) + return false; return true; } return false; @@ -3591,13 +3595,13 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, reg_errcode_t err; bool ok; Idx i, j, k; - Idx ndests; /* Number of the destinations from `state'. */ + Idx ndests; /* Number of the destinations from 'state'. */ bitset_t accepts; /* Characters a node can accept. */ const re_node_set *cur_nodes = &state->nodes; bitset_empty (accepts); ndests = 0; - /* For all the nodes belonging to `state', */ + /* For all the nodes belonging to 'state', */ for (i = 0; i < cur_nodes->nelem; ++i) { re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; @@ -3640,7 +3644,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, else continue; - /* Check the `accepts' and sift the characters which are not + /* Check the 'accepts' and sift the characters which are not match it the context. */ if (constraint) { @@ -3699,7 +3703,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, } } - /* Then divide `accepts' into DFA states, or create a new + /* Then divide 'accepts' into DFA states, or create a new state. Above, we make sure that accepts is not empty. */ for (j = 0; j < ndests; ++j) { @@ -3712,7 +3716,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) continue; - /* Enumerate the intersection set of this state and `accepts'. */ + /* Enumerate the intersection set of this state and 'accepts'. */ has_intersec = 0; for (k = 0; k < BITSET_WORDS; ++k) has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; @@ -3720,7 +3724,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, if (!has_intersec) continue; - /* Then check if this state is a subset of `accepts'. */ + /* Then check if this state is a subset of 'accepts'. */ not_subset = not_consumed = 0; for (k = 0; k < BITSET_WORDS; ++k) { @@ -3728,8 +3732,8 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; } - /* If this state isn't a subset of `accepts', create a - new group state, which has the `remains'. */ + /* If this state isn't a subset of 'accepts', create a + new group state, which has the 'remains'. */ if (not_subset) { bitset_copy (dests_ch[ndests], remains); @@ -3768,7 +3772,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, } #ifdef RE_ENABLE_I18N -/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. +/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts. Return the number of the bytes the node accepts. STR_IDX is the current index of the input string. @@ -3895,7 +3899,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, const int32_t *table, *indirect; const unsigned char *weights, *extra; const char *collseqwc; - int32_t idx; /* This #include defines a local function! */ # include @@ -3933,6 +3936,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, in_collseq = find_collation_sequence_value (pin, elem_len); } /* match with range expression? */ + /* FIXME: Implement rational ranges here, too. */ for (i = 0; i < cset->nranges; ++i) if (cset->range_starts[i] <= in_collseq && in_collseq <= cset->range_ends[i]) @@ -3953,7 +3957,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - int32_t idx = findidx (&cp); + int32_t idx = findidx (&cp, elem_len); if (idx > 0) for (i = 0; i < cset->nequiv_classes; ++i) { @@ -3984,18 +3988,9 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, # endif /* _LIBC */ { /* match with range expression? */ -#if __GNUC__ >= 2 && ! (__STDC_VERSION__ < 199901L && __STRICT_ANSI__) - wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; -#else - wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - cmp_buf[2] = wc; -#endif for (i = 0; i < cset->nranges; ++i) { - cmp_buf[0] = cset->range_starts[i]; - cmp_buf[4] = cset->range_ends[i]; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) + if (cset->range_starts[i] <= wc && wc <= cset->range_ends[i]) { match_len = char_len; goto check_node_accept_bytes_match; @@ -4065,7 +4060,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) /* Skip the collation sequence value. */ idx += sizeof (uint32_t); /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (extra[idx] + 1); + idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1); /* If we found the entry, return the sequence value. */ if (found) return *(uint32_t *) (extra + idx); @@ -4133,17 +4128,20 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node, static reg_errcode_t internal_function __attribute_warn_unused_result__ -extend_buffers (re_match_context_t *mctx) +extend_buffers (re_match_context_t *mctx, int min_len) { reg_errcode_t ret; re_string_t *pstr = &mctx->input; /* Avoid overflow. */ - if (BE (SIZE_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2 + <= pstr->bufs_len, 0)) return REG_ESPACE; - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + /* Double the lengths of the buffers, but allocate at least MIN_LEN. */ + ret = re_string_realloc_buffers (pstr, + MAX (min_len, + MIN (pstr->len, pstr->bufs_len * 2))); if (BE (ret != REG_NOERROR, 0)) return ret; @@ -4206,7 +4204,7 @@ match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) size_t max_object_size = MAX (sizeof (struct re_backref_cache_entry), sizeof (re_sub_match_top_t *)); - if (BE (SIZE_MAX / max_object_size < n, 0)) + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n, 0)) return REG_ESPACE; mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); diff --git a/grub-core/gnulib/size_max.h b/grub-core/gnulib/size_max.h index 56d5a9b1c..5f3312404 100644 --- a/grub-core/gnulib/size_max.h +++ b/grub-core/gnulib/size_max.h @@ -1,5 +1,5 @@ /* size_max.h -- declare SIZE_MAX through system headers - Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2013 Free Software Foundation, Inc. Written by Simon Josefsson. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ #ifndef GNULIB_SIZE_MAX_H #define GNULIB_SIZE_MAX_H diff --git a/grub-core/gnulib/sleep.c b/grub-core/gnulib/sleep.c index 213e5bd29..4c97d7dfa 100644 --- a/grub-core/gnulib/sleep.c +++ b/grub-core/gnulib/sleep.c @@ -1,5 +1,5 @@ /* Pausing execution of the current thread. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2007. This program is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ sleep (unsigned int seconds) unsigned int remaining; /* Sleep for 1 second many times, because - 1. Sleep is not interruptiple by Ctrl-C, + 1. Sleep is not interruptible by Ctrl-C, 2. we want to avoid arithmetic overflow while multiplying with 1000. */ for (remaining = seconds; remaining > 0; remaining--) Sleep (1000); @@ -50,13 +50,14 @@ sleep (unsigned int seconds) /* 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. */ + garbage answer. Similarly, Linux 2.6.9 with glibc 2.3.4 has a too + small return value when asked to sleep more than 24.85 days. */ 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; + verify (UINT_MAX / 24 / 24 / 60 / 60); + const unsigned int limit = 24 * 24 * 60 * 60; while (limit < seconds) { unsigned int result; diff --git a/grub-core/gnulib/stdalign.in.h b/grub-core/gnulib/stdalign.in.h new file mode 100644 index 000000000..c3a67321b --- /dev/null +++ b/grub-core/gnulib/stdalign.in.h @@ -0,0 +1,90 @@ +/* A substitute for ISO C11 . + + Copyright 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 and Bruno Haible. */ + +#ifndef _GL_STDALIGN_H +#define _GL_STDALIGN_H + +/* ISO C11 for platforms that lack it. + + References: + ISO C11 (latest free draft + ) + sections 6.5.3.4, 6.7.5, 7.15. + C++11 (latest free draft + ) + section 18.10. */ + +/* alignof (TYPE), also known as _Alignof (TYPE), yields the alignment + requirement of a structure member (i.e., slot or field) that is of + type TYPE, as an integer constant expression. + + This differs from GCC's __alignof__ operator, which can yield a + better-performing alignment for an object of that type. For + example, on x86 with GCC, __alignof__ (double) and __alignof__ + (long long) are 8, whereas alignof (double) and alignof (long long) + are 4 unless the option '-malign-double' is used. + + The result cannot be used as a value for an 'enum' constant, if you + want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#include +#if defined __cplusplus + template struct __alignof_helper { char __a; __t __b; }; +# define _Alignof(type) offsetof (__alignof_helper, __b) +#else +# define _Alignof(type) offsetof (struct { char __a; type __b; }, __b) +#endif +#define alignof _Alignof +#define __alignof_is_defined 1 + +/* alignas (A), also known as _Alignas (A), aligns a variable or type + to the alignment A, where A is an integer constant expression. For + example: + + int alignas (8) foo; + struct s { int a; int alignas (8) bar; }; + + aligns the address of FOO and the offset of BAR to be multiples of 8. + + A should be a power of two that is at least the type's alignment + and at most the implementation's alignment limit. This limit is + 2**28 on typical GNUish hosts, and 2**13 on MSVC. To be portable + to MSVC through at least version 10.0, A should be an integer + constant, as MSVC does not support expressions such as 1 << 3. + To be portable to Sun C 5.11, do not align auto variables to + anything stricter than their default alignment. + + The following C11 requirements are not supported here: + + - If A is zero, alignas has no effect. + - alignas can be used multiple times; the strictest one wins. + - alignas (TYPE) is equivalent to alignas (alignof (TYPE)). + + */ + +#if __GNUC__ || __IBMC__ || __IBMCPP__ || 0x5110 <= __SUNPRO_C +# define _Alignas(a) __attribute__ ((__aligned__ (a))) +#elif 1300 <= _MSC_VER +# define _Alignas(a) __declspec (align (a)) +#endif +#ifdef _Alignas +# define alignas _Alignas +# define __alignas_is_defined 1 +#endif + +#endif /* _GL_STDALIGN_H */ diff --git a/grub-core/gnulib/stdbool.in.h b/grub-core/gnulib/stdbool.in.h index 574c281a8..7c1577277 100644 --- a/grub-core/gnulib/stdbool.in.h +++ b/grub-core/gnulib/stdbool.in.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2003, 2006-2010 Free Software Foundation, Inc. +/* Copyright (C) 2001-2003, 2006-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2001. This program is free software; you can redistribute it and/or modify @@ -12,8 +12,7 @@ GNU 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. */ + along with this program; if not, see . */ #ifndef _GL_STDBOOL_H #define _GL_STDBOOL_H @@ -67,24 +66,19 @@ # 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__) +#ifdef __cplusplus +# define _Bool bool +# define bool bool +#else +# if 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@ +# if !@HAVE__BOOL@ typedef bool _Bool; -# endif -#else -# if !defined __GNUC__ +# 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 @@ -104,19 +98,35 @@ typedef bool _Bool; "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 +# define _Bool signed char +# else /* With this compiler, trust the _Bool type if the compiler has it. */ -# if !@HAVE__BOOL@ +# if !@HAVE__BOOL@ + /* For the sake of symbolic names in gdb, 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 then + values of type '_Bool' might 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 add a negative value to the + enum; this ensures that '_Bool' promotes to 'int'. */ typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; +# endif # endif # endif +# define bool _Bool #endif -#define bool _Bool /* The other macros must be usable in preprocessor directives. */ -#define false 0 -#define true 1 +#ifdef __cplusplus +# define false false +# define true true +#else +# define false 0 +# define true 1 +#endif + #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 index 08778a233..40f0536aa 100644 --- a/grub-core/gnulib/stddef.in.h +++ b/grub-core/gnulib/stddef.in.h @@ -1,6 +1,6 @@ /* A substitute for POSIX 2008 , for platforms that have issues. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ /* Written by Eric Blake. */ @@ -26,6 +25,7 @@ #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ #if defined __need_wchar_t || defined __need_size_t \ || defined __need_ptrdiff_t || defined __need_NULL \ @@ -37,9 +37,9 @@ 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) +# if !(defined _@GUARD_PREFIX@_STDDEF_H && defined _GL_STDDEF_WINT_T) # ifdef __need_wint_t -# undef _GL_STDDEF_H +# undef _@GUARD_PREFIX@_STDDEF_H # define _GL_STDDEF_WINT_T # endif # @INCLUDE_NEXT@ @NEXT_STDDEF_H@ @@ -48,14 +48,14 @@ #else /* Normal invocation convention. */ -# ifndef _GL_STDDEF_H +# ifndef _@GUARD_PREFIX@_STDDEF_H /* The include_next requires a split double-inclusion guard. */ # @INCLUDE_NEXT@ @NEXT_STDDEF_H@ -# ifndef _GL_STDDEF_H -# define _GL_STDDEF_H +# ifndef _@GUARD_PREFIX@_STDDEF_H +# define _@GUARD_PREFIX@_STDDEF_H /* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ #if @REPLACE_NULL@ @@ -81,6 +81,6 @@ # define wchar_t int #endif -# endif /* _GL_STDDEF_H */ -# endif /* _GL_STDDEF_H */ +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +# endif /* _@GUARD_PREFIX@_STDDEF_H */ #endif /* __need_XXX */ diff --git a/grub-core/gnulib/stdint.in.h b/grub-core/gnulib/stdint.in.h index 5da5f1788..2db8b2e37 100644 --- a/grub-core/gnulib/stdint.in.h +++ b/grub-core/gnulib/stdint.in.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2002, 2004-2010 Free Software Foundation, Inc. +/* Copyright (C) 2001-2002, 2004-2013 Free Software Foundation, Inc. Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. This file is part of gnulib. @@ -13,19 +13,19 @@ GNU 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. */ + along with this program; if not, see . */ /* * ISO C 99 for platforms that lack it. * */ -#ifndef _GL_STDINT_H +#ifndef _@GUARD_PREFIX@_STDINT_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ /* When including a system file that in turn includes , use the system , not our substitute. This avoids @@ -33,6 +33,16 @@ . */ #define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H +/* On Android (Bionic libc), includes this file before + having defined 'time_t'. Therefore in this case avoid including + other system header files; just include the system's . + Ideally we should test __BIONIC__ here, but it is only defined after + has been included; hence test __ANDROID__ instead. */ +#if defined __ANDROID__ \ + && defined _SYS_TYPES_H_ && !defined __need_size_t +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#else + /* 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 @@ -48,28 +58,40 @@ diagnostics. */ # define __STDINT_H__ # endif + + /* Some pre-C++11 implementations need this. */ +# ifdef __cplusplus +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif +# 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. + _@GUARD_PREFIX@_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 +#if ! defined _@GUARD_PREFIX@_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H +#define _@GUARD_PREFIX@_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 + Mac OS 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. */ +/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX, + LONG_MIN, LONG_MAX, ULONG_MAX. */ #include #if @HAVE_INTTYPES_H@ @@ -92,7 +114,7 @@ #undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H -/* Minimum and maximum values for a integer type under the usual assumption. +/* Minimum and maximum values for an integer type under the usual assumption. Return an unspecified value if BITS == 0, adding a check to pacify picky compilers. */ @@ -107,6 +129,8 @@ warnings in the signed case. */ \ ((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) +#if !GNULIB_defined_stdint_types + /* 7.18.1.1. Exact-width integer types */ /* Here we assume a standard architecture where the hardware integer @@ -133,40 +157,54 @@ typedef unsigned int gl_uint32_t; #define int32_t gl_int32_t #define uint32_t gl_uint32_t +/* If the system defines INT64_MAX, assume int64_t works. That way, + if the underlying platform defines int64_t to be a 64-bit long long + int, the code below won't mistakenly define it to be a 64-bit long + int, which would mess up C++ name mangling. We must use #ifdef + rather than #if, to avoid an error with HP-UX 10.20 cc. */ + +#ifdef INT64_MAX +# define GL_INT64_T +#else /* 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 +# 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 +# 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 +# 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 +# define int64_t gl_int64_t +# define GL_INT64_T +# endif #endif -#if ULONG_MAX >> 31 >> 31 >> 1 == 1 -# undef uint64_t +#ifdef UINT64_MAX +# define GL_UINT64_T +#else +# 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 +# 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 +# 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 +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# endif #endif /* Avoid collision with Solaris 2.5.1 etc. */ @@ -209,8 +247,9 @@ typedef unsigned long long int gl_uint64_t; /* 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. */ + are taken from the same list of types. The following code normally + uses types consistent with glibc, as that lessens the chance of + incompatibility with older GNU hosts. */ #undef int_fast8_t #undef uint_fast8_t @@ -220,12 +259,21 @@ typedef unsigned long long int gl_uint64_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 signed char gl_int_fast8_t; +typedef unsigned char gl_uint_fast8_t; + +#ifdef __sun +/* Define types compatible with SunOS 5.10, so that code compiled under + earlier SunOS versions works with code compiled under SunOS 5.10. */ +typedef int gl_int_fast32_t; +typedef unsigned int gl_uint_fast32_t; +#else typedef long int gl_int_fast32_t; typedef unsigned long int gl_uint_fast32_t; +#endif +typedef gl_int_fast32_t gl_int_fast16_t; +typedef gl_uint_fast32_t gl_uint_fast16_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 @@ -253,37 +301,49 @@ typedef unsigned long int gl_uintptr_t; /* 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 +/* If the system defines INTMAX_MAX, assume that intmax_t works, and + similarly for UINTMAX_MAX and uintmax_t. This avoids problems with + assuming one type where another is used by the system. */ + +#ifndef INTMAX_MAX +# undef INTMAX_C +# 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 +# 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 +# define intmax_t gl_intmax_t +# endif #endif -#undef uintmax_t -#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +#ifndef UINTMAX_MAX +# undef UINTMAX_C +# 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 +# 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 +# define uintmax_t gl_uintmax_t +# endif #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]; +typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) + ? 1 : -1]; + +#define GNULIB_defined_stdint_types 1 +#endif /* !GNULIB_defined_stdint_types */ /* 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 @@ -310,17 +370,14 @@ typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - #define INT32_MAX 2147483647 #define UINT32_MAX 4294967295U -#undef INT64_MIN -#undef INT64_MAX -#ifdef GL_INT64_T +#if defined GL_INT64_T && ! defined INT64_MAX /* 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 +#if defined GL_UINT64_T && ! defined UINT64_MAX # define UINT64_MAX UINTMAX_C (18446744073709551615) #endif @@ -372,23 +429,29 @@ typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - #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 +#define INT_FAST8_MIN SCHAR_MIN +#define INT_FAST8_MAX SCHAR_MAX +#define UINT_FAST8_MAX UCHAR_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 +#define INT_FAST16_MIN INT_FAST32_MIN +#define INT_FAST16_MAX INT_FAST32_MAX +#define UINT_FAST16_MAX UINT_FAST32_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 +#ifdef __sun +# define INT_FAST32_MIN INT_MIN +# define INT_FAST32_MAX INT_MAX +# define UINT_FAST32_MAX UINT_MAX +#else +# define INT_FAST32_MIN LONG_MIN +# define INT_FAST32_MAX LONG_MAX +# define UINT_FAST32_MAX ULONG_MAX +#endif #undef INT_FAST64_MIN #undef INT_FAST64_MAX @@ -413,21 +476,23 @@ typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - /* 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 +#ifndef INTMAX_MAX +# undef INTMAX_MIN +# 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 #endif -#undef UINTMAX_MAX -#ifdef UINT64_MAX -# define UINTMAX_MAX UINT64_MAX -#else -# define UINTMAX_MAX UINT32_MAX +#ifndef UINTMAX_MAX +# ifdef UINT64_MAX +# define UINTMAX_MAX UINT64_MAX +# else +# define UINTMAX_MAX UINT32_MAX +# endif #endif /* 7.18.3. Limits of other integer types */ @@ -475,10 +540,16 @@ typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - /* 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 + 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) +#if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) + /* BSD/OS 4.0.1 has a bug: , and must be + included before . */ +# include +# include +# include # define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H # include # undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H @@ -498,12 +569,8 @@ typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - #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 */ @@ -544,25 +611,26 @@ typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - /* 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 +#ifndef 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 #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 +#ifndef 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 -#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */ - -#endif /* _GL_STDINT_H */ -#endif /* !defined _GL_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ +#endif /* _@GUARD_PREFIX@_STDINT_H */ +#endif /* !(defined __ANDROID__ && ...) */ +#endif /* !defined _@GUARD_PREFIX@_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/grub-core/gnulib/stdio-write.c b/grub-core/gnulib/stdio-write.c deleted file mode 100644 index a6a0eb143..000000000 --- a/grub-core/gnulib/stdio-write.c +++ /dev/null @@ -1,148 +0,0 @@ -/* POSIX compatible FILE stream write function. - Copyright (C) 2008-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -/* Replace these functions only if module 'sigpipe' is requested. */ -#if GNULIB_SIGPIPE - -/* On native Windows platforms, SIGPIPE does not exist. When write() is - called on a pipe with no readers, WriteFile() fails with error - GetLastError() = ERROR_NO_DATA, and write() in consequence fails with - error EINVAL. This write() function is at the basis of the function - which flushes the buffer of a FILE stream. */ - -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - -# include -# include -# include - -# define WIN32_LEAN_AND_MEAN /* avoid including junk */ -# include - -# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ - if (ferror (stream)) \ - return (EXPRESSION); \ - else \ - { \ - RETTYPE ret; \ - SetLastError (0); \ - ret = (EXPRESSION); \ - if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream)) \ - { \ - int fd = fileno (stream); \ - if (fd >= 0 \ - && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\ - { \ - /* Try to raise signal SIGPIPE. */ \ - raise (SIGPIPE); \ - /* If it is currently blocked or ignored, change errno from \ - EINVAL to EPIPE. */ \ - errno = EPIPE; \ - } \ - } \ - return ret; \ - } - -# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ -int -printf (const char *format, ...) -{ - int retval; - va_list args; - - va_start (args, format); - retval = vfprintf (stdout, format, args); - va_end (args); - - return retval; -} -# endif - -# if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */ -int -fprintf (FILE *stream, const char *format, ...) -{ - int retval; - va_list args; - - va_start (args, format); - retval = vfprintf (stream, format, args); - va_end (args); - - return retval; -} -# endif - -# if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */ -int -vprintf (const char *format, va_list args) -{ - return vfprintf (stdout, format, args); -} -# endif - -# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */ -int -vfprintf (FILE *stream, const char *format, va_list args) -#undef vfprintf -{ - CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF) -} -# endif - -int -putchar (int c) -{ - return fputc (c, stdout); -} - -int -fputc (int c, FILE *stream) -#undef fputc -{ - CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF) -} - -int -fputs (const char *string, FILE *stream) -#undef fputs -{ - CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF) -} - -int -puts (const char *string) -#undef puts -{ - FILE *stream = stdout; - CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF) -} - -size_t -fwrite (const void *ptr, size_t s, size_t n, FILE *stream) -#undef fwrite -{ - CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n) -} - -# endif -#endif diff --git a/grub-core/gnulib/stdio.in.h b/grub-core/gnulib/stdio.in.h index a8b00c617..e1d28cebf 100644 --- a/grub-core/gnulib/stdio.in.h +++ b/grub-core/gnulib/stdio.in.h @@ -1,6 +1,6 @@ /* A GNU-like . - Copyright (C) 2004, 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2004, 2007-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,47 +13,104 @@ GNU 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. */ + along with this program; if not, see . */ #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ -#if defined __need_FILE || defined __need___FILE -/* Special invocation convention inside glibc header files. */ +#if defined __need_FILE || defined __need___FILE || defined _GL_ALREADY_INCLUDING_STDIO_H +/* Special invocation convention: + - Inside glibc header files. + - On OSF/1 5.1 we have a sequence of nested includes + -> -> -> -> + -> -> -> . + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ #@INCLUDE_NEXT@ @NEXT_STDIO_H@ #else /* Normal invocation convention. */ -#ifndef _GL_STDIO_H +#ifndef _@GUARD_PREFIX@_STDIO_H + +#define _GL_ALREADY_INCLUDING_STDIO_H /* The include_next requires a split double-inclusion guard. */ #@INCLUDE_NEXT@ @NEXT_STDIO_H@ -#ifndef _GL_STDIO_H -#define _GL_STDIO_H +#undef _GL_ALREADY_INCLUDING_STDIO_H + +#ifndef _@GUARD_PREFIX@_STDIO_H +#define _@GUARD_PREFIX@_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. */ +/* Get off_t and ssize_t. Needed on many systems, including glibc 2.8 + and eglibc 2.11.2. + May also define off_t to a 64-bit type on native Windows. */ #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 + We enable _GL_ATTRIBUTE_FORMAT 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 +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_printf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF, + except that it indicates to GCC that the supported format string directives + are the ones of the system printf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument)) + +/* _GL_ATTRIBUTE_FORMAT_SCANF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_scanf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_SCANF, + except that it indicates to GCC that the supported format string directives + are the ones of the system scanf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) + +/* Solaris 10 declares renameat in , not in . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && defined __sun \ + && ! defined __GLIBC__ +# include #endif @@ -74,13 +131,13 @@ # define dprintf rpl_dprintf # endif _GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_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_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((2))); # endif _GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *format, ...)); @@ -113,6 +170,26 @@ _GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - " "use gnulib module fclose for portable POSIX compliance"); #endif +#if @GNULIB_FDOPEN@ +# if @REPLACE_FDOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopen +# define fdopen rpl_fdopen +# endif +_GL_FUNCDECL_RPL (fdopen, FILE *, (int fd, const char *mode) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fdopen, FILE *, (int fd, const char *mode)); +# else +_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode)); +# endif +_GL_CXXALIASWARN (fdopen); +#elif defined GNULIB_POSIXCHECK +# undef fdopen +/* Assume fdopen is always declared. */ +_GL_WARN_ON_USE (fdopen, "fdopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fdopen for portability"); +#endif + #if @GNULIB_FFLUSH@ /* Flush all pending data on STREAM according to POSIX rules. Both output and seekable input streams are supported. @@ -137,12 +214,33 @@ _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; besides, C11 - removed it. */ -#undef gets -#if HAVE_RAW_DECL_GETS -_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); +#if @GNULIB_FGETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgetc +# define fgetc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgetc, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (fgetc); +#endif + +#if @GNULIB_FGETS@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgets +# define fgets rpl_fgets +# endif +_GL_FUNCDECL_RPL (fgets, char *, (char *s, int n, FILE *stream) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (fgets, char *, (char *s, int n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgets, char *, (char *s, int n, FILE *stream)); +# endif +_GL_CXXALIASWARN (fgets); #endif #if @GNULIB_FOPEN@ @@ -161,20 +259,26 @@ _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 - " +_GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX compliant - " "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@) + || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define fprintf rpl_fprintf # endif # define GNULIB_overrides_fprintf 1 +# if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ _GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif _GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...)); # else _GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...)); @@ -220,7 +324,7 @@ _GL_WARN_ON_USE (fpurge, "fpurge is not always present - " #endif #if @GNULIB_FPUTC@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fputc # define fputc rpl_fputc @@ -234,7 +338,7 @@ _GL_CXXALIASWARN (fputc); #endif #if @GNULIB_FPUTS@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fputs # define fputs rpl_fputs @@ -248,6 +352,21 @@ _GL_CXXALIAS_SYS (fputs, int, (const char *string, FILE *stream)); _GL_CXXALIASWARN (fputs); #endif +#if @GNULIB_FREAD@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fread +# define fread rpl_fread +# endif +_GL_FUNCDECL_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream) + _GL_ARG_NONNULL ((4))); +_GL_CXXALIAS_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)); +# endif +_GL_CXXALIASWARN (fread); +#endif + #if @GNULIB_FREOPEN@ # if @REPLACE_FREOPEN@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) @@ -267,10 +386,27 @@ _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 - " +_GL_WARN_ON_USE (freopen, + "freopen on native Windows platforms is not POSIX compliant - " "use gnulib module freopen for portability"); #endif +#if @GNULIB_FSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fscanf +# define fscanf rpl_fscanf +# endif +_GL_FUNCDECL_RPL (fscanf, int, (FILE *stream, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fscanf, int, (FILE *stream, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (fscanf, int, (FILE *stream, const char *format, ...)); +# endif +_GL_CXXALIASWARN (fscanf); +#endif + /* Set up the following warnings, based on which modules are in use. GNU Coding Standards discourage the use of fseek, since it imposes @@ -338,29 +474,13 @@ _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@ +# if ! @HAVE_DECL_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 @@ -414,28 +534,12 @@ _GL_CXXALIASWARN (ftell); _GL_FUNCDECL_RPL (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL (ftello, off_t, (FILE *fp)); # else -# if ! @HAVE_FTELLO@ +# if ! @HAVE_DECL_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 @@ -457,7 +561,7 @@ _GL_WARN_ON_USE (ftell, "ftell cannot handle files larger than 4 GB " #if @GNULIB_FWRITE@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef fwrite # define fwrite rpl_fwrite @@ -470,10 +574,51 @@ _GL_CXXALIAS_RPL (fwrite, size_t, # else _GL_CXXALIAS_SYS (fwrite, size_t, (const void *ptr, size_t s, size_t n, FILE *stream)); + +/* Work around bug 11959 when fortifying glibc 2.4 through 2.15 + , + which sometimes causes an unwanted diagnostic for fwrite calls. + This affects only function declaration attributes under certain + versions of gcc, and is not needed for C++. */ +# if (0 < __USE_FORTIFY_LEVEL \ + && __GLIBC__ == 2 && 4 <= __GLIBC_MINOR__ && __GLIBC_MINOR__ <= 15 \ + && 3 < __GNUC__ + (4 <= __GNUC_MINOR__) \ + && !defined __cplusplus) +# undef fwrite +# define fwrite(a, b, c, d) ({size_t __r = fwrite (a, b, c, d); __r; }) +# endif # endif _GL_CXXALIASWARN (fwrite); #endif +#if @GNULIB_GETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getc +# define getc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (getc, rpl_fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (getc, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (getc); +#endif + +#if @GNULIB_GETCHAR@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getchar +# define getchar rpl_getchar +# endif +_GL_FUNCDECL_RPL (getchar, int, (void)); +_GL_CXXALIAS_RPL (getchar, int, (void)); +# else +_GL_CXXALIAS_SYS (getchar, int, (void)); +# endif +_GL_CXXALIASWARN (getchar); +#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). @@ -550,6 +695,14 @@ _GL_WARN_ON_USE (getline, "getline is unportable - " # endif #endif +/* It is very rare that the developer ever has full control of stdin, + so any use of gets warrants an unconditional warning; besides, C11 + removed it. */ +#undef gets +#if HAVE_RAW_DECL_GETS +#endif + + #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@ struct obstack; /* Grow an obstack with formatted output. Return the number of @@ -563,7 +716,7 @@ struct obstack; # endif _GL_FUNCDECL_RPL (obstack_printf, int, (struct obstack *obs, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_RPL (obstack_printf, int, (struct obstack *obs, const char *format, ...)); @@ -571,7 +724,7 @@ _GL_CXXALIAS_RPL (obstack_printf, int, # if !@HAVE_DECL_OBSTACK_PRINTF@ _GL_FUNCDECL_SYS (obstack_printf, int, (struct obstack *obs, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((1, 2))); # endif _GL_CXXALIAS_SYS (obstack_printf, int, @@ -584,7 +737,7 @@ _GL_CXXALIASWARN (obstack_printf); # endif _GL_FUNCDECL_RPL (obstack_vprintf, int, (struct obstack *obs, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) + _GL_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)); @@ -592,7 +745,7 @@ _GL_CXXALIAS_RPL (obstack_vprintf, int, # 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_ATTRIBUTE_FORMAT_PRINTF (2, 0) _GL_ARG_NONNULL ((1, 2))); # endif _GL_CXXALIAS_SYS (obstack_vprintf, int, @@ -601,6 +754,20 @@ _GL_CXXALIAS_SYS (obstack_vprintf, int, _GL_CXXALIASWARN (obstack_vprintf); #endif +#if @GNULIB_PCLOSE@ +# if !@HAVE_PCLOSE@ +_GL_FUNCDECL_SYS (pclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pclose, int, (FILE *stream)); +_GL_CXXALIASWARN (pclose); +#elif defined GNULIB_POSIXCHECK +# undef pclose +# if HAVE_RAW_DECL_PCLOSE +_GL_WARN_ON_USE (pclose, "pclose is unportable - " + "use gnulib module pclose for more portability"); +# endif +#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 ": ", @@ -632,6 +799,10 @@ _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 +# if !@HAVE_POPEN@ +_GL_FUNCDECL_SYS (popen, FILE *, (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +# endif _GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode)); # endif _GL_CXXALIASWARN (popen); @@ -645,23 +816,35 @@ _GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " #if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ # if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ - || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @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 +# if @GNULIB_PRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ _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_ATTRIBUTE_FORMAT_PRINTF (1, 2) _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +# endif _GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); # else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define printf rpl_printf +# endif _GL_FUNCDECL_RPL (printf, int, (const char *format, ...) - __attribute__ ((__format__ (__printf__, 1, 2))) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL (printf, int, (const char *format, ...)); # endif @@ -682,7 +865,7 @@ _GL_WARN_ON_USE (printf, "printf is not always POSIX compliant - " #endif #if @GNULIB_PUTC@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef putc # define putc rpl_fputc @@ -696,7 +879,7 @@ _GL_CXXALIASWARN (putc); #endif #if @GNULIB_PUTCHAR@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef putchar # define putchar rpl_putchar @@ -710,7 +893,7 @@ _GL_CXXALIASWARN (putchar); #endif #if @GNULIB_PUTS@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef puts # define puts rpl_puts @@ -794,6 +977,37 @@ _GL_WARN_ON_USE (renameat, "renameat is not portable - " # endif #endif +#if @GNULIB_SCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if defined __GNUC__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +/* Don't break __attribute__((format(scanf,M,N))). */ +# define scanf __scanf__ +# endif +_GL_FUNCDECL_RPL_1 (__scanf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_scanf)) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (scanf, __scanf__, int, (const char *format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +# define scanf rpl_scanf +# endif +_GL_FUNCDECL_RPL (scanf, int, (const char *format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (scanf, int, (const char *format, ...)); +# endif +# else +_GL_CXXALIAS_SYS (scanf, int, (const char *format, ...)); +# endif +_GL_CXXALIASWARN (scanf); +#endif + #if @GNULIB_SNPRINTF@ # if @REPLACE_SNPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) @@ -801,7 +1015,7 @@ _GL_WARN_ON_USE (renameat, "renameat is not portable - " # endif _GL_FUNCDECL_RPL (snprintf, int, (char *str, size_t size, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4) _GL_ARG_NONNULL ((3))); _GL_CXXALIAS_RPL (snprintf, int, (char *str, size_t size, const char *format, ...)); @@ -809,7 +1023,7 @@ _GL_CXXALIAS_RPL (snprintf, int, # if !@HAVE_DECL_SNPRINTF@ _GL_FUNCDECL_SYS (snprintf, int, (char *str, size_t size, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4) _GL_ARG_NONNULL ((3))); # endif _GL_CXXALIAS_SYS (snprintf, int, @@ -824,9 +1038,9 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - " # 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. +/* Some people would argue that all sprintf uses should be warned about + (for example, OpenBSD issues a link warning for it), + since it 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 @@ -839,7 +1053,7 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - " # define sprintf rpl_sprintf # endif _GL_FUNCDECL_RPL (sprintf, int, (char *str, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_RPL (sprintf, int, (char *str, const char *format, ...)); # else @@ -884,7 +1098,7 @@ _GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - " # endif _GL_FUNCDECL_RPL (asprintf, int, (char **result, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_RPL (asprintf, int, (char **result, const char *format, ...)); @@ -892,7 +1106,7 @@ _GL_CXXALIAS_RPL (asprintf, int, # if !@HAVE_VASPRINTF@ _GL_FUNCDECL_SYS (asprintf, int, (char **result, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) _GL_ARG_NONNULL ((1, 2))); # endif _GL_CXXALIAS_SYS (asprintf, int, @@ -905,7 +1119,7 @@ _GL_CXXALIASWARN (asprintf); # endif _GL_FUNCDECL_RPL (vasprintf, int, (char **result, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_RPL (vasprintf, int, (char **result, const char *format, va_list args)); @@ -913,7 +1127,7 @@ _GL_CXXALIAS_RPL (vasprintf, int, # if !@HAVE_VASPRINTF@ _GL_FUNCDECL_SYS (vasprintf, int, (char **result, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) _GL_ARG_NONNULL ((1, 2))); # endif _GL_CXXALIAS_SYS (vasprintf, int, @@ -928,13 +1142,13 @@ _GL_CXXALIASWARN (vasprintf); # define vdprintf rpl_vdprintf # endif _GL_FUNCDECL_RPL (vdprintf, int, (int fd, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) + _GL_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_ATTRIBUTE_FORMAT_PRINTF (2, 0) _GL_ARG_NONNULL ((2))); # endif /* Need to cast, because on Solaris, the third parameter will likely be @@ -953,14 +1167,20 @@ _GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - " #if @GNULIB_VFPRINTF_POSIX@ || @GNULIB_VFPRINTF@ # if (@GNULIB_VFPRINTF_POSIX@ && @REPLACE_VFPRINTF@) \ - || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define vfprintf rpl_vfprintf # endif # define GNULIB_overrides_vfprintf 1 +# if @GNULIB_VFPRINTF_POSIX@ _GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif _GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)); # else /* Need to cast, because on Solaris, the third parameter is @@ -981,16 +1201,41 @@ _GL_WARN_ON_USE (vfprintf, "vfprintf is not always POSIX compliant - " "POSIX compliance"); #endif +#if @GNULIB_VFSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vfscanf +# define vfscanf rpl_vfscanf +# endif +_GL_FUNCDECL_RPL (vfscanf, int, + (FILE *stream, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vfscanf, int, + (FILE *stream, const char *format, va_list args)); +# else +_GL_CXXALIAS_SYS (vfscanf, int, + (FILE *stream, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vfscanf); +#endif + #if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@ # if (@GNULIB_VPRINTF_POSIX@ && @REPLACE_VPRINTF@) \ - || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) + || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define vprintf rpl_vprintf # endif # define GNULIB_overrides_vprintf 1 +# if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ _GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 1, 0))) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 0) _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +# endif _GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args)); # else /* Need to cast, because on Solaris, the second parameter is @@ -1010,6 +1255,22 @@ _GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - " "POSIX compliance"); #endif +#if @GNULIB_VSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vscanf +# define vscanf rpl_vscanf +# endif +_GL_FUNCDECL_RPL (vscanf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (vscanf, int, (const char *format, va_list args)); +# else +_GL_CXXALIAS_SYS (vscanf, int, (const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vscanf); +#endif + #if @GNULIB_VSNPRINTF@ # if @REPLACE_VSNPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) @@ -1017,7 +1278,7 @@ _GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - " # endif _GL_FUNCDECL_RPL (vsnprintf, int, (char *str, size_t size, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 3, 0))) + _GL_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)); @@ -1025,7 +1286,7 @@ _GL_CXXALIAS_RPL (vsnprintf, int, # 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_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3))); # endif _GL_CXXALIAS_SYS (vsnprintf, int, @@ -1047,7 +1308,7 @@ _GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " # endif _GL_FUNCDECL_RPL (vsprintf, int, (char *str, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_RPL (vsprintf, int, (char *str, const char *format, va_list args)); @@ -1067,7 +1328,6 @@ _GL_WARN_ON_USE (vsprintf, "vsprintf is not always POSIX compliant - " "POSIX compliance"); #endif - -#endif /* _GL_STDIO_H */ -#endif /* _GL_STDIO_H */ +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif /* _@GUARD_PREFIX@_STDIO_H */ #endif diff --git a/grub-core/gnulib/stdlib.in.h b/grub-core/gnulib/stdlib.in.h index f4309ed73..c9552480e 100644 --- a/grub-core/gnulib/stdlib.in.h +++ b/grub-core/gnulib/stdlib.in.h @@ -1,6 +1,6 @@ /* A GNU-like . - Copyright (C) 1995, 2001-2004, 2006-2010 Free Software Foundation, Inc. + Copyright (C) 1995, 2001-2004, 2006-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,28 +18,30 @@ #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ -#if defined __need_malloc_and_calloc -/* Special invocation convention inside glibc header files. */ +#if defined __need_system_stdlib_h || defined __need_malloc_and_calloc +/* Special invocation conventions inside some gnulib header files, + and inside some glibc header files, respectively. */ #@INCLUDE_NEXT@ @NEXT_STDLIB_H@ #else /* Normal invocation convention. */ -#ifndef _GL_STDLIB_H +#ifndef _@GUARD_PREFIX@_STDLIB_H /* The include_next requires a split double-inclusion guard. */ #@INCLUDE_NEXT@ @NEXT_STDLIB_H@ -#ifndef _GL_STDLIB_H -#define _GL_STDLIB_H +#ifndef _@GUARD_PREFIX@_STDLIB_H +#define _@GUARD_PREFIX@_STDLIB_H /* NetBSD 5.0 mis-defines NULL. */ #include /* MirBSD 10 defines WEXITSTATUS in , not in . */ -#ifndef WEXITSTATUS +#if @GNULIB_SYSTEM_POSIX@ && !defined WEXITSTATUS # include #endif @@ -48,18 +50,28 @@ # include #endif +/* Native Windows platforms declare mktemp() in . */ +#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +# include +#endif + +#if @GNULIB_RANDOM_R@ + /* 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 + from if _REENTRANT is defined. Include it whenever we need + 'struct random_data'. */ +# 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@ || @REPLACE_RANDOM_R@ || !@HAVE_RANDOM_R@ +# include +# endif -#if !@HAVE_STRUCT_RANDOM_DATA@ +# if !@HAVE_STRUCT_RANDOM_DATA@ +/* Define 'struct random_data'. + But allow multiple gnulib generated replacements to coexist. */ +# if !GNULIB_defined_struct_random_data struct random_data { int32_t *fptr; /* Front pointer. */ @@ -70,21 +82,29 @@ struct random_data int rand_sep; /* Distance between front and rear. */ int32_t *end_ptr; /* Pointer behind state table. */ }; +# define GNULIB_defined_struct_random_data 1 +# endif +# endif #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. */ +#if (@GNULIB_MKSTEMP@ || @GNULIB_MKSTEMPS@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) +/* On Mac OS X 10.3, only declares mkstemp. */ +/* On Mac OS X 10.5, only declares mkstemps. */ /* 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 +/* The __attribute__ feature is available in gcc versions 2.5 and later. + 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 +/* The definition of _Noreturn is copied here. */ + /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ /* The definition of _GL_ARG_NONNULL is copied here. */ @@ -110,7 +130,7 @@ struct random_data /* 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__))); +_GL_FUNCDECL_SYS (_Exit, _Noreturn void, (int status)); # endif _GL_CXXALIAS_SYS (_Exit, void, (int status)); _GL_CXXALIASWARN (_Exit); @@ -127,7 +147,9 @@ _GL_WARN_ON_USE (_Exit, "_Exit is unportable - " /* 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))); +_GL_FUNCDECL_SYS (atoll, long long, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); # endif _GL_CXXALIAS_SYS (atoll, long long, (const char *string)); _GL_CXXALIASWARN (atoll); @@ -177,7 +199,8 @@ _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 - " +_GL_WARN_ON_USE (canonicalize_file_name, + "canonicalize_file_name is unportable - " "use gnulib module canonicalize-lgpl for portability"); # endif #endif @@ -240,14 +263,19 @@ _GL_CXXALIASWARN (grantpt); #elif defined GNULIB_POSIXCHECK # undef grantpt # if HAVE_RAW_DECL_GRANTPT -_GL_WARN_ON_USE (ptsname, "grantpt is not portable - " +_GL_WARN_ON_USE (grantpt, "grantpt is not portable - " "use gnulib module grantpt for portability"); # endif #endif +/* If _GL_USE_STDLIB_ALLOC is nonzero, the including module does not + rely on GNU or POSIX semantics for malloc and realloc (for example, + by never specifying a zero size), so it does not need malloc or + realloc to be redefined. */ #if @GNULIB_MALLOC_POSIX@ # if @REPLACE_MALLOC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) # undef malloc # define malloc rpl_malloc # endif @@ -257,13 +285,28 @@ _GL_CXXALIAS_RPL (malloc, void *, (size_t size)); _GL_CXXALIAS_SYS (malloc, void *, (size_t size)); # endif _GL_CXXALIASWARN (malloc); -#elif defined GNULIB_POSIXCHECK +#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC # 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 +/* Convert a multibyte character to a wide character. */ +#if @GNULIB_MBTOWC@ +# if @REPLACE_MBTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbtowc +# define mbtowc rpl_mbtowc +# endif +_GL_FUNCDECL_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +_GL_CXXALIAS_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +# else +_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +# endif +_GL_CXXALIASWARN (mbtowc); +#endif + #if @GNULIB_MKDTEMP@ /* Create a unique temporary directory from TEMPLATE. The last six characters of TEMPLATE must be "XXXXXX"; @@ -396,13 +439,38 @@ _GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - " # endif #endif +#if @GNULIB_POSIX_OPENPT@ +/* Return an FD open to the master side of a pseudo-terminal. Flags should + include O_RDWR, and may also include O_NOCTTY. */ +# if !@HAVE_POSIX_OPENPT@ +_GL_FUNCDECL_SYS (posix_openpt, int, (int flags)); +# endif +_GL_CXXALIAS_SYS (posix_openpt, int, (int flags)); +_GL_CXXALIASWARN (posix_openpt); +#elif defined GNULIB_POSIXCHECK +# undef posix_openpt +# if HAVE_RAW_DECL_POSIX_OPENPT +_GL_WARN_ON_USE (posix_openpt, "posix_openpt is not portable - " + "use gnulib module posix_openpt 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@ +# if @REPLACE_PTSNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname +# define ptsname rpl_ptsname +# endif +_GL_FUNCDECL_RPL (ptsname, char *, (int fd)); +_GL_CXXALIAS_RPL (ptsname, char *, (int fd)); +# else +# if !@HAVE_PTSNAME@ _GL_FUNCDECL_SYS (ptsname, char *, (int fd)); -# endif +# endif _GL_CXXALIAS_SYS (ptsname, char *, (int fd)); +# endif _GL_CXXALIASWARN (ptsname); #elif defined GNULIB_POSIXCHECK # undef ptsname @@ -412,6 +480,32 @@ _GL_WARN_ON_USE (ptsname, "ptsname is not portable - " # endif #endif +#if @GNULIB_PTSNAME_R@ +/* Set the pathname of the pseudo-terminal slave associated with + the master FD is open on and return 0, or set errno and return + non-zero on errors. */ +# if @REPLACE_PTSNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname_r +# define ptsname_r rpl_ptsname_r +# endif +_GL_FUNCDECL_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +_GL_CXXALIAS_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +# else +# if !@HAVE_PTSNAME_R@ +_GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIASWARN (ptsname_r); +#elif defined GNULIB_POSIXCHECK +# undef ptsname_r +# if HAVE_RAW_DECL_PTSNAME_R +_GL_WARN_ON_USE (ptsname_r, "ptsname_r is not portable - " + "use gnulib module ptsname_r for portability"); +# endif +#endif + #if @GNULIB_PUTENV@ # if @REPLACE_PUTENV@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) @@ -435,12 +529,83 @@ _GL_CXXALIASWARN (putenv); # endif #endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (random, long, (void)); +# endif +_GL_CXXALIAS_SYS (random, long, (void)); +_GL_CXXALIASWARN (random); +#elif defined GNULIB_POSIXCHECK +# undef random +# if HAVE_RAW_DECL_RANDOM +_GL_WARN_ON_USE (random, "random is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (srandom, void, (unsigned int seed)); +# endif +_GL_CXXALIAS_SYS (srandom, void, (unsigned int seed)); +_GL_CXXALIASWARN (srandom); +#elif defined GNULIB_POSIXCHECK +# undef srandom +# if HAVE_RAW_DECL_SRANDOM +_GL_WARN_ON_USE (srandom, "srandom is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size)); +_GL_CXXALIASWARN (initstate); +#elif defined GNULIB_POSIXCHECK +# undef initstate +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate, "initstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setstate, char *, (char *arg_state)); +_GL_CXXALIASWARN (setstate); +#elif defined GNULIB_POSIXCHECK +# undef setstate +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate, "setstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + + #if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef random_r +# define random_r rpl_random_r +# endif +_GL_FUNCDECL_RPL (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (random_r, int, (struct random_data *buf, int32_t *result)); +# else +# if !@HAVE_RANDOM_R@ _GL_FUNCDECL_SYS (random_r, int, (struct random_data *buf, int32_t *result) _GL_ARG_NONNULL ((1, 2))); -# endif +# endif _GL_CXXALIAS_SYS (random_r, int, (struct random_data *buf, int32_t *result)); +# endif _GL_CXXALIASWARN (random_r); #elif defined GNULIB_POSIXCHECK # undef random_r @@ -451,13 +616,25 @@ _GL_WARN_ON_USE (random_r, "random_r is unportable - " #endif #if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef srandom_r +# define srandom_r rpl_srandom_r +# endif +_GL_FUNCDECL_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ _GL_FUNCDECL_SYS (srandom_r, int, (unsigned int seed, struct random_data *rand_state) _GL_ARG_NONNULL ((2))); -# endif +# endif _GL_CXXALIAS_SYS (srandom_r, int, (unsigned int seed, struct random_data *rand_state)); +# endif _GL_CXXALIASWARN (srandom_r); #elif defined GNULIB_POSIXCHECK # undef srandom_r @@ -468,15 +645,29 @@ _GL_WARN_ON_USE (srandom_r, "srandom_r is unportable - " #endif #if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef initstate_r +# define initstate_r rpl_initstate_r +# endif +_GL_FUNCDECL_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# else +# 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 +# endif _GL_CXXALIAS_SYS (initstate_r, int, (unsigned int seed, char *buf, size_t buf_size, struct random_data *rand_state)); +# endif _GL_CXXALIASWARN (initstate_r); #elif defined GNULIB_POSIXCHECK # undef initstate_r @@ -487,13 +678,25 @@ _GL_WARN_ON_USE (initstate_r, "initstate_r is unportable - " #endif #if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setstate_r +# define setstate_r rpl_setstate_r +# endif +_GL_FUNCDECL_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ _GL_FUNCDECL_SYS (setstate_r, int, (char *arg_state, struct random_data *rand_state) _GL_ARG_NONNULL ((1, 2))); -# endif +# endif _GL_CXXALIAS_SYS (setstate_r, int, (char *arg_state, struct random_data *rand_state)); +# endif _GL_CXXALIASWARN (setstate_r); #elif defined GNULIB_POSIXCHECK # undef setstate_r @@ -506,7 +709,8 @@ _GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - " #if @GNULIB_REALLOC_POSIX@ # if @REPLACE_REALLOC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) # undef realloc # define realloc rpl_realloc # endif @@ -516,7 +720,7 @@ _GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size)); _GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size)); # endif _GL_CXXALIASWARN (realloc); -#elif defined GNULIB_POSIXCHECK +#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC # undef realloc /* Assume realloc is always declared. */ _GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " @@ -563,6 +767,22 @@ _GL_WARN_ON_USE (rpmatch, "rpmatch is unportable - " # endif #endif +#if @GNULIB_SECURE_GETENV@ +/* Look up NAME in the environment, returning 0 in insecure situations. */ +# if !@HAVE_SECURE_GETENV@ +_GL_FUNCDECL_SYS (secure_getenv, char *, + (char const *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (secure_getenv, char *, (char const *name)); +_GL_CXXALIASWARN (secure_getenv); +#elif defined GNULIB_POSIXCHECK +# undef secure_getenv +# if HAVE_RAW_DECL_SECURE_GETENV +_GL_WARN_ON_USE (secure_getenv, "secure_getenv is unportable - " + "use gnulib module secure_getenv for portability"); +# endif +#endif + #if @GNULIB_SETENV@ /* Set NAME to VALUE in the environment. If REPLACE is nonzero, overwrite an existing value. */ @@ -577,7 +797,7 @@ _GL_FUNCDECL_RPL (setenv, int, _GL_CXXALIAS_RPL (setenv, int, (const char *name, const char *value, int replace)); # else -# if !@HAVE_SETENV@ +# if !@HAVE_DECL_SETENV@ _GL_FUNCDECL_SYS (setenv, int, (const char *name, const char *value, int replace) _GL_ARG_NONNULL ((1))); @@ -585,7 +805,9 @@ _GL_FUNCDECL_SYS (setenv, int, _GL_CXXALIAS_SYS (setenv, int, (const char *name, const char *value, int replace)); # endif +# if !(@REPLACE_SETENV@ && !@HAVE_DECL_SETENV@) _GL_CXXALIASWARN (setenv); +# endif #elif defined GNULIB_POSIXCHECK # undef setenv # if HAVE_RAW_DECL_SETENV @@ -695,12 +917,14 @@ _GL_WARN_ON_USE (unlockpt, "unlockpt is not portable - " _GL_FUNCDECL_RPL (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL (unsetenv, int, (const char *name)); # else -# if !@HAVE_UNSETENV@ +# if !@HAVE_DECL_UNSETENV@ _GL_FUNCDECL_SYS (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); # endif _GL_CXXALIAS_SYS (unsetenv, int, (const char *name)); # endif +# if !(@REPLACE_UNSETENV@ && !@HAVE_DECL_UNSETENV@) _GL_CXXALIASWARN (unsetenv); +# endif #elif defined GNULIB_POSIXCHECK # undef unsetenv # if HAVE_RAW_DECL_UNSETENV @@ -709,7 +933,22 @@ _GL_WARN_ON_USE (unsetenv, "unsetenv is unportable - " # endif #endif - -#endif /* _GL_STDLIB_H */ -#endif /* _GL_STDLIB_H */ +/* Convert a wide character to a multibyte character. */ +#if @GNULIB_WCTOMB@ +# if @REPLACE_WCTOMB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wctomb +# define wctomb rpl_wctomb +# endif +_GL_FUNCDECL_RPL (wctomb, int, (char *s, wchar_t wc)); +_GL_CXXALIAS_RPL (wctomb, int, (char *s, wchar_t wc)); +# else +_GL_CXXALIAS_SYS (wctomb, int, (char *s, wchar_t wc)); +# endif +_GL_CXXALIASWARN (wctomb); +#endif + + +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif /* _@GUARD_PREFIX@_STDLIB_H */ #endif diff --git a/grub-core/gnulib/strcasecmp.c b/grub-core/gnulib/strcasecmp.c index 612c80fdc..0f0a742ff 100644 --- a/grub-core/gnulib/strcasecmp.c +++ b/grub-core/gnulib/strcasecmp.c @@ -1,5 +1,5 @@ /* Case-insensitive string comparison function. - Copyright (C) 1998-1999, 2005-2007, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 1998-1999, 2005-2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + along with this program; if not, see . */ #include diff --git a/grub-core/gnulib/strchrnul.c b/grub-core/gnulib/strchrnul.c index f834d3434..f6b072274 100644 --- a/grub-core/gnulib/strchrnul.c +++ b/grub-core/gnulib/strchrnul.c @@ -1,5 +1,5 @@ /* Searching in a string. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/grub-core/gnulib/streq.h b/grub-core/gnulib/streq.h index aa65bb8e1..12c1867c8 100644 --- a/grub-core/gnulib/streq.h +++ b/grub-core/gnulib/streq.h @@ -1,5 +1,5 @@ /* Optimized string comparison. - Copyright (C) 2001-2002, 2007, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2001-2002, 2007, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -9,7 +9,7 @@ This program is distributed in the hope that 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. + 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 . */ @@ -21,8 +21,8 @@ #include -/* STREQ allows to optimize string comparison with a small literal string. - STREQ (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) +/* STREQ_OPT allows to optimize string comparison with a small literal string. + STREQ_OPT (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) is semantically equivalent to strcmp (s, "EUC-KR") == 0 just faster. */ @@ -163,12 +163,12 @@ streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, return 0; } -#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ +#define STREQ_OPT(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) \ +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ (strcmp (s1, s2) == 0) #endif diff --git a/grub-core/gnulib/strerror-override.c b/grub-core/gnulib/strerror-override.c new file mode 100644 index 000000000..d0ed2fb86 --- /dev/null +++ b/grub-core/gnulib/strerror-override.c @@ -0,0 +1,302 @@ +/* strerror-override.c --- POSIX compatible system error routine + + Copyright (C) 2010-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2010. */ + +#include + +#include "strerror-override.h" + +#include + +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ +# if HAVE_WINSOCK2_H +# include +# endif +#endif + +/* If ERRNUM maps to an errno value defined by gnulib, return a string + describing the error. Otherwise return NULL. */ +const char * +strerror_override (int errnum) +{ + /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ + switch (errnum) + { +#if REPLACE_STRERROR_0 + case 0: + return "Success"; +#endif + +#if GNULIB_defined_ESOCK /* native Windows platforms with older */ + case EINPROGRESS: + return "Operation now in progress"; + case EALREADY: + return "Operation already in progress"; + case ENOTSOCK: + return "Socket operation on non-socket"; + case EDESTADDRREQ: + return "Destination address required"; + case EMSGSIZE: + return "Message too long"; + case EPROTOTYPE: + return "Protocol wrong type for socket"; + case ENOPROTOOPT: + return "Protocol not available"; + case EPROTONOSUPPORT: + return "Protocol not supported"; + case EOPNOTSUPP: + return "Operation not supported"; + case EAFNOSUPPORT: + return "Address family not supported by protocol"; + case EADDRINUSE: + return "Address already in use"; + case EADDRNOTAVAIL: + return "Cannot assign requested address"; + case ENETDOWN: + return "Network is down"; + case ENETUNREACH: + return "Network is unreachable"; + case ECONNRESET: + return "Connection reset by peer"; + case ENOBUFS: + return "No buffer space available"; + case EISCONN: + return "Transport endpoint is already connected"; + case ENOTCONN: + return "Transport endpoint is not connected"; + case ETIMEDOUT: + return "Connection timed out"; + case ECONNREFUSED: + return "Connection refused"; + case ELOOP: + return "Too many levels of symbolic links"; + case EHOSTUNREACH: + return "No route to host"; + case EWOULDBLOCK: + return "Operation would block"; +#endif +#if GNULIB_defined_ESTREAMS /* native Windows platforms with older */ + case ETXTBSY: + return "Text file busy"; + case ENODATA: + return "No data available"; + case ENOSR: + return "Out of streams resources"; + case ENOSTR: + return "Device not a stream"; + case ETIME: + return "Timer expired"; + case EOTHER: + return "Other error"; +#endif +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ + case ESOCKTNOSUPPORT: + return "Socket type not supported"; + case EPFNOSUPPORT: + return "Protocol family not supported"; + case ESHUTDOWN: + return "Cannot send after transport endpoint shutdown"; + case ETOOMANYREFS: + return "Too many references: cannot splice"; + case EHOSTDOWN: + return "Host is down"; + case EPROCLIM: + return "Too many processes"; + case EUSERS: + return "Too many users"; + case EDQUOT: + return "Disk quota exceeded"; + case ESTALE: + return "Stale NFS file handle"; + case EREMOTE: + return "Object is remote"; +# 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: + return "Overlapped operation aborted"; + case WSA_IO_INCOMPLETE: + return "Overlapped I/O event object not in signaled state"; + case WSA_IO_PENDING: + return "Overlapped operations will complete later"; + /* 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 maps to EINPROGRESS */ + /* WSAEALREADY maps to EALREADY */ + /* WSAENOTSOCK maps to ENOTSOCK */ + /* WSAEDESTADDRREQ maps to EDESTADDRREQ */ + /* WSAEMSGSIZE maps to EMSGSIZE */ + /* WSAEPROTOTYPE maps to EPROTOTYPE */ + /* WSAENOPROTOOPT maps to ENOPROTOOPT */ + /* WSAEPROTONOSUPPORT maps to EPROTONOSUPPORT */ + /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ + /* WSAEOPNOTSUPP maps to EOPNOTSUPP */ + /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ + /* WSAEAFNOSUPPORT maps to EAFNOSUPPORT */ + /* WSAEADDRINUSE maps to EADDRINUSE */ + /* WSAEADDRNOTAVAIL maps to EADDRNOTAVAIL */ + /* WSAENETDOWN maps to ENETDOWN */ + /* WSAENETUNREACH maps to ENETUNREACH */ + /* WSAENETRESET maps to ENETRESET */ + /* WSAECONNABORTED maps to ECONNABORTED */ + /* WSAECONNRESET maps to ECONNRESET */ + /* WSAENOBUFS maps to ENOBUFS */ + /* WSAEISCONN maps to EISCONN */ + /* WSAENOTCONN maps to ENOTCONN */ + /* WSAESHUTDOWN is ESHUTDOWN */ + /* WSAETOOMANYREFS is ETOOMANYREFS */ + /* WSAETIMEDOUT maps to ETIMEDOUT */ + /* WSAECONNREFUSED maps to ECONNREFUSED */ + /* WSAELOOP maps to ELOOP */ + /* WSAENAMETOOLONG maps to ENAMETOOLONG */ + /* WSAEHOSTDOWN is EHOSTDOWN */ + /* WSAEHOSTUNREACH maps to EHOSTUNREACH */ + /* WSAENOTEMPTY maps to ENOTEMPTY */ + /* WSAEPROCLIM is EPROCLIM */ + /* WSAEUSERS is EUSERS */ + /* WSAEDQUOT is EDQUOT */ + /* WSAESTALE is ESTALE */ + /* WSAEREMOTE is EREMOTE */ + case WSASYSNOTREADY: + return "Network subsystem is unavailable"; + case WSAVERNOTSUPPORTED: + return "Winsock.dll version out of range"; + case WSANOTINITIALISED: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: + return "Graceful shutdown in progress"; + case WSAENOMORE: case WSA_E_NO_MORE: + return "No more results"; + case WSAECANCELLED: case WSA_E_CANCELLED: + return "Call was canceled"; + case WSAEINVALIDPROCTABLE: + return "Procedure call table is invalid"; + case WSAEINVALIDPROVIDER: + return "Service provider is invalid"; + case WSAEPROVIDERFAILEDINIT: + return "Service provider failed to initialize"; + case WSASYSCALLFAILURE: + return "System call failure"; + case WSASERVICE_NOT_FOUND: + return "Service not found"; + case WSATYPE_NOT_FOUND: + return "Class type not found"; + case WSAEREFUSED: + return "Database query was refused"; + case WSAHOST_NOT_FOUND: + return "Host not found"; + case WSATRY_AGAIN: + return "Nonauthoritative host not found"; + case WSANO_RECOVERY: + return "Nonrecoverable error"; + case WSANO_DATA: + return "Valid name, no data record of requested type"; + /* WSA_QOS_* omitted */ +# endif +#endif + +#if GNULIB_defined_ENOMSG + case ENOMSG: + return "No message of desired type"; +#endif + +#if GNULIB_defined_EIDRM + case EIDRM: + return "Identifier removed"; +#endif + +#if GNULIB_defined_ENOLINK + case ENOLINK: + return "Link has been severed"; +#endif + +#if GNULIB_defined_EPROTO + case EPROTO: + return "Protocol error"; +#endif + +#if GNULIB_defined_EMULTIHOP + case EMULTIHOP: + return "Multihop attempted"; +#endif + +#if GNULIB_defined_EBADMSG + case EBADMSG: + return "Bad message"; +#endif + +#if GNULIB_defined_EOVERFLOW + case EOVERFLOW: + return "Value too large for defined data type"; +#endif + +#if GNULIB_defined_ENOTSUP + case ENOTSUP: + return "Not supported"; +#endif + +#if GNULIB_defined_ENETRESET + case ENETRESET: + return "Network dropped connection on reset"; +#endif + +#if GNULIB_defined_ECONNABORTED + case ECONNABORTED: + return "Software caused connection abort"; +#endif + +#if GNULIB_defined_ESTALE + case ESTALE: + return "Stale NFS file handle"; +#endif + +#if GNULIB_defined_EDQUOT + case EDQUOT: + return "Disk quota exceeded"; +#endif + +#if GNULIB_defined_ECANCELED + case ECANCELED: + return "Operation canceled"; +#endif + +#if GNULIB_defined_EOWNERDEAD + case EOWNERDEAD: + return "Owner died"; +#endif + +#if GNULIB_defined_ENOTRECOVERABLE + case ENOTRECOVERABLE: + return "State not recoverable"; +#endif + +#if GNULIB_defined_EILSEQ + case EILSEQ: + return "Invalid or incomplete multibyte or wide character"; +#endif + + default: + return NULL; + } +} diff --git a/grub-core/gnulib/strerror-override.h b/grub-core/gnulib/strerror-override.h new file mode 100644 index 000000000..3b8f24b99 --- /dev/null +++ b/grub-core/gnulib/strerror-override.h @@ -0,0 +1,56 @@ +/* strerror-override.h --- POSIX compatible system error routine + + Copyright (C) 2010-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _GL_STRERROR_OVERRIDE_H +# define _GL_STRERROR_OVERRIDE_H + +# include +# include + +/* Reasonable buffer size that should never trigger ERANGE; if this + proves too small, we intentionally abort(), to remind us to fix + this value. */ +# define STACKBUF_LEN 256 + +/* If ERRNUM maps to an errno value defined by gnulib, return a string + describing the error. Otherwise return NULL. */ +# if REPLACE_STRERROR_0 \ + || GNULIB_defined_ESOCK \ + || GNULIB_defined_ESTREAMS \ + || GNULIB_defined_EWINSOCK \ + || GNULIB_defined_ENOMSG \ + || GNULIB_defined_EIDRM \ + || GNULIB_defined_ENOLINK \ + || GNULIB_defined_EPROTO \ + || GNULIB_defined_EMULTIHOP \ + || GNULIB_defined_EBADMSG \ + || GNULIB_defined_EOVERFLOW \ + || GNULIB_defined_ENOTSUP \ + || GNULIB_defined_ENETRESET \ + || GNULIB_defined_ECONNABORTED \ + || GNULIB_defined_ESTALE \ + || GNULIB_defined_EDQUOT \ + || GNULIB_defined_ECANCELED \ + || GNULIB_defined_EOWNERDEAD \ + || GNULIB_defined_ENOTRECOVERABLE \ + || GNULIB_defined_EILSEQ +extern const char *strerror_override (int errnum); +# else +# define strerror_override(ignored) NULL +# endif + +#endif /* _GL_STRERROR_OVERRIDE_H */ diff --git a/grub-core/gnulib/strerror.c b/grub-core/gnulib/strerror.c index 46153abf5..80a2f2eea 100644 --- a/grub-core/gnulib/strerror.c +++ b/grub-core/gnulib/strerror.c @@ -1,6 +1,6 @@ /* strerror.c --- POSIX compatible system error routine - Copyright (C) 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2007-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,334 +17,54 @@ #include +/* Specification. */ #include -#if REPLACE_STRERROR +#include +#include +#include +#include -# include -# include - -# if GNULIB_defined_ESOCK /* native Windows platforms */ -# if HAVE_WINSOCK2_H -# include -# endif -# endif - -# include "intprops.h" +#include "intprops.h" +#include "strerror-override.h" +#include "verify.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 +#undef sprintf char * -rpl_strerror (int n) +strerror (int n) +#undef strerror { - 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 - } + static char buf[STACKBUF_LEN]; + size_t len; + /* Cast away const, due to the historical signature of strerror; + callers should not be modifying the string. */ + const char *msg = strerror_override (n); if (msg) return (char *) msg; - { - char *result = strerror (n); + msg = 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; - } + /* Our strerror_r implementation might use the system's strerror + buffer, so all other clients of strerror have to see the error + copied into a buffer that we manage. This is not thread-safe, + even if the system strerror is, but portable programs shouldn't + be using strerror if they care about thread-safety. */ + if (!msg || !*msg) + { + static char const fmt[] = "Unknown error %d"; + verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n)); + sprintf (buf, fmt, n); + errno = EINVAL; + return buf; + } - return result; - } + /* Fix STACKBUF_LEN if this ever aborts. */ + len = strlen (msg); + if (sizeof buf <= len) + abort (); + + return memcpy (buf, msg, len + 1); } - -#endif diff --git a/grub-core/gnulib/string.in.h b/grub-core/gnulib/string.in.h index 49c711d8f..d7a6c9c92 100644 --- a/grub-core/gnulib/string.in.h +++ b/grub-core/gnulib/string.in.h @@ -1,6 +1,6 @@ /* A GNU-like . - Copyright (C) 1995-1996, 2001-2010 Free Software Foundation, Inc. + Copyright (C) 1995-1996, 2001-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,20 +13,20 @@ GNU 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. */ + along with this program; if not, see . */ -#ifndef _GL_STRING_H +#ifndef _@GUARD_PREFIX@_STRING_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ /* The include_next requires a split double-inclusion guard. */ #@INCLUDE_NEXT@ @NEXT_STRING_H@ -#ifndef _GL_STRING_H -#define _GL_STRING_H +#ifndef _@GUARD_PREFIX@_STRING_H +#define _@GUARD_PREFIX@_STRING_H /* NetBSD 5.0 mis-defines NULL. */ #include @@ -36,13 +36,8 @@ # 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. */ +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) #else @@ -50,8 +45,8 @@ #endif /* NetBSD 5.0 declares strsignal in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) \ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \ && ! defined __GLIBC__ # include #endif @@ -63,6 +58,36 @@ /* The definition of _GL_WARN_ON_USE is copied here. */ +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSL@ +# if !@HAVE_FFSL@ +_GL_FUNCDECL_SYS (ffsl, int, (long int i)); +# endif +_GL_CXXALIAS_SYS (ffsl, int, (long int i)); +_GL_CXXALIASWARN (ffsl); +#elif defined GNULIB_POSIXCHECK +# undef ffsl +# if HAVE_RAW_DECL_FFSL +_GL_WARN_ON_USE (ffsl, "ffsl is not portable - use the ffsl module"); +# endif +#endif + + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSLL@ +# if !@HAVE_FFSLL@ +_GL_FUNCDECL_SYS (ffsll, int, (long long int i)); +# endif +_GL_CXXALIAS_SYS (ffsll, int, (long long int i)); +_GL_CXXALIASWARN (ffsll); +#elif defined GNULIB_POSIXCHECK +# undef ffsll +# if HAVE_RAW_DECL_FFSLL +_GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module"); +# endif +#endif + + /* Return the first instance of C within N bytes of S, or NULL. */ #if @GNULIB_MEMCHR@ # if @REPLACE_MEMCHR@ @@ -86,7 +111,7 @@ _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 \ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) _GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n)); _GL_CXXALIASWARN1 (memchr, void const *, @@ -171,7 +196,7 @@ _GL_FUNCDECL_SYS (memrchr, void *, (void const *, 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 \ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__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)); @@ -201,7 +226,7 @@ _GL_FUNCDECL_SYS (rawmemchr, void *, (void const *__s, int __c_in) _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 \ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__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)); @@ -281,18 +306,29 @@ _GL_WARN_ON_USE (strchr, "strchr cannot work correctly on character strings " /* Find the first occurrence of C in S or the final NUL byte. */ #if @GNULIB_STRCHRNUL@ -# if ! @HAVE_STRCHRNUL@ +# if @REPLACE_STRCHRNUL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strchrnul rpl_strchrnul +# endif +_GL_FUNCDECL_RPL (strchrnul, char *, (const char *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strchrnul, char *, + (const char *str, int ch)); +# else +# if ! @HAVE_STRCHRNUL@ _GL_FUNCDECL_SYS (strchrnul, char *, (char const *__s, int __c_in) _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1))); -# endif +# 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 \ +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__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)); @@ -438,7 +474,7 @@ _GL_FUNCDECL_SYS (strpbrk, char *, (char const *__s, char const *__accept) _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 \ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) _GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept)); _GL_CXXALIASWARN1 (strpbrk, char const *, @@ -540,7 +576,7 @@ _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 \ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) _GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle)); _GL_CXXALIASWARN1 (strstr, const char *, @@ -589,7 +625,7 @@ _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 \ +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) _GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle)); _GL_CXXALIASWARN1 (strcasestr, const char *, @@ -688,10 +724,14 @@ _GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " # 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_FUNCDECL_RPL (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _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_FUNCDECL_SYS (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_SYS (mbslen, size_t, (const char *string)); # endif _GL_CXXALIASWARN (mbslen); @@ -701,6 +741,7 @@ _GL_CXXALIASWARN (mbslen); /* 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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1)); #endif @@ -714,10 +755,12 @@ _GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) # define mbschr rpl_mbschr /* avoid collision with HP-UX function */ # endif _GL_FUNCDECL_RPL (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE _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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_SYS (mbschr, char *, (const char *string, int c)); # endif @@ -729,15 +772,17 @@ _GL_CXXALIASWARN (mbschr); 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 __hpux || defined __INTERIX # if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbsrchr rpl_mbsrchr /* avoid collision with HP-UX function */ +# define mbsrchr rpl_mbsrchr /* avoid collision with system function */ # endif _GL_FUNCDECL_RPL (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE _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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_SYS (mbsrchr, char *, (const char *string, int c)); # endif @@ -750,6 +795,7 @@ _GL_CXXALIASWARN (mbsrchr); 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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -761,6 +807,7 @@ _GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) different lengths! Unlike strcasecmp(), this function works correctly in multibyte locales. */ _GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) + _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -775,6 +822,7 @@ _GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) 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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -788,6 +836,7 @@ _GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) Unlike strncasecmp(), this function works correctly in multibyte locales. */ _GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) + _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -798,6 +847,7 @@ _GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) 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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -808,6 +858,7 @@ _GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) 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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -821,10 +872,12 @@ _GL_EXTERN_C size_t mbscspn (const char *string, const char *accept) # define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */ # endif _GL_FUNCDECL_RPL (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE _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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2))); _GL_CXXALIAS_SYS (mbspbrk, char *, (const char *string, const char *accept)); # endif @@ -838,6 +891,7 @@ _GL_CXXALIASWARN (mbspbrk); 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_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2)); #endif @@ -901,6 +955,35 @@ _GL_WARN_ON_USE (strerror, "strerror is unportable - " "use gnulib module strerror to guarantee non-NULL result"); #endif +/* Map any int, typically from errno, into an error message. Multithread-safe. + Uses the POSIX declaration, not the glibc declaration. */ +#if @GNULIB_STRERROR_R@ +# if @REPLACE_STRERROR_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror_r +# define strerror_r rpl_strerror_r +# endif +_GL_FUNCDECL_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_STRERROR_R@ +_GL_FUNCDECL_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# endif +# if @HAVE_DECL_STRERROR_R@ +_GL_CXXALIASWARN (strerror_r); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strerror_r +# if HAVE_RAW_DECL_STRERROR_R +_GL_WARN_ON_USE (strerror_r, "strerror_r is unportable - " + "use gnulib module strerror_r-posix for portability"); +# endif +#endif + #if @GNULIB_STRSIGNAL@ # if @REPLACE_STRSIGNAL@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) @@ -928,6 +1011,7 @@ _GL_WARN_ON_USE (strsignal, "strsignal is unportable - " #if @GNULIB_STRVERSCMP@ # if !@HAVE_STRVERSCMP@ _GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) + _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2))); # endif _GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); @@ -941,5 +1025,5 @@ _GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - " #endif -#endif /* _GL_STRING_H */ -#endif /* _GL_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ diff --git a/grub-core/gnulib/strings.in.h b/grub-core/gnulib/strings.in.h index c726a1623..4469f86ca 100644 --- a/grub-core/gnulib/strings.in.h +++ b/grub-core/gnulib/strings.in.h @@ -1,6 +1,6 @@ /* A substitute . - Copyright (C) 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2007-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,21 +13,36 @@ GNU 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. */ + along with this program; if not, see . */ -#ifndef _GL_STRINGS_H +#ifndef _@GUARD_PREFIX@_STRINGS_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ + +/* Minix 3.1.8 has a bug: must be included before . + But avoid namespace pollution on glibc systems. */ +#if defined __minix && !defined __GLIBC__ +# include +#endif /* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_STRINGS_H@ +#if @HAVE_STRINGS_H@ +# @INCLUDE_NEXT@ @NEXT_STRINGS_H@ +#endif -#ifndef _GL_STRINGS_H -#define _GL_STRINGS_H +#ifndef _@GUARD_PREFIX@_STRINGS_H +#define _@GUARD_PREFIX@_STRINGS_H +#if ! @HAVE_DECL_STRNCASECMP@ +/* Get size_t. */ +# include +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ /* The definition of _GL_ARG_NONNULL is copied here. */ @@ -38,6 +53,20 @@ extern "C" { #endif + /* Find the index of the least-significant set bit. */ +#if @GNULIB_FFS@ +# if !@HAVE_FFS@ +_GL_FUNCDECL_SYS (ffs, int, (int i)); +# endif +_GL_CXXALIAS_SYS (ffs, int, (int i)); +_GL_CXXALIASWARN (ffs); +#elif defined GNULIB_POSIXCHECK +# undef ffs +# if HAVE_RAW_DECL_FFS +_GL_WARN_ON_USE (ffs, "ffs is not portable - use the ffs module"); +# endif +#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. @@ -89,5 +118,5 @@ _GL_WARN_ON_USE (strncasecmp, "strncasecmp cannot work correctly on character " } #endif -#endif /* _GL_STRING_H */ -#endif /* _GL_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ diff --git a/grub-core/gnulib/stripslash.c b/grub-core/gnulib/stripslash.c index 3a5996fd9..0e452a95e 100644 --- a/grub-core/gnulib/stripslash.c +++ b/grub-core/gnulib/stripslash.c @@ -1,6 +1,6 @@ /* stripslash.c -- remove redundant trailing slashes from a file name - Copyright (C) 1990, 2001, 2003-2006, 2009-2010 Free Software Foundation, + Copyright (C) 1990, 2001, 2003-2006, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ strip_trailing_slashes (char *file) bool had_slash; /* last_component returns "" for file system roots, but we need to turn - `///' into `/'. */ + "///" into "/". */ if (! *base) base = file; base_lim = base + base_len (base); diff --git a/grub-core/gnulib/strncasecmp.c b/grub-core/gnulib/strncasecmp.c index 8c806a6b0..35840bc01 100644 --- a/grub-core/gnulib/strncasecmp.c +++ b/grub-core/gnulib/strncasecmp.c @@ -1,5 +1,5 @@ /* strncasecmp.c -- case insensitive string comparator - Copyright (C) 1998-1999, 2005-2007, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 1998-1999, 2005-2007, 2009-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + along with this program; if not, see . */ #include diff --git a/grub-core/gnulib/strndup.c b/grub-core/gnulib/strndup.c index 3de3dbc5a..e60268b86 100644 --- a/grub-core/gnulib/strndup.c +++ b/grub-core/gnulib/strndup.c @@ -1,7 +1,7 @@ /* 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. + Copyright (C) 1996-1998, 2001-2003, 2005-2007, 2009-2013 Free Software + Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -14,8 +14,7 @@ GNU 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. */ + along with this program; if not, see . */ #include diff --git a/grub-core/gnulib/strnlen.c b/grub-core/gnulib/strnlen.c index f1ec356dc..57fdfe770 100644 --- a/grub-core/gnulib/strnlen.c +++ b/grub-core/gnulib/strnlen.c @@ -1,5 +1,5 @@ /* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005-2007, 2009-2013 Free Software Foundation, Inc. Written by Simon Josefsson. This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ #include diff --git a/grub-core/gnulib/strnlen1.c b/grub-core/gnulib/strnlen1.c index b8cd2bff0..0c22d21ed 100644 --- a/grub-core/gnulib/strnlen1.c +++ b/grub-core/gnulib/strnlen1.c @@ -1,5 +1,5 @@ /* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/grub-core/gnulib/strnlen1.h b/grub-core/gnulib/strnlen1.h index dfaf62dcb..7c65e3161 100644 --- a/grub-core/gnulib/strnlen1.h +++ b/grub-core/gnulib/strnlen1.h @@ -1,5 +1,5 @@ /* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,7 +28,8 @@ extern "C" { /* 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); +extern size_t strnlen1 (const char *string, size_t maxlen) + _GL_ATTRIBUTE_PURE; #ifdef __cplusplus diff --git a/grub-core/gnulib/sys_types.in.h b/grub-core/gnulib/sys_types.in.h new file mode 100644 index 000000000..d7da35623 --- /dev/null +++ b/grub-core/gnulib/sys_types.in.h @@ -0,0 +1,51 @@ +/* Provide a more complete sys/types.h. + + Copyright (C) 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 +@PRAGMA_COLUMNS@ + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H +#define _@GUARD_PREFIX@_SYS_TYPES_H + +/* Override off_t if Large File Support is requested on native Windows. */ +#if @WINDOWS_64_BIT_OFF_T@ +/* Same as int64_t in . */ +# if defined _MSC_VER +# define off_t __int64 +# else +# define off_t long long int +# endif +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_64_BIT_OFF_T 1 +#endif + +/* MSVC 9 defines size_t in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \ + && ! defined __GLIBC__ +# include +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ diff --git a/grub-core/gnulib/sys_wait.in.h b/grub-core/gnulib/sys_wait.in.h deleted file mode 100644 index 009fa219b..000000000 --- a/grub-core/gnulib/sys_wait.in.h +++ /dev/null @@ -1,106 +0,0 @@ -/* A POSIX-like . - Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - - -#ifndef _GL_SYS_WAIT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) -# @INCLUDE_NEXT@ @NEXT_SYS_WAIT_H@ -#endif - -#ifndef _GL_SYS_WAIT_H -#define _GL_SYS_WAIT_H - -#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) -/* Unix API. */ - -/* The following macros apply to an argument x, that is a status of a process, - as returned by waitpid(). - On nearly all systems, including Linux/x86, WEXITSTATUS are bits 15..8 and - WTERMSIG are bits 7..0, while BeOS uses the opposite. Therefore programs - have to use the abstract macros. */ - -/* For valid x, exactly one of WIFSIGNALED(x), WIFEXITED(x), WIFSTOPPED(x) - is true. */ -# ifndef WIFSIGNALED -# define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f) -# endif -# ifndef WIFEXITED -# define WIFEXITED(x) (WTERMSIG (x) == 0) -# endif -# ifndef WIFSTOPPED -# define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f) -# endif - -/* The termination signal. Only to be accessed if WIFSIGNALED(x) is true. */ -# ifndef WTERMSIG -# define WTERMSIG(x) ((x) & 0x7f) -# endif - -/* The exit status. Only to be accessed if WIFEXITED(x) is true. */ -# ifndef WEXITSTATUS -# define WEXITSTATUS(x) (((x) >> 8) & 0xff) -# endif - -/* True if the process dumped core. Not standardized by POSIX. */ -# ifndef WCOREDUMP -# define WCOREDUMP(x) ((x) & 0x80) -# endif - -# ifdef __cplusplus -extern "C" { -# endif - -/* Declarations of functions. */ - -# ifdef __cplusplus -} -# endif - -#else -/* Native Windows API. */ - -# include - -# define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD) - -/* The following macros apply to an argument x, that is a status of a process, - as returned by waitpid() or, equivalently, _cwait() or GetExitCodeProcess(). - This value is simply an 'int', not composed of bit fields. */ - -/* When an unhandled fatal signal terminates a process, the exit code is 3. */ -# define WIFSIGNALED(x) ((x) == 3) -# define WIFEXITED(x) ((x) != 3) -# define WIFSTOPPED(x) 0 - -/* The signal that terminated a process is not known posthum. */ -# define WTERMSIG(x) SIGTERM - -# define WEXITSTATUS(x) (x) - -/* There are no core dumps. */ -# define WCOREDUMP(x) 0 - -#endif - -#endif /* _GL_SYS_WAIT_H */ -#endif /* _GL_SYS_WAIT_H */ diff --git a/grub-core/gnulib/sysexits.in.h b/grub-core/gnulib/sysexits.in.h index 45255dfa5..fa8db8386 100644 --- a/grub-core/gnulib/sysexits.in.h +++ b/grub-core/gnulib/sysexits.in.h @@ -1,5 +1,5 @@ /* exit() exit codes for some BSD system programs. - Copyright (C) 2003, 2006-2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2006-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,11 +16,12 @@ /* Written by Simon Josefsson based on sysexits(3) man page */ -#ifndef _GL_SYSEXITS_H +#ifndef _@GUARD_PREFIX@_SYSEXITS_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ #if @HAVE_SYSEXITS_H@ @@ -42,8 +43,8 @@ #endif -#ifndef _GL_SYSEXITS_H -#define _GL_SYSEXITS_H +#ifndef _@GUARD_PREFIX@_SYSEXITS_H +#define _@GUARD_PREFIX@_SYSEXITS_H #if !@HAVE_SYSEXITS_H@ @@ -67,5 +68,5 @@ #endif -#endif /* _GL_SYSEXITS_H */ -#endif /* _GL_SYSEXITS_H */ +#endif /* _@GUARD_PREFIX@_SYSEXITS_H */ +#endif /* _@GUARD_PREFIX@_SYSEXITS_H */ diff --git a/grub-core/gnulib/unistd.c b/grub-core/gnulib/unistd.c new file mode 100644 index 000000000..6c6a8e268 --- /dev/null +++ b/grub-core/gnulib/unistd.c @@ -0,0 +1,3 @@ +#include +#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE +#include "unistd.h" diff --git a/grub-core/gnulib/unistd.in.h b/grub-core/gnulib/unistd.in.h index 26a4cbd6a..2ea9af436 100644 --- a/grub-core/gnulib/unistd.in.h +++ b/grub-core/gnulib/unistd.in.h @@ -1,5 +1,5 @@ /* Substitute for and wrapper around . - Copyright (C) 2003-2010 Free Software Foundation, Inc. + Copyright (C) 2003-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,30 +12,14 @@ GNU 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. */ + along with this program; if not, see . */ + +#ifndef _@GUARD_PREFIX@_UNISTD_H #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 +@PRAGMA_COLUMNS@ /* The include_next requires a split double-inclusion guard. */ #if @HAVE_UNISTD_H@ @@ -50,8 +34,8 @@ # undef _GL_INCLUDING_WINSOCK2_H #endif -#if !defined _GL_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H -#define _GL_UNISTD_H +#if !defined _@GUARD_PREFIX@_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H +#define _@GUARD_PREFIX@_UNISTD_H /* NetBSD 5.0 mis-defines NULL. Also get size_t. */ #include @@ -60,32 +44,66 @@ /* 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)) \ + || ((@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK) \ + && defined __CYGWIN__)) \ && ! 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__ +#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) && defined __CYGWIN__ \ + && ! defined __GLIBC__ # include #endif /* mingw fails to declare _exit in . */ -/* mingw, BeOS, Haiku declare environ in , not in . */ +/* mingw, MSVC, BeOS, Haiku declare environ in , not in + . */ /* Solaris declares getcwd not only in but also in . */ +/* OSF Tru64 Unix cannot see gnulib rpl_strtod when system is + included here. */ /* But avoid namespace pollution on glibc systems. */ -#ifndef __GLIBC__ +#if !defined __GLIBC__ && !defined __osf__ +# define __need_system_stdlib_h # include +# undef __need_system_stdlib_h #endif -/* mingw declares getcwd in , not in . */ -#if ((@GNULIB_GETCWD@ || defined GNULIB_POSIXCHECK) \ +/* Native Windows platforms declare chdir, getcwd, rmdir in + and/or , not in . + They also declare access(), chmod(), close(), dup(), dup2(), isatty(), + lseek(), read(), unlink(), write() in . */ +#if ((@GNULIB_CHDIR@ || @GNULIB_GETCWD@ || @GNULIB_RMDIR@ \ + || defined GNULIB_POSIXCHECK) \ && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) +# include /* mingw32, mingw64 */ +# include /* mingw64, MSVC 9 */ +#elif (@GNULIB_CLOSE@ || @GNULIB_DUP@ || @GNULIB_DUP2@ || @GNULIB_ISATTY@ \ + || @GNULIB_LSEEK@ || @GNULIB_READ@ || @GNULIB_UNLINK@ || @GNULIB_WRITE@ \ + || defined GNULIB_POSIXCHECK) \ + && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) # include #endif -#if (@GNULIB_WRITE@ || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \ +/* AIX and OSF/1 5.1 declare getdomainname in , not in . + NonStop Kernel declares gethostname in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if ((@GNULIB_GETDOMAINNAME@ && (defined _AIX || defined __osf__)) \ + || (@GNULIB_GETHOSTNAME@ && defined __TANDEM)) \ + && !defined __GLIBC__ +# include +#endif + +/* MSVC defines off_t in . + May also define off_t to a 64-bit type on native Windows. */ +#if !@HAVE_UNISTD_H@ || @WINDOWS_64_BIT_OFF_T@ +/* Get off_t. */ +# include +#endif + +#if (@GNULIB_READ@ || @GNULIB_WRITE@ \ + || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \ || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK) /* Get ssize_t. */ # include @@ -94,9 +112,15 @@ /* Get getopt(), optarg, optind, opterr, optopt. But avoid namespace pollution on glibc systems. */ #if @GNULIB_UNISTD_H_GETOPT@ && !defined __GLIBC__ && !defined _GL_SYSTEM_GETOPT +# define __need_getopt # include #endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_UNISTD_INLINE +# define _GL_UNISTD_INLINE _GL_INLINE +#endif + /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ /* The definition of _GL_ARG_NONNULL is copied here. */ @@ -104,78 +128,77 @@ /* 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 +/* Hide some function declarations from . */ + +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_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 -# 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 +# if !defined _@GUARD_PREFIX@_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 @@ -211,12 +234,24 @@ _GL_WARN_ON_USE (access, "the access function is a security risk - " #endif +#if @GNULIB_CHDIR@ +_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); +_GL_CXXALIASWARN (chdir); +#elif defined GNULIB_POSIXCHECK +# undef chdir +# if HAVE_RAW_DECL_CHDIR +_GL_WARN_ON_USE (chown, "chdir is not always in - " + "use gnulib module chdir for portability"); +# endif +#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 - . */ + See the POSIX:2008 specification + . */ + See the POSIX:2008 specification + . */ # if @REPLACE_DUP2@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define dup2 rpl_dup2 @@ -355,7 +398,7 @@ extern char **environ; # endif #elif defined GNULIB_POSIXCHECK # if HAVE_RAW_DECL_ENVIRON -static inline char *** +_GL_UNISTD_INLINE char *** rpl_environ (void) { return &environ; @@ -413,8 +456,8 @@ _GL_WARN_ON_USE (faccessat, "faccessat is not portable - " /* 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 - . */ + See the POSIX:2008 specification + . */ # if ! @HAVE_FCHDIR@ _GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); @@ -425,6 +468,10 @@ _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); +# else +# if !@HAVE_DECL_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); +# endif # endif _GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); _GL_CXXALIASWARN (fchdir); @@ -467,11 +514,30 @@ _GL_WARN_ON_USE (fchownat, "fchownat is not portable - " #endif -#if @GNULIB_FSYNC@ +#if @GNULIB_FDATASYNC@ /* Synchronize changes to a file. Return 0 if successful, otherwise -1 and errno set. - See POSIX:2001 specification - . */ + See POSIX:2008 specification + . */ +# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@ +_GL_FUNCDECL_SYS (fdatasync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fdatasync, int, (int fd)); +_GL_CXXALIASWARN (fdatasync); +#elif defined GNULIB_POSIXCHECK +# undef fdatasync +# if HAVE_RAW_DECL_FDATASYNC +_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - " + "use gnulib module fdatasync for portability"); +# endif +#endif + + +#if @GNULIB_FSYNC@ +/* Synchronize changes, including metadata, to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ # if !@HAVE_FSYNC@ _GL_FUNCDECL_SYS (fsync, int, (int fd)); # endif @@ -489,12 +555,21 @@ _GL_WARN_ON_USE (fsync, "fsync is unportable - " #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@ + See the POSIX:2008 specification + . */ +# if @REPLACE_FTRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftruncate +# define ftruncate rpl_ftruncate +# endif +_GL_FUNCDECL_RPL (ftruncate, int, (int fd, off_t length)); +_GL_CXXALIAS_RPL (ftruncate, int, (int fd, off_t length)); +# else +# if !@HAVE_FTRUNCATE@ _GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length)); -# endif +# endif _GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length)); +# endif _GL_CXXALIASWARN (ftruncate); #elif defined GNULIB_POSIXCHECK # undef ftruncate @@ -510,8 +585,8 @@ _GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - " 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 - . + See the POSIX:2008 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 @@ -548,13 +623,21 @@ _GL_WARN_ON_USE (getcwd, "getcwd is unportable - " 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@ +# if @REPLACE_GETDOMAINNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdomainname +# define getdomainname rpl_getdomainname +# endif +_GL_FUNCDECL_RPL (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getdomainname, int, (char *name, size_t len)); +# else +# if !@HAVE_DECL_GETDOMAINNAME@ _GL_FUNCDECL_SYS (getdomainname, int, (char *name, size_t len) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getdomainname, int, (char *name, size_t len)); # 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 @@ -632,7 +715,8 @@ _GL_CXXALIAS_RPL (gethostname, int, (char *name, size_t len)); _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 +/* Need to cast, because on Solaris 10 and OSF/1 5.1 systems, the second + parameter is int len. */ _GL_CXXALIAS_SYS_CAST (gethostname, int, (char *name, size_t len)); # endif @@ -689,13 +773,22 @@ _GL_WARN_ON_USE (getlogin, "getlogin is unportable - " ${LOGNAME-$USER} on Unix platforms, $USERNAME on native Windows platforms. */ -# if !@HAVE_DECL_GETLOGIN_R@ +# if @REPLACE_GETLOGIN_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getlogin_r rpl_getlogin_r +# endif +_GL_FUNCDECL_RPL (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getlogin_r, int, (char *name, size_t size)); +# else +# if !@HAVE_DECL_GETLOGIN_R@ _GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t size) _GL_ARG_NONNULL ((1))); -# endif +# 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)); +# endif _GL_CXXALIASWARN (getlogin_r); #elif defined GNULIB_POSIXCHECK # undef getlogin_r @@ -762,11 +855,14 @@ _GL_CXXALIAS_RPL (getpagesize, int, (void)); # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define getpagesize() _gl_getpagesize () # else -static inline int +# if !GNULIB_defined_getpagesize_function +_GL_UNISTD_INLINE int getpagesize () { return _gl_getpagesize (); } +# define GNULIB_defined_getpagesize_function 1 +# endif # endif # endif # endif @@ -833,12 +929,49 @@ _GL_WARN_ON_USE (endusershell, "endusershell is unportable - " #endif +#if @GNULIB_GROUP_MEMBER@ +/* Determine whether group id is in calling user's group list. */ +# if !@HAVE_GROUP_MEMBER@ +_GL_FUNCDECL_SYS (group_member, int, (gid_t gid)); +# endif +_GL_CXXALIAS_SYS (group_member, int, (gid_t gid)); +_GL_CXXALIASWARN (group_member); +#elif defined GNULIB_POSIXCHECK +# undef group_member +# if HAVE_RAW_DECL_GROUP_MEMBER +_GL_WARN_ON_USE (group_member, "group_member is unportable - " + "use gnulib module group-member for portability"); +# endif +#endif + + +#if @GNULIB_ISATTY@ +# if @REPLACE_ISATTY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef isatty +# define isatty rpl_isatty +# endif +_GL_FUNCDECL_RPL (isatty, int, (int fd)); +_GL_CXXALIAS_RPL (isatty, int, (int fd)); +# else +_GL_CXXALIAS_SYS (isatty, int, (int fd)); +# endif +_GL_CXXALIASWARN (isatty); +#elif defined GNULIB_POSIXCHECK +# undef isatty +# if HAVE_RAW_DECL_ISATTY +_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - " + "use gnulib module isatty 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 - . */ + See the POSIX:2008 specification + . */ # if @REPLACE_LCHOWN@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef lchown @@ -867,8 +1000,8 @@ _GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - " #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 - . */ + See POSIX:2008 specification + . */ # if @REPLACE_LINK@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define link rpl_link @@ -933,8 +1066,8 @@ _GL_WARN_ON_USE (linkat, "linkat is unportable - " #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 - . */ + See the POSIX:2008 specification + . */ # if @REPLACE_LSEEK@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define lseek rpl_lseek @@ -954,6 +1087,24 @@ _GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some " #endif +#if @GNULIB_PIPE@ +/* Create a pipe, defaulting to O_BINARY mode. + 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. */ +# if !@HAVE_PIPE@ +_GL_FUNCDECL_SYS (pipe, int, (int fd[2]) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pipe, int, (int fd[2])); +_GL_CXXALIASWARN (pipe); +#elif defined GNULIB_POSIXCHECK +# undef pipe +# if HAVE_RAW_DECL_PIPE +_GL_WARN_ON_USE (pipe, "pipe is unportable - " + "use gnulib module pipe-posix 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. @@ -986,10 +1137,12 @@ _GL_WARN_ON_USE (pipe2, "pipe2 is unportable - " #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 . */ + set errno and return -1. 0 indicates EOF. + See the POSIX:2008 specification + . */ # if @REPLACE_PREAD@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pread # define pread rpl_pread # endif _GL_FUNCDECL_RPL (pread, ssize_t, @@ -1020,10 +1173,11 @@ _GL_WARN_ON_USE (pread, "pread is unportable - " /* 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 - . */ + POSIX:2008 specification + . */ # if @REPLACE_PWRITE@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pwrite # define pwrite rpl_pwrite # endif _GL_FUNCDECL_RPL (pwrite, ssize_t, @@ -1050,12 +1204,34 @@ _GL_WARN_ON_USE (pwrite, "pwrite is unportable - " #endif +#if @GNULIB_READ@ +/* Read up to COUNT bytes from file descriptor FD into the buffer starting + at BUF. See the POSIX:2008 specification + . */ +# if @REPLACE_READ@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef read +# define read rpl_read +# endif +_GL_FUNCDECL_RPL (read, ssize_t, (int fd, void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (read, ssize_t, (int fd, 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 (read, ssize_t, (int fd, void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (read); +#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 - . */ + See the POSIX:2008 specification + . */ # if @REPLACE_READLINK@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define readlink rpl_readlink @@ -1123,11 +1299,38 @@ _GL_WARN_ON_USE (rmdir, "rmdir is unportable - " #endif +#if @GNULIB_SETHOSTNAME@ +/* Set the host name of the machine. + The host name may or may not be fully qualified. + + Put LEN bytes of NAME into the host name. + Return 0 if successful, otherwise, set errno and return -1. + + Platforms with no ability to set the hostname return -1 and set + errno = ENOSYS. */ +# if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@ +_GL_FUNCDECL_SYS (sethostname, int, (const char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 11 2011-10, Mac OS X 10.5, IRIX 6.5 + and FreeBSD 6.4 the second parameter is int. On Solaris 11 + 2011-10, the first parameter is not const. */ +_GL_CXXALIAS_SYS_CAST (sethostname, int, (const char *name, size_t len)); +_GL_CXXALIASWARN (sethostname); +#elif defined GNULIB_POSIXCHECK +# undef sethostname +# if HAVE_RAW_DECL_SETHOSTNAME +_GL_WARN_ON_USE (sethostname, "sethostname is unportable - " + "use gnulib module sethostname 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 - . */ + See the POSIX:2008 specification + . */ # if @REPLACE_SLEEP@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef sleep @@ -1208,7 +1411,7 @@ _GL_FUNCDECL_RPL (ttyname_r, int, _GL_CXXALIAS_RPL (ttyname_r, int, (int fd, char *buf, size_t buflen)); # else -# if !@HAVE_TTYNAME_R@ +# if !@HAVE_DECL_TTYNAME_R@ _GL_FUNCDECL_SYS (ttyname_r, int, (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); # endif @@ -1276,7 +1479,7 @@ _GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - " /* 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 @@ -1302,9 +1505,9 @@ _GL_WARN_ON_USE (usleep, "usleep is unportable - " #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@ + See the POSIX:2008 specification + . */ +# if @REPLACE_WRITE@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef write # define write rpl_write @@ -1321,6 +1524,7 @@ _GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count)); _GL_CXXALIASWARN (write); #endif +_GL_INLINE_HEADER_END -#endif /* _GL_UNISTD_H */ -#endif /* _GL_UNISTD_H */ +#endif /* _@GUARD_PREFIX@_UNISTD_H */ +#endif /* _@GUARD_PREFIX@_UNISTD_H */ diff --git a/grub-core/gnulib/unitypes.in.h b/grub-core/gnulib/unitypes.in.h new file mode 100644 index 000000000..06eef05ce --- /dev/null +++ b/grub-core/gnulib/unitypes.in.h @@ -0,0 +1,46 @@ +/* Elementary types and macros for the GNU UniString library. + Copyright (C) 2002, 2005-2006, 2009-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNITYPES_H +#define _UNITYPES_H + +/* Get uint8_t, uint16_t, uint32_t. */ +#include + +/* Type representing a Unicode character. */ +typedef uint32_t ucs4_t; + +/* Attribute of a function whose result depends only on the arguments + (not pointers!) and which has no side effects. */ +#ifndef _UC_ATTRIBUTE_CONST +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +# define _UC_ATTRIBUTE_CONST __attribute__ ((__const__)) +# else +# define _UC_ATTRIBUTE_CONST +# endif +#endif + +/* Attribute of a function whose result depends only on the arguments + (possibly pointers) and global memory, and which has no side effects. */ +#ifndef _UC_ATTRIBUTE_PURE +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _UC_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _UC_ATTRIBUTE_PURE +# endif +#endif + +#endif /* _UNITYPES_H */ diff --git a/grub-core/gnulib/uniwidth.in.h b/grub-core/gnulib/uniwidth.in.h new file mode 100644 index 000000000..8931cc9b0 --- /dev/null +++ b/grub-core/gnulib/uniwidth.in.h @@ -0,0 +1,72 @@ +/* Display width functions. + Copyright (C) 2001-2002, 2005, 2007, 2009-2013 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef _UNIWIDTH_H +#define _UNIWIDTH_H + +#include "unitypes.h" + +/* Get size_t. */ +#include + +/* Get locale_charset() declaration. */ +#include "localcharset.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Display width. */ + +/* These functions are locale dependent. The encoding argument identifies + the encoding (e.g. "ISO-8859-2" for Polish). */ + +/* Determine number of column positions required for UC. */ +extern int + uc_width (ucs4_t uc, const char *encoding) + _UC_ATTRIBUTE_PURE; + +/* Determine number of column positions required for first N units + (or fewer if S ends before this) in S. */ +extern int + u8_width (const uint8_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u16_width (const uint16_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u32_width (const uint32_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; + +/* Determine number of column positions required for S. */ +extern int + u8_strwidth (const uint8_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u16_strwidth (const uint16_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u32_strwidth (const uint32_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + +#endif /* _UNIWIDTH_H */ diff --git a/grub-core/gnulib/uniwidth/cjk.h b/grub-core/gnulib/uniwidth/cjk.h new file mode 100644 index 000000000..11b14dfec --- /dev/null +++ b/grub-core/gnulib/uniwidth/cjk.h @@ -0,0 +1,37 @@ +/* Test for CJK encoding. + Copyright (C) 2001-2002, 2005-2007, 2009-2013 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the 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 "streq.h" + +static int +is_cjk_encoding (const char *encoding) +{ + if (0 + /* Legacy Japanese encodings */ + || STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0) + /* Legacy Chinese encodings */ + || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, "GBK", 'G', 'B', 'K', 0, 0, 0, 0, 0, 0) + || STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0) + || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0) + /* Legacy Korean encodings */ + || STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, "CP949", 'C', 'P', '9', '4', '9', 0, 0, 0, 0) + || STREQ_OPT (encoding, "JOHAB", 'J', 'O', 'H', 'A', 'B', 0, 0, 0, 0)) + return 1; + return 0; +} diff --git a/grub-core/gnulib/uniwidth/width.c b/grub-core/gnulib/uniwidth/width.c new file mode 100644 index 000000000..173d0872c --- /dev/null +++ b/grub-core/gnulib/uniwidth/width.c @@ -0,0 +1,368 @@ +/* Determine display width of Unicode character. + Copyright (C) 2001-2002, 2006-2013 Free Software Foundation, Inc. + Written by Bruno Haible , 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the 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 "uniwidth.h" + +#include "cjk.h" + +/* + * Non-spacing attribute table. + * Consists of: + * - Non-spacing characters; generated from PropList.txt or + * "grep '^[^;]*;[^;]*;[^;]*;[^;]*;NSM;' UnicodeData.txt" + * - Format control characters; generated from + * "grep '^[^;]*;[^;]*;Cf;' UnicodeData.txt" + * - Zero width characters; generated from + * "grep '^[^;]*;ZERO WIDTH ' UnicodeData.txt" + */ +static const unsigned char nonspacing_table_data[27*64] = { + /* 0x0000-0x01ff */ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0x0000-0x003f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x0040-0x007f */ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, /* 0x0080-0x00bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00c0-0x00ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x013f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0140-0x017f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0180-0x01bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01c0-0x01ff */ + /* 0x0200-0x03ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0200-0x023f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0240-0x027f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0280-0x02bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x02c0-0x02ff */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x0300-0x033f */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, /* 0x0340-0x037f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0380-0x03bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x03c0-0x03ff */ + /* 0x0400-0x05ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0400-0x043f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0440-0x047f */ + 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0480-0x04bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04c0-0x04ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0500-0x053f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0540-0x057f */ + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, /* 0x0580-0x05bf */ + 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x05c0-0x05ff */ + /* 0x0600-0x07ff */ + 0x0f, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, /* 0x0600-0x063f */ + 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, /* 0x0640-0x067f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0680-0x06bf */ + 0x00, 0x00, 0xc0, 0xbf, 0x9f, 0x3d, 0x00, 0x00, /* 0x06c0-0x06ff */ + 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, /* 0x0700-0x073f */ + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0740-0x077f */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, /* 0x0780-0x07bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, /* 0x07c0-0x07ff */ + /* 0x0800-0x09ff */ + 0x00, 0x00, 0xc0, 0xfb, 0xef, 0x3e, 0x00, 0x00, /* 0x0800-0x083f */ + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 0x0840-0x087f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0880-0x08bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08c0-0x08ff */ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, /* 0x0900-0x093f */ + 0xfe, 0x21, 0xfe, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0940-0x097f */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0980-0x09bf */ + 0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x09c0-0x09ff */ + /* 0x0a00-0x0bff */ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a00-0x0a3f */ + 0x86, 0x39, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, /* 0x0a40-0x0a7f */ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a80-0x0abf */ + 0xbe, 0x21, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0ac0-0x0aff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, /* 0x0b00-0x0b3f */ + 0x1e, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0b40-0x0b7f */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b80-0x0bbf */ + 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0bc0-0x0bff */ + /* 0x0c00-0x0dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, /* 0x0c00-0x0c3f */ + 0xc1, 0x3d, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0c40-0x0c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0c80-0x0cbf */ + 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0cc0-0x0cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d00-0x0d3f */ + 0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0d40-0x0d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d80-0x0dbf */ + 0x00, 0x04, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0dc0-0x0dff */ + /* 0x0e00-0x0fff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x07, /* 0x0e00-0x0e3f */ + 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e40-0x0e7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x1b, /* 0x0e80-0x0ebf */ + 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0ec0-0x0eff */ + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x02, /* 0x0f00-0x0f3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, /* 0x0f40-0x0f7f */ + 0xdf, 0xe0, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x1f, /* 0x0f80-0x0fbf */ + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0fc0-0x0fff */ + /* 0x1000-0x11ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfd, 0x66, /* 0x1000-0x103f */ + 0x00, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x1e, 0x00, /* 0x1040-0x107f */ + 0x64, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, /* 0x1080-0x10bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10c0-0x10ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1100-0x113f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1140-0x117f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1180-0x11bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11c0-0x11ff */ + /* 0x1200-0x13ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1200-0x123f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1240-0x127f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1280-0x12bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x12c0-0x12ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1300-0x133f */ + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, /* 0x1340-0x137f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1380-0x13bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x13c0-0x13ff */ + /* 0x1600-0x17ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1600-0x163f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1640-0x167f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1680-0x16bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16c0-0x16ff */ + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, /* 0x1700-0x173f */ + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, /* 0x1740-0x177f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x3f, /* 0x1780-0x17bf */ + 0x40, 0xfe, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x00, /* 0x17c0-0x17ff */ + /* 0x1800-0x19ff */ + 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1800-0x183f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1840-0x187f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x1880-0x18bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18c0-0x18ff */ + 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x04, 0x0e, /* 0x1900-0x193f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1940-0x197f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1980-0x19bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x19c0-0x19ff */ + /* 0x1a00-0x1bff */ + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, /* 0x1a00-0x1a3f */ + 0x00, 0x00, 0x40, 0x7f, 0xe5, 0x1f, 0xf8, 0x9f, /* 0x1a40-0x1a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a80-0x1abf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1ac0-0x1aff */ + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x17, /* 0x1b00-0x1b3f */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, /* 0x1b40-0x1b7f */ + 0x03, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x00, /* 0x1b80-0x1bbf */ + 0x00, 0x00, 0x00, 0x00, 0x40, 0xa3, 0x03, 0x00, /* 0x1bc0-0x1bff */ + /* 0x1c00-0x1dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xcf, 0x00, /* 0x1c00-0x1c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c40-0x1c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c80-0x1cbf */ + 0x00, 0x00, 0xf7, 0xff, 0xfd, 0x21, 0x00, 0x00, /* 0x1cc0-0x1cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d00-0x1d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d40-0x1d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d80-0x1dbf */ + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, /* 0x1dc0-0x1dff */ + /* 0x2000-0x21ff */ + 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, /* 0x2000-0x203f */ + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, /* 0x2040-0x207f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2080-0x20bf */ + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, /* 0x20c0-0x20ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2100-0x213f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2140-0x217f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2180-0x21bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x21c0-0x21ff */ + /* 0x2c00-0x2dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c00-0x2c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c40-0x2c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c80-0x2cbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, /* 0x2cc0-0x2cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d00-0x2d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x2d40-0x2d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d80-0x2dbf */ + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, /* 0x2dc0-0x2dff */ + /* 0x3000-0x31ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, /* 0x3000-0x303f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3040-0x307f */ + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, /* 0x3080-0x30bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30c0-0x30ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3100-0x313f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3140-0x317f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3180-0x31bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x31c0-0x31ff */ + /* 0xa600-0xa7ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa600-0xa63f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x30, /* 0xa640-0xa67f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa680-0xa6bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, /* 0xa6c0-0xa6ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa700-0xa73f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa740-0xa77f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa780-0xa7bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa7c0-0xa7ff */ + /* 0xa800-0xa9ff */ + 0x44, 0x08, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* 0xa800-0xa83f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa840-0xa87f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa880-0xa8bf */ + 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xa8c0-0xa8ff */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, /* 0xa900-0xa93f */ + 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa940-0xa97f */ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x13, /* 0xa980-0xa9bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa9c0-0xa9ff */ + /* 0xaa00-0xabff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x66, 0x00, /* 0xaa00-0xaa3f */ + 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa40-0xaa7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0xc1, /* 0xaa80-0xaabf */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaac0-0xaaff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab00-0xab3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab40-0xab7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab80-0xabbf */ + 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00, /* 0xabc0-0xabff */ + /* 0xfa00-0xfbff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa00-0xfa3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa40-0xfa7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa80-0xfabf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfac0-0xfaff */ + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, /* 0xfb00-0xfb3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb40-0xfb7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb80-0xfbbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfbc0-0xfbff */ + /* 0xfe00-0xffff */ + 0xff, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, /* 0xfe00-0xfe3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe40-0xfe7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe80-0xfebf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xfec0-0xfeff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff00-0xff3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff40-0xff7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff80-0xffbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, /* 0xffc0-0xffff */ + /* 0x10000-0x101ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10000-0x1003f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10040-0x1007f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10080-0x100bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x100c0-0x100ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10100-0x1013f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10140-0x1017f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10180-0x101bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* 0x101c0-0x101ff */ + /* 0x10a00-0x10bff */ + 0x6e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, /* 0x10a00-0x10a3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10a40-0x10a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10a80-0x10abf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10ac0-0x10aff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b00-0x10b3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b40-0x10b7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b80-0x10bbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10bc0-0x10bff */ + /* 0x11000-0x111ff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0x11000-0x1103f */ + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11040-0x1107f */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x26, /* 0x11080-0x110bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110c0-0x110ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11100-0x1113f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11140-0x1117f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11180-0x111bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x111c0-0x111ff */ + /* 0x1d000-0x1d1ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d000-0x1d03f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d040-0x1d07f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d080-0x1d0bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0c0-0x1d0ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d100-0x1d13f */ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xf8, 0xff, /* 0x1d140-0x1d17f */ + 0xe7, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, /* 0x1d180-0x1d1bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d1c0-0x1d1ff */ + /* 0x1d200-0x1d3ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d200-0x1d23f */ + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d240-0x1d27f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d280-0x1d2bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d2c0-0x1d2ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d300-0x1d33f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d340-0x1d37f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d380-0x1d3bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0x1d3c0-0x1d3ff */ +}; +static const signed char nonspacing_table_ind[240] = { + 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000-0x0fff */ + 8, 9, -1, 10, 11, 12, 13, -1, /* 0x1000-0x1fff */ + 14, -1, -1, -1, -1, -1, 15, -1, /* 0x2000-0x2fff */ + 16, -1, -1, -1, -1, -1, -1, -1, /* 0x3000-0x3fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x4000-0x4fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x5000-0x5fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x6000-0x6fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x7000-0x7fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x8000-0x8fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9000-0x9fff */ + -1, -1, -1, 17, 18, 19, -1, -1, /* 0xa000-0xafff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb000-0xbfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc000-0xcfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd000-0xdfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe000-0xefff */ + -1, -1, -1, -1, -1, 20, -1, 21, /* 0xf000-0xffff */ + 22, -1, -1, -1, -1, 23, -1, -1, /* 0x10000-0x10fff */ + 24, -1, -1, -1, -1, -1, -1, -1, /* 0x11000-0x11fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x12000-0x12fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x13000-0x13fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x14000-0x14fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x15000-0x15fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x16000-0x16fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x17000-0x17fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x18000-0x18fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x19000-0x19fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1a000-0x1afff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1b000-0x1bfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1c000-0x1cfff */ + 25, 26, -1, -1, -1, -1, -1, -1 /* 0x1d000-0x1dfff */ +}; + +/* Determine number of column positions required for UC. */ +int +uc_width (ucs4_t uc, const char *encoding) +{ + /* Test for non-spacing or control character. */ + if ((uc >> 9) < 240) + { + int ind = nonspacing_table_ind[uc >> 9]; + if (ind >= 0) + if ((nonspacing_table_data[64*ind + ((uc >> 3) & 63)] >> (uc & 7)) & 1) + { + if (uc > 0 && uc < 0xa0) + return -1; + else + return 0; + } + } + else if ((uc >> 9) == (0xe0000 >> 9)) + { + if (uc >= 0xe0100) + { + if (uc <= 0xe01ef) + return 0; + } + else + { + if (uc >= 0xe0020 ? uc <= 0xe007f : uc == 0xe0001) + return 0; + } + } + /* Test for double-width character. + * Generated from "grep '^[^;]\{4,5\};[WF]' EastAsianWidth.txt" + * and "grep '^[^;]\{4,5\};[^WF]' EastAsianWidth.txt" + */ + if (uc >= 0x1100 + && ((uc < 0x1160) /* Hangul Jamo */ + || (uc >= 0x2329 && uc < 0x232b) /* Angle Brackets */ + || (uc >= 0x2e80 && uc < 0xa4d0 /* CJK ... Yi */ + && !(uc == 0x303f) && !(uc >= 0x4dc0 && uc < 0x4e00)) + || (uc >= 0xac00 && uc < 0xd7a4) /* Hangul Syllables */ + || (uc >= 0xf900 && uc < 0xfb00) /* CJK Compatibility Ideographs */ + || (uc >= 0xfe10 && uc < 0xfe20) /* Presentation Forms for Vertical */ + || (uc >= 0xfe30 && uc < 0xfe70) /* CJK Compatibility Forms */ + || (uc >= 0xff00 && uc < 0xff61) /* Fullwidth Forms */ + || (uc >= 0xffe0 && uc < 0xffe7) /* Fullwidth Signs */ + || (uc >= 0x20000 && uc <= 0x2ffff) /* Supplementary Ideographic Plane */ + || (uc >= 0x30000 && uc <= 0x3ffff) /* Tertiary Ideographic Plane */ + ) ) + return 2; + /* In ancient CJK encodings, Cyrillic and most other characters are + double-width as well. */ + if (uc >= 0x00A1 && uc < 0xFF61 && uc != 0x20A9 + && is_cjk_encoding (encoding)) + return 2; + return 1; +} diff --git a/grub-core/gnulib/vasnprintf.c b/grub-core/gnulib/vasnprintf.c index e618901ba..8fdab32ea 100644 --- a/grub-core/gnulib/vasnprintf.c +++ b/grub-core/gnulib/vasnprintf.c @@ -1,5 +1,5 @@ /* vsprintf with automatic memory allocation. - Copyright (C) 1999, 2002-2010 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + with this program; if not, see . */ /* This file can be parametrized with the following macros: VASNPRINTF The name of the function being defined. @@ -88,6 +87,8 @@ /* Checked size_t computations. */ #include "xsize.h" +#include "verify.h" + #if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL # include # include "float+.h" @@ -274,10 +275,10 @@ 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 + multithread-safe on glibc systems and Mac OS 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__)) +# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__)) point = nl_langinfo (RADIXCHAR); # elif 1 char pointbuf[5]; @@ -322,11 +323,11 @@ is_infinite_or_zerol (long double x) 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]; +verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS); 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]; +verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS); /* Representation of a bignum >= 0. */ typedef struct @@ -551,32 +552,61 @@ divide (mpn_t a, mpn_t b, mpn_t *q) size_t s; { mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ - s = 31; - if (msd >= 0x10000) + /* Determine s = GMP_LIMB_BITS - integer_length (msd). + Code copied from gnulib's integer_length.c. */ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + s = __builtin_clz (msd); +# else +# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT + if (GMP_LIMB_BITS <= DBL_MANT_BIT) { - msd = msd >> 16; - s -= 16; + /* Use 'double' operations. + Assumes an IEEE 754 'double' implementation. */ +# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1) +# define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { double value; unsigned int word[NWORDS]; } m; + + /* Use a single integer to floating-point conversion. */ + m.value = msd; + + s = GMP_LIMB_BITS + - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK) + - DBL_EXP_BIAS); } - if (msd >= 0x100) + else +# undef NWORDS +# endif { - 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; + 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; + } } +# endif } /* 0 <= s < GMP_LIMB_BITS. Copy b, shifting it left by s bits. */ @@ -883,9 +913,9 @@ decode_long_double (long double x, int *ep, mpn_t *mp) 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 + /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the latter is an integer. */ - /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs. + /* Convert the mantissa (y * 2^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', @@ -933,11 +963,11 @@ decode_long_double (long double x, int *ep, mpn_t *mp) 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 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess + precision. */ if (!(y == 0.0L)) abort (); -#endif +# endif /* Normalise. */ while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) m.nlimbs--; @@ -971,9 +1001,9 @@ decode_double (double x, int *ep, mpn_t *mp) 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 + /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the latter is an integer. */ - /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs. + /* Convert the mantissa (y * 2^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', @@ -1500,7 +1530,7 @@ is_borderline (const char *digits, size_t precision) /* 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 +static 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) @@ -1751,8 +1781,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, return NULL; #define CLEANUP() \ - free (d.dir); \ - if (a.arg) \ + if (d.dir != d.direct_alloc_dir) \ + free (d.dir); \ + if (a.arg != a.direct_alloc_arg) \ free (a.arg); if (PRINTF_FETCHARGS (args, &a) < 0) @@ -2621,7 +2652,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, 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]; + verify (sizeof (TCHAR_T) == 1); TCHAR_T *tmpsrc; DCHAR_T *tmpdst; size_t tmpdst_len; @@ -2782,7 +2813,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (has_width) { # if ENABLE_UNISTDIO - /* Outside POSIX, it's preferrable to compare the width + /* Outside POSIX, it's preferable to compare the width against the number of _characters_ of the converted value. */ w = DCHAR_MBSNLEN (result + length, characters); @@ -4597,6 +4628,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, TCHAR_T *fbp; unsigned int prefix_count; int prefixes[2] IF_LINT (= { 0 }); + int orig_errno; #if !USE_SNPRINTF size_t tmp_length; TCHAR_T tmpbuf[700]; @@ -4751,6 +4783,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, *fbp++ = ' '; if (flags & FLAG_ALT) *fbp++ = '#'; +#if __GLIBC__ >= 2 && !defined __UCLIBC__ + if (flags & FLAG_LOCALIZED) + *fbp++ = 'I'; +#endif if (!pad_ourselves) { if (flags & FLAG_ZERO) @@ -4834,20 +4870,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #endif *fbp = dp->conversion; #if USE_SNPRINTF -# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) +# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((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. + ones - we know that snprintf's return value conforms to + ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and + gl_SNPRINTF_TRUNCATION_C99 pass. 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 + /* On native Windows 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 @@ -4856,7 +4893,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, - 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 + On native Windows systems (such as mingw) where the OS is Windows Vista, the use of %n in format strings by default crashes the program. See and @@ -4900,6 +4937,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, *(TCHAR_T *) (result + length) = '\0'; #endif + orig_errno = errno; + for (;;) { int count = -1; @@ -5284,8 +5323,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, 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]; + verify (sizeof (TCHAR_T) == 1); # if USE_SNPRINTF tmpsrc = (TCHAR_T *) (result + length); # else @@ -5378,7 +5416,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { size_t w; # if ENABLE_UNISTDIO - /* Outside POSIX, it's preferrable to compare the width + /* Outside POSIX, it's preferable to compare the width against the number of _characters_ of the converted value. */ w = DCHAR_MBSNLEN (result + length, count); @@ -5498,6 +5536,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, length += count; break; } + errno = orig_errno; #undef pad_ourselves #undef prec_ourselves } diff --git a/grub-core/gnulib/vasnprintf.h b/grub-core/gnulib/vasnprintf.h index a689bad25..7658f505e 100644 --- a/grub-core/gnulib/vasnprintf.h +++ b/grub-core/gnulib/vasnprintf.h @@ -1,5 +1,5 @@ /* vsprintf with automatic memory allocation. - Copyright (C) 2002-2004, 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2002-2004, 2007-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,8 +12,7 @@ GNU 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. */ + with this program; if not, see . */ #ifndef _VASNPRINTF_H #define _VASNPRINTF_H @@ -24,16 +23,16 @@ /* 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 + We enable _GL_ATTRIBUTE_FORMAT 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 +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ #endif #ifdef __cplusplus @@ -69,9 +68,9 @@ extern "C" { # define vasnprintf rpl_vasnprintf #endif extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4)); extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 3, 0))); + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 0)); #ifdef __cplusplus } diff --git a/grub-core/gnulib/verify.h b/grub-core/gnulib/verify.h index 4ad780c8f..cb8e90b54 100644 --- a/grub-core/gnulib/verify.h +++ b/grub-core/gnulib/verify.h @@ -1,6 +1,6 @@ /* Compile-time assert-like macros. - Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,21 +17,39 @@ /* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ -#ifndef VERIFY_H -# define VERIFY_H 1 +#ifndef _GL_VERIFY_H +# define _GL_VERIFY_H + + +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11. + This is supported by GCC 4.6.0 and later, in C mode, and its use + here generates easier-to-read diagnostics when verify (R) fails. + + Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11. + This will likely be supported by future GCC versions, in C++ mode. + + Use this only with GCC. If we were willing to slow 'configure' + down we could also use it with other compilers, but since this + affects only the quality of diagnostics, why bother? */ +# if (4 < __GNUC__ || (__GNUC__ == 4 && 6 <= __GNUC_MINOR__)) && !defined __cplusplus +# define _GL_HAVE__STATIC_ASSERT 1 +# endif +/* The condition (99 < __GNUC__) is temporary, until we know about the + first G++ release that supports static_assert. */ +# if (99 < __GNUC__) && defined __cplusplus +# define _GL_HAVE_STATIC_ASSERT 1 +# endif /* 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. + If _Static_assert works, verify (R) uses it directly. Similarly, + _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct + that is an operand of sizeof. - Symbols ending in "__" are private to this header. - - The code below uses several ideas. + The code below uses several ideas for C++ compilers, and for C + compilers that do not support _Static_assert: * The first step is ((R) ? 1 : -1). Given an expression R, of integral or boolean or floating-point type, this yields an @@ -39,7 +57,9 @@ constant and nonnegative. * Next this expression W is wrapped in a type - struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }. + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: W; + }. If W is negative, this yields a compile-time error. No compiler can deal with a bit-field of negative size. @@ -53,7 +73,7 @@ void function (int n) { verify (n < 0); } - * For the verify macro, the struct verify_type__ will need to + * For the verify macro, the struct _gl_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, @@ -91,11 +111,11 @@ Which of the following alternatives can be used? extern int dummy [sizeof (struct {...})]; - extern int dummy [sizeof (struct verify_type__ {...})]; + extern int dummy [sizeof (struct _gl_verify_type {...})]; extern void dummy (int [sizeof (struct {...})]); - extern void dummy (int [sizeof (struct verify_type__ {...})]); + extern void dummy (int [sizeof (struct _gl_verify_type {...})]); extern int (*dummy (void)) [sizeof (struct {...})]; - extern int (*dummy (void)) [sizeof (struct verify_type__ {...})]; + extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})]; In the second and sixth case, the struct type is exported to the outer scope; two such declarations therefore collide. GCC warns @@ -105,19 +125,17 @@ 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 + -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. + * This implementation exploits the fact that older versions of GCC, + which do not support _Static_assert, also do not warn about the + last declaration mentioned above. - #if 4 <= __GNUC__ - # define verify(R) [another version to keep GCC happy] - #endif + * GCC warns if -Wnested-externs is enabled and verify() is used + within a function body; but inside a function, you can always + arrange to use verify_expr() instead. * In C++, any struct definition inside sizeof is invalid. Use a template type to work around the problem. */ @@ -140,24 +158,88 @@ possible. */ # define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) -/* Verify requirement R at compile-time, as an integer constant expression. - Return 1. */ +/* Verify requirement R at compile-time, as an integer constant expression + that returns 1. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. */ + +# define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \ + (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC))) # ifdef __cplusplus +# if !GNULIB_defined_struct__gl_verify_type template - struct verify_type__ { unsigned int verify_error_if_negative_size__: w; }; -# define verify_true(R) \ - (!!sizeof (verify_type__<(R) ? 1 : -1>)) + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: w; + }; +# define GNULIB_defined_struct__gl_verify_type 1 +# endif +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + _gl_verify_type<(R) ? 1 : -1> +# elif defined _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { \ + _Static_assert (R, DIAGNOSTIC); \ + int _gl_dummy; \ + } # else -# define verify_true(R) \ - (!!sizeof \ - (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; })) +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; } # endif +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. + + Unfortunately, unlike C11, this implementation must appear as an + ordinary declaration, and cannot appear inside struct { ... }. */ + +# ifdef _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY _Static_assert +# else +# define _GL_VERIFY(R, DIAGNOSTIC) \ + extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ + [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] +# endif + +/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ +# ifdef _GL_STATIC_ASSERT_H +# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert +# define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC) +# endif +# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert +# define static_assert _Static_assert /* C11 requires this #define. */ +# endif +# endif + +/* @assert.h omit start@ */ + +/* 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. */ + +/* Verify requirement R at compile-time, as an integer constant expression. + Return 1. This is equivalent to verify_expr (R, 1). + + verify_true is obsolescent; please use verify_expr instead. */ + +# define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")") + +/* Verify requirement R at compile-time. Return the value of the + expression E. */ + +# define verify_expr(R, E) \ + (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E)) + /* 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)] +# define verify(R) _GL_VERIFY (R, "verify (" #R ")") + +/* @assert.h omit end@ */ #endif diff --git a/grub-core/gnulib/vsnprintf.c b/grub-core/gnulib/vsnprintf.c index d447cc2d5..7d4dfbed9 100644 --- a/grub-core/gnulib/vsnprintf.c +++ b/grub-core/gnulib/vsnprintf.c @@ -1,5 +1,5 @@ /* Formatted output to strings. - Copyright (C) 2004, 2006-2010 Free Software Foundation, Inc. + Copyright (C) 2004, 2006-2013 Free Software Foundation, Inc. Written by Simon Josefsson and Yoann Vandoorselaere . This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ GNU 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. */ + with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include diff --git a/grub-core/gnulib/wchar.in.h b/grub-core/gnulib/wchar.in.h index 88d47dbc0..b6e436279 100644 --- a/grub-core/gnulib/wchar.in.h +++ b/grub-core/gnulib/wchar.in.h @@ -1,6 +1,6 @@ /* A substitute for ISO C99 , for platforms that have issues. - Copyright (C) 2007-2010 Free Software Foundation, Inc. + Copyright (C) 2007-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ /* Written by Eric Blake. */ @@ -29,6 +28,7 @@ #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ #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: @@ -48,17 +48,25 @@ #else /* Normal invocation convention. */ -#ifndef _GL_WCHAR_H +#ifndef _@GUARD_PREFIX@_WCHAR_H #define _GL_ALREADY_INCLUDING_WCHAR_H +#if @HAVE_FEATURES_H@ +# include /* for __GLIBC__ */ +#endif + /* 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 . + In some builds of uClibc, is nonexistent and wchar_t is defined + by . But avoid namespace pollution on glibc systems. */ -#ifndef __GLIBC__ +#if !(defined __GLIBC__ && !defined __UCLIBC__) # include +#endif +#ifndef __GLIBC__ # include # include #endif @@ -72,8 +80,16 @@ #undef _GL_ALREADY_INCLUDING_WCHAR_H -#ifndef _GL_WCHAR_H -#define _GL_WCHAR_H +#ifndef _@GUARD_PREFIX@_WCHAR_H +#define _@GUARD_PREFIX@_WCHAR_H + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + 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 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ @@ -89,6 +105,18 @@ # define WEOF -1 # endif #else +/* MSVC defines wint_t as 'unsigned short' in . + This is too small: ISO C 99 section 7.24.1.(2) says that wint_t must be + "unchanged by default argument promotions". Override it. */ +# if defined _MSC_VER +# if !GNULIB_defined_wint_t +# include +typedef unsigned int rpl_wint_t; +# undef wint_t +# define wint_t rpl_wint_t +# define GNULIB_defined_wint_t 1 +# endif +# endif # ifndef WEOF # define WEOF ((wint_t) -1) # endif @@ -99,10 +127,12 @@ 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@ +# if !GNULIB_defined_mbstate_t typedef int rpl_mbstate_t; -# undef mbstate_t -# define mbstate_t rpl_mbstate_t -# define GNULIB_defined_mbstate_t 1 +# undef mbstate_t +# define mbstate_t rpl_mbstate_t +# define GNULIB_defined_mbstate_t 1 +# endif #endif @@ -113,11 +143,11 @@ typedef int rpl_mbstate_t; # undef btowc # define btowc rpl_btowc # endif -_GL_FUNCDECL_RPL (btowc, wint_t, (int c)); +_GL_FUNCDECL_RPL (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE); _GL_CXXALIAS_RPL (btowc, wint_t, (int c)); # else # if !@HAVE_BTOWC@ -_GL_FUNCDECL_SYS (btowc, wint_t, (int c)); +_GL_FUNCDECL_SYS (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE); # endif _GL_CXXALIAS_SYS (btowc, wint_t, (int c)); # endif @@ -138,12 +168,12 @@ _GL_WARN_ON_USE (btowc, "btowc is unportable - " # undef wctob # define wctob rpl_wctob # endif -_GL_FUNCDECL_RPL (wctob, int, (wint_t wc)); +_GL_FUNCDECL_RPL (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE); _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)); +_GL_FUNCDECL_SYS (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE); # endif _GL_CXXALIAS_SYS (wctob, int, (wint_t wc)); # endif @@ -404,12 +434,12 @@ _GL_WARN_ON_USE (wcsnrtombs, "wcsnrtombs is unportable - " # undef wcwidth # define wcwidth rpl_wcwidth # endif -_GL_FUNCDECL_RPL (wcwidth, int, (wchar_t)); +_GL_FUNCDECL_RPL (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE); _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)); +_GL_FUNCDECL_SYS (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE); # endif _GL_CXXALIAS_SYS (wcwidth, int, (wchar_t)); # endif @@ -423,6 +453,576 @@ _GL_WARN_ON_USE (wcwidth, "wcwidth is unportable - " #endif -#endif /* _GL_WCHAR_H */ -#endif /* _GL_WCHAR_H */ +/* Search N wide characters of S for C. */ +#if @GNULIB_WMEMCHR@ +# if !@HAVE_WMEMCHR@ +_GL_FUNCDECL_SYS (wmemchr, wchar_t *, (const wchar_t *s, wchar_t c, size_t n) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wmemchr (const wchar_t *, wchar_t, size_t); + wchar_t * std::wmemchr (wchar_t *, wchar_t, size_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wmemchr, + wchar_t *, (const wchar_t *, wchar_t, size_t), + const wchar_t *, (const wchar_t *, wchar_t, size_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wmemchr, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +_GL_CXXALIASWARN1 (wmemchr, const wchar_t *, + (const wchar_t *s, wchar_t c, size_t n)); +# else +_GL_CXXALIASWARN (wmemchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wmemchr +# if HAVE_RAW_DECL_WMEMCHR +_GL_WARN_ON_USE (wmemchr, "wmemchr is unportable - " + "use gnulib module wmemchr for portability"); +# endif +#endif + + +/* Compare N wide characters of S1 and S2. */ +#if @GNULIB_WMEMCMP@ +# if !@HAVE_WMEMCMP@ +_GL_FUNCDECL_SYS (wmemcmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wmemcmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wmemcmp); +#elif defined GNULIB_POSIXCHECK +# undef wmemcmp +# if HAVE_RAW_DECL_WMEMCMP +_GL_WARN_ON_USE (wmemcmp, "wmemcmp is unportable - " + "use gnulib module wmemcmp for portability"); +# endif +#endif + + +/* Copy N wide characters of SRC to DEST. */ +#if @GNULIB_WMEMCPY@ +# if !@HAVE_WMEMCPY@ +_GL_FUNCDECL_SYS (wmemcpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemcpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wmemcpy); +#elif defined GNULIB_POSIXCHECK +# undef wmemcpy +# if HAVE_RAW_DECL_WMEMCPY +_GL_WARN_ON_USE (wmemcpy, "wmemcpy is unportable - " + "use gnulib module wmemcpy for portability"); +# endif +#endif + + +/* Copy N wide characters of SRC to DEST, guaranteeing correct behavior for + overlapping memory areas. */ +#if @GNULIB_WMEMMOVE@ +# if !@HAVE_WMEMMOVE@ +_GL_FUNCDECL_SYS (wmemmove, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemmove, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wmemmove); +#elif defined GNULIB_POSIXCHECK +# undef wmemmove +# if HAVE_RAW_DECL_WMEMMOVE +_GL_WARN_ON_USE (wmemmove, "wmemmove is unportable - " + "use gnulib module wmemmove for portability"); +# endif +#endif + + +/* Set N wide characters of S to C. */ +#if @GNULIB_WMEMSET@ +# if !@HAVE_WMEMSET@ +_GL_FUNCDECL_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +_GL_CXXALIASWARN (wmemset); +#elif defined GNULIB_POSIXCHECK +# undef wmemset +# if HAVE_RAW_DECL_WMEMSET +_GL_WARN_ON_USE (wmemset, "wmemset is unportable - " + "use gnulib module wmemset for portability"); +# endif +#endif + + +/* Return the number of wide characters in S. */ +#if @GNULIB_WCSLEN@ +# if !@HAVE_WCSLEN@ +_GL_FUNCDECL_SYS (wcslen, size_t, (const wchar_t *s) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcslen, size_t, (const wchar_t *s)); +_GL_CXXALIASWARN (wcslen); +#elif defined GNULIB_POSIXCHECK +# undef wcslen +# if HAVE_RAW_DECL_WCSLEN +_GL_WARN_ON_USE (wcslen, "wcslen is unportable - " + "use gnulib module wcslen for portability"); +# endif +#endif + + +/* Return the number of wide characters in S, but at most MAXLEN. */ +#if @GNULIB_WCSNLEN@ +# if !@HAVE_WCSNLEN@ +_GL_FUNCDECL_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen)); +_GL_CXXALIASWARN (wcsnlen); +#elif defined GNULIB_POSIXCHECK +# undef wcsnlen +# if HAVE_RAW_DECL_WCSNLEN +_GL_WARN_ON_USE (wcsnlen, "wcsnlen is unportable - " + "use gnulib module wcsnlen for portability"); +# endif +#endif + + +/* Copy SRC to DEST. */ +#if @GNULIB_WCSCPY@ +# if !@HAVE_WCSCPY@ +_GL_FUNCDECL_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcscpy); +#elif defined GNULIB_POSIXCHECK +# undef wcscpy +# if HAVE_RAW_DECL_WCSCPY +_GL_WARN_ON_USE (wcscpy, "wcscpy is unportable - " + "use gnulib module wcscpy for portability"); +# endif +#endif + + +/* Copy SRC to DEST, returning the address of the terminating L'\0' in DEST. */ +#if @GNULIB_WCPCPY@ +# if !@HAVE_WCPCPY@ +_GL_FUNCDECL_SYS (wcpcpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcpcpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcpcpy); +#elif defined GNULIB_POSIXCHECK +# undef wcpcpy +# if HAVE_RAW_DECL_WCPCPY +_GL_WARN_ON_USE (wcpcpy, "wcpcpy is unportable - " + "use gnulib module wcpcpy for portability"); +# endif +#endif + + +/* Copy no more than N wide characters of SRC to DEST. */ +#if @GNULIB_WCSNCPY@ +# if !@HAVE_WCSNCPY@ +_GL_FUNCDECL_SYS (wcsncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcsncpy); +#elif defined GNULIB_POSIXCHECK +# undef wcsncpy +# if HAVE_RAW_DECL_WCSNCPY +_GL_WARN_ON_USE (wcsncpy, "wcsncpy is unportable - " + "use gnulib module wcsncpy for portability"); +# endif +#endif + + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +#if @GNULIB_WCPNCPY@ +# if !@HAVE_WCPNCPY@ +_GL_FUNCDECL_SYS (wcpncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcpncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcpncpy); +#elif defined GNULIB_POSIXCHECK +# undef wcpncpy +# if HAVE_RAW_DECL_WCPNCPY +_GL_WARN_ON_USE (wcpncpy, "wcpncpy is unportable - " + "use gnulib module wcpncpy for portability"); +# endif +#endif + + +/* Append SRC onto DEST. */ +#if @GNULIB_WCSCAT@ +# if !@HAVE_WCSCAT@ +_GL_FUNCDECL_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcscat); +#elif defined GNULIB_POSIXCHECK +# undef wcscat +# if HAVE_RAW_DECL_WCSCAT +_GL_WARN_ON_USE (wcscat, "wcscat is unportable - " + "use gnulib module wcscat for portability"); +# endif +#endif + + +/* Append no more than N wide characters of SRC onto DEST. */ +#if @GNULIB_WCSNCAT@ +# if !@HAVE_WCSNCAT@ +_GL_FUNCDECL_SYS (wcsncat, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsncat, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcsncat); +#elif defined GNULIB_POSIXCHECK +# undef wcsncat +# if HAVE_RAW_DECL_WCSNCAT +_GL_WARN_ON_USE (wcsncat, "wcsncat is unportable - " + "use gnulib module wcsncat for portability"); +# endif +#endif + + +/* Compare S1 and S2. */ +#if @GNULIB_WCSCMP@ +# if !@HAVE_WCSCMP@ +_GL_FUNCDECL_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscmp); +#elif defined GNULIB_POSIXCHECK +# undef wcscmp +# if HAVE_RAW_DECL_WCSCMP +_GL_WARN_ON_USE (wcscmp, "wcscmp is unportable - " + "use gnulib module wcscmp for portability"); +# endif +#endif + + +/* Compare no more than N wide characters of S1 and S2. */ +#if @GNULIB_WCSNCMP@ +# if !@HAVE_WCSNCMP@ +_GL_FUNCDECL_SYS (wcsncmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsncmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsncmp); +#elif defined GNULIB_POSIXCHECK +# undef wcsncmp +# if HAVE_RAW_DECL_WCSNCMP +_GL_WARN_ON_USE (wcsncmp, "wcsncmp is unportable - " + "use gnulib module wcsncmp for portability"); +# endif +#endif + + +/* Compare S1 and S2, ignoring case. */ +#if @GNULIB_WCSCASECMP@ +# if !@HAVE_WCSCASECMP@ +_GL_FUNCDECL_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscasecmp); +#elif defined GNULIB_POSIXCHECK +# undef wcscasecmp +# if HAVE_RAW_DECL_WCSCASECMP +_GL_WARN_ON_USE (wcscasecmp, "wcscasecmp is unportable - " + "use gnulib module wcscasecmp for portability"); +# endif +#endif + + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +#if @GNULIB_WCSNCASECMP@ +# if !@HAVE_WCSNCASECMP@ +_GL_FUNCDECL_SYS (wcsncasecmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsncasecmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsncasecmp); +#elif defined GNULIB_POSIXCHECK +# undef wcsncasecmp +# if HAVE_RAW_DECL_WCSNCASECMP +_GL_WARN_ON_USE (wcsncasecmp, "wcsncasecmp is unportable - " + "use gnulib module wcsncasecmp for portability"); +# endif +#endif + + +/* Compare S1 and S2, both interpreted as appropriate to the LC_COLLATE + category of the current locale. */ +#if @GNULIB_WCSCOLL@ +# if !@HAVE_WCSCOLL@ +_GL_FUNCDECL_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2)); +# endif +_GL_CXXALIAS_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscoll); +#elif defined GNULIB_POSIXCHECK +# undef wcscoll +# if HAVE_RAW_DECL_WCSCOLL +_GL_WARN_ON_USE (wcscoll, "wcscoll is unportable - " + "use gnulib module wcscoll for portability"); +# endif +#endif + + +/* Transform S2 into array pointed to by S1 such that if wcscmp is applied + to two transformed strings the result is the as applying 'wcscoll' to the + original strings. */ +#if @GNULIB_WCSXFRM@ +# if !@HAVE_WCSXFRM@ +_GL_FUNCDECL_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsxfrm); +#elif defined GNULIB_POSIXCHECK +# undef wcsxfrm +# if HAVE_RAW_DECL_WCSXFRM +_GL_WARN_ON_USE (wcsxfrm, "wcsxfrm is unportable - " + "use gnulib module wcsxfrm for portability"); +# endif +#endif + + +/* Duplicate S, returning an identical malloc'd string. */ +#if @GNULIB_WCSDUP@ +# if !@HAVE_WCSDUP@ +_GL_FUNCDECL_SYS (wcsdup, wchar_t *, (const wchar_t *s)); +# endif +_GL_CXXALIAS_SYS (wcsdup, wchar_t *, (const wchar_t *s)); +_GL_CXXALIASWARN (wcsdup); +#elif defined GNULIB_POSIXCHECK +# undef wcsdup +# if HAVE_RAW_DECL_WCSDUP +_GL_WARN_ON_USE (wcsdup, "wcsdup is unportable - " + "use gnulib module wcsdup for portability"); +# endif +#endif + + +/* Find the first occurrence of WC in WCS. */ +#if @GNULIB_WCSCHR@ +# if !@HAVE_WCSCHR@ +_GL_FUNCDECL_SYS (wcschr, wchar_t *, (const wchar_t *wcs, wchar_t wc) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcschr (const wchar_t *, wchar_t); + wchar_t * std::wcschr (wchar_t *, wchar_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcschr, + wchar_t *, (const wchar_t *, wchar_t), + const wchar_t *, (const wchar_t *, wchar_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcschr, wchar_t *, (wchar_t *wcs, wchar_t wc)); +_GL_CXXALIASWARN1 (wcschr, const wchar_t *, (const wchar_t *wcs, wchar_t wc)); +# else +_GL_CXXALIASWARN (wcschr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcschr +# if HAVE_RAW_DECL_WCSCHR +_GL_WARN_ON_USE (wcschr, "wcschr is unportable - " + "use gnulib module wcschr for portability"); +# endif +#endif + + +/* Find the last occurrence of WC in WCS. */ +#if @GNULIB_WCSRCHR@ +# if !@HAVE_WCSRCHR@ +_GL_FUNCDECL_SYS (wcsrchr, wchar_t *, (const wchar_t *wcs, wchar_t wc) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcsrchr (const wchar_t *, wchar_t); + wchar_t * std::wcsrchr (wchar_t *, wchar_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcsrchr, + wchar_t *, (const wchar_t *, wchar_t), + const wchar_t *, (const wchar_t *, wchar_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcsrchr, wchar_t *, (wchar_t *wcs, wchar_t wc)); +_GL_CXXALIASWARN1 (wcsrchr, const wchar_t *, (const wchar_t *wcs, wchar_t wc)); +# else +_GL_CXXALIASWARN (wcsrchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcsrchr +# if HAVE_RAW_DECL_WCSRCHR +_GL_WARN_ON_USE (wcsrchr, "wcsrchr is unportable - " + "use gnulib module wcsrchr for portability"); +# endif +#endif + + +/* Return the length of the initial segmet of WCS which consists entirely + of wide characters not in REJECT. */ +#if @GNULIB_WCSCSPN@ +# if !@HAVE_WCSCSPN@ +_GL_FUNCDECL_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject)); +_GL_CXXALIASWARN (wcscspn); +#elif defined GNULIB_POSIXCHECK +# undef wcscspn +# if HAVE_RAW_DECL_WCSCSPN +_GL_WARN_ON_USE (wcscspn, "wcscspn is unportable - " + "use gnulib module wcscspn for portability"); +# endif +#endif + + +/* Return the length of the initial segmet of WCS which consists entirely + of wide characters in ACCEPT. */ +#if @GNULIB_WCSSPN@ +# if !@HAVE_WCSSPN@ +_GL_FUNCDECL_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept)); +_GL_CXXALIASWARN (wcsspn); +#elif defined GNULIB_POSIXCHECK +# undef wcsspn +# if HAVE_RAW_DECL_WCSSPN +_GL_WARN_ON_USE (wcsspn, "wcsspn is unportable - " + "use gnulib module wcsspn for portability"); +# endif +#endif + + +/* Find the first occurrence in WCS of any character in ACCEPT. */ +#if @GNULIB_WCSPBRK@ +# if !@HAVE_WCSPBRK@ +_GL_FUNCDECL_SYS (wcspbrk, wchar_t *, + (const wchar_t *wcs, const wchar_t *accept) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcspbrk (const wchar_t *, const wchar_t *); + wchar_t * std::wcspbrk (wchar_t *, const wchar_t *); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcspbrk, + wchar_t *, (const wchar_t *, const wchar_t *), + const wchar_t *, (const wchar_t *, const wchar_t *)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcspbrk, wchar_t *, + (wchar_t *wcs, const wchar_t *accept)); +_GL_CXXALIASWARN1 (wcspbrk, const wchar_t *, + (const wchar_t *wcs, const wchar_t *accept)); +# else +_GL_CXXALIASWARN (wcspbrk); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcspbrk +# if HAVE_RAW_DECL_WCSPBRK +_GL_WARN_ON_USE (wcspbrk, "wcspbrk is unportable - " + "use gnulib module wcspbrk for portability"); +# endif +#endif + + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +#if @GNULIB_WCSSTR@ +# if !@HAVE_WCSSTR@ +_GL_FUNCDECL_SYS (wcsstr, wchar_t *, + (const wchar_t *haystack, const wchar_t *needle) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcsstr (const wchar_t *, const wchar_t *); + wchar_t * std::wcsstr (wchar_t *, const wchar_t *); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcsstr, + wchar_t *, (const wchar_t *, const wchar_t *), + const wchar_t *, (const wchar_t *, const wchar_t *)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcsstr, wchar_t *, + (wchar_t *haystack, const wchar_t *needle)); +_GL_CXXALIASWARN1 (wcsstr, const wchar_t *, + (const wchar_t *haystack, const wchar_t *needle)); +# else +_GL_CXXALIASWARN (wcsstr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcsstr +# if HAVE_RAW_DECL_WCSSTR +_GL_WARN_ON_USE (wcsstr, "wcsstr is unportable - " + "use gnulib module wcsstr for portability"); +# endif +#endif + + +/* Divide WCS into tokens separated by characters in DELIM. */ +#if @GNULIB_WCSTOK@ +# if !@HAVE_WCSTOK@ +_GL_FUNCDECL_SYS (wcstok, wchar_t *, + (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)); +# endif +_GL_CXXALIAS_SYS (wcstok, wchar_t *, + (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)); +_GL_CXXALIASWARN (wcstok); +#elif defined GNULIB_POSIXCHECK +# undef wcstok +# if HAVE_RAW_DECL_WCSTOK +_GL_WARN_ON_USE (wcstok, "wcstok is unportable - " + "use gnulib module wcstok for portability"); +# endif +#endif + + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +#if @GNULIB_WCSWIDTH@ +# if @REPLACE_WCSWIDTH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcswidth +# define wcswidth rpl_wcswidth +# endif +_GL_FUNCDECL_RPL (wcswidth, int, (const wchar_t *s, size_t n) + _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wcswidth, int, (const wchar_t *s, size_t n)); +# else +# if !@HAVE_WCSWIDTH@ +_GL_FUNCDECL_SYS (wcswidth, int, (const wchar_t *s, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcswidth, int, (const wchar_t *s, size_t n)); +# endif +_GL_CXXALIASWARN (wcswidth); +#elif defined GNULIB_POSIXCHECK +# undef wcswidth +# if HAVE_RAW_DECL_WCSWIDTH +_GL_WARN_ON_USE (wcswidth, "wcswidth is unportable - " + "use gnulib module wcswidth for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_WCHAR_H */ +#endif /* _@GUARD_PREFIX@_WCHAR_H */ #endif diff --git a/grub-core/gnulib/wcrtomb.c b/grub-core/gnulib/wcrtomb.c index e7345f698..da42809bc 100644 --- a/grub-core/gnulib/wcrtomb.c +++ b/grub-core/gnulib/wcrtomb.c @@ -1,5 +1,5 @@ /* Convert wide character to multibyte character. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2013 Free Software Foundation, Inc. Written by Bruno Haible , 2008. This program is free software: you can redistribute it and/or modify diff --git a/grub-core/gnulib/wctype-h.c b/grub-core/gnulib/wctype-h.c new file mode 100644 index 000000000..bb5f847e3 --- /dev/null +++ b/grub-core/gnulib/wctype-h.c @@ -0,0 +1,4 @@ +/* Normally this would be wctype.c, but that name's already taken. */ +#include +#define _GL_WCTYPE_INLINE _GL_EXTERN_INLINE +#include "wctype.h" diff --git a/grub-core/gnulib/wctype.in.h b/grub-core/gnulib/wctype.in.h index 12c8975fe..0cd02d5a3 100644 --- a/grub-core/gnulib/wctype.in.h +++ b/grub-core/gnulib/wctype.in.h @@ -1,6 +1,6 @@ /* A substitute for ISO C99 , for platforms that lack it. - Copyright (C) 2006-2010 Free Software Foundation, Inc. + Copyright (C) 2006-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ /* Written by Bruno Haible and Paul Eggert. */ @@ -26,11 +25,12 @@ * wctrans_t, and wctype_t are not yet implemented. */ -#ifndef _GL_WCTYPE_H +#ifndef _@GUARD_PREFIX@_WCTYPE_H #if __GNUC__ >= 3 @PRAGMA_SYSTEM_HEADER@ #endif +@PRAGMA_COLUMNS@ #if @HAVE_WINT_T@ /* Solaris 2.5 has a bug: must be included before . @@ -51,13 +51,31 @@ # @INCLUDE_NEXT@ @NEXT_WCTYPE_H@ #endif -#ifndef _GL_WCTYPE_H -#define _GL_WCTYPE_H +#ifndef _@GUARD_PREFIX@_WCTYPE_H +#define _@GUARD_PREFIX@_WCTYPE_H + +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_WCTYPE_INLINE +# define _GL_WCTYPE_INLINE _GL_INLINE +#endif /* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ /* The definition of _GL_WARN_ON_USE is copied here. */ +/* Solaris 2.6 includes which includes which + #defines a number of identifiers in the application namespace. Revert + these #defines. */ +#ifdef __sun +# undef multibyte +# undef eucw1 +# undef eucw2 +# undef eucw3 +# undef scrw1 +# undef scrw2 +# undef scrw3 +#endif + /* Define wint_t and WEOF. (Also done in wchar.in.h.) */ #if !@HAVE_WINT_T@ && !defined wint_t # define wint_t int @@ -65,153 +83,171 @@ # define WEOF -1 # endif #else +/* MSVC defines wint_t as 'unsigned short' in . + This is too small: ISO C 99 section 7.24.1.(2) says that wint_t must be + "unchanged by default argument promotions". Override it. */ +# if defined _MSC_VER +# if !GNULIB_defined_wint_t +# include +typedef unsigned int rpl_wint_t; +# undef wint_t +# define wint_t rpl_wint_t +# define GNULIB_defined_wint_t 1 +# endif +# endif # ifndef WEOF # define WEOF ((wint_t) -1) # endif #endif +#if !GNULIB_defined_wctype_functions + /* 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@ +# 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 +# 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 +# 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 +# endif +# endif +# if @REPLACE_TOWLOWER@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towlower rpl_towlower +# define towupper rpl_towupper +# endif # endif -# endif -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswalnum -# else +# else iswalnum -# endif +# endif (wint_t wc) { return ((wc >= '0' && wc <= '9') || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')); } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswalpha -# else +# else iswalpha -# endif +# endif (wint_t wc) { return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswblank -# else +# else iswblank -# endif +# endif (wint_t wc) { return wc == ' ' || wc == '\t'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswcntrl -# else +# else iswcntrl -# endif +# endif (wint_t wc) { return (wc & ~0x1f) == 0 || wc == 0x7f; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswdigit -# else +# else iswdigit -# endif +# endif (wint_t wc) { return wc >= '0' && wc <= '9'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswgraph -# else +# else iswgraph -# endif +# endif (wint_t wc) { return wc >= '!' && wc <= '~'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswlower -# else +# else iswlower -# endif +# endif (wint_t wc) { return wc >= 'a' && wc <= 'z'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswprint -# else +# else iswprint -# endif +# endif (wint_t wc) { return wc >= ' ' && wc <= '~'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswpunct -# else +# else iswpunct -# endif +# endif (wint_t wc) { return (wc >= '!' && wc <= '~' @@ -219,86 +255,78 @@ iswpunct || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'))); } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswspace -# else +# else iswspace -# endif +# endif (wint_t wc) { return (wc == ' ' || wc == '\t' || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r'); } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswupper -# else +# else iswupper -# endif +# endif (wint_t wc) { return wc >= 'A' && wc <= 'Z'; } -static inline int -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ rpl_iswxdigit -# else +# else iswxdigit -# endif +# endif (wint_t wc) { return ((wc >= '0' && wc <= '9') || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F')); } -static inline wint_t -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE wint_t +# if @REPLACE_TOWLOWER@ rpl_towlower -# else +# else towlower -# endif +# endif (wint_t wc) { return (wc >= 'A' && wc <= 'Z' ? wc - 'A' + 'a' : wc); } -static inline wint_t -# if @REPLACE_ISWCNTRL@ +_GL_WCTYPE_INLINE wint_t +# if @REPLACE_TOWLOWER@ rpl_towupper -# else +# else towupper -# endif +# endif (wint_t wc) { return (wc >= 'a' && wc <= 'z' ? wc - 'a' + 'A' : wc); } -#elif ! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@ +# elif @GNULIB_ISWBLANK@ && (! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@) /* Only the iswblank function is missing. */ -# if @REPLACE_ISWBLANK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define iswblank rpl_iswblank +# if @REPLACE_ISWBLANK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iswblank rpl_iswblank +# endif +_GL_FUNCDECL_RPL (iswblank, int, (wint_t wc)); +# else +_GL_FUNCDECL_SYS (iswblank, int, (wint_t wc)); # endif + # endif -static inline int -# if @REPLACE_ISWBLANK@ -rpl_iswblank -# else -iswblank -# endif - (wint_t wc) -{ - return wc == ' ' || wc == '\t'; -} - -#endif - -#if defined __MINGW32__ +# 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 @@ -313,30 +341,32 @@ iswblank 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 +_GL_WCTYPE_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 +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towlower rpl_towlower +# endif -static inline wint_t +_GL_WCTYPE_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 +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towupper rpl_towupper +# endif -#endif /* __MINGW32__ */ +# endif /* __MINGW32__ */ + +# define GNULIB_defined_wctype_functions 1 +#endif #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)); @@ -349,11 +379,6 @@ _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)); @@ -366,7 +391,6 @@ _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); @@ -377,7 +401,55 @@ _GL_CXXALIASWARN (iswspace); _GL_CXXALIASWARN (iswupper); _GL_CXXALIASWARN (iswxdigit); -#if @REPLACE_ISWCNTRL@ || defined __MINGW32__ +#if @GNULIB_ISWBLANK@ +# if @REPLACE_ISWCNTRL@ || @REPLACE_ISWBLANK@ +_GL_CXXALIAS_RPL (iswblank, int, (wint_t wc)); +# else +_GL_CXXALIAS_SYS (iswblank, int, (wint_t wc)); +# endif +_GL_CXXALIASWARN (iswblank); +#endif + +#if !@HAVE_WCTYPE_T@ +# if !GNULIB_defined_wctype_t +typedef void * wctype_t; +# define GNULIB_defined_wctype_t 1 +# endif +#endif + +/* Get a descriptor for a wide character property. */ +#if @GNULIB_WCTYPE@ +# if !@HAVE_WCTYPE_T@ +_GL_FUNCDECL_SYS (wctype, wctype_t, (const char *name)); +# endif +_GL_CXXALIAS_SYS (wctype, wctype_t, (const char *name)); +_GL_CXXALIASWARN (wctype); +#elif defined GNULIB_POSIXCHECK +# undef wctype +# if HAVE_RAW_DECL_WCTYPE +_GL_WARN_ON_USE (wctype, "wctype is unportable - " + "use gnulib module wctype for portability"); +# endif +#endif + +/* Test whether a wide character has a given property. + The argument WC must be either a wchar_t value or WEOF. + The argument DESC must have been returned by the wctype() function. */ +#if @GNULIB_ISWCTYPE@ +# if !@HAVE_WCTYPE_T@ +_GL_FUNCDECL_SYS (iswctype, int, (wint_t wc, wctype_t desc)); +# endif +_GL_CXXALIAS_SYS (iswctype, int, (wint_t wc, wctype_t desc)); +_GL_CXXALIASWARN (iswctype); +#elif defined GNULIB_POSIXCHECK +# undef iswctype +# if HAVE_RAW_DECL_ISWCTYPE +_GL_WARN_ON_USE (iswctype, "iswctype is unportable - " + "use gnulib module iswctype for portability"); +# endif +#endif + +#if @REPLACE_TOWLOWER@ || defined __MINGW32__ _GL_CXXALIAS_RPL (towlower, wint_t, (wint_t wc)); _GL_CXXALIAS_RPL (towupper, wint_t, (wint_t wc)); #else @@ -387,6 +459,46 @@ _GL_CXXALIAS_SYS (towupper, wint_t, (wint_t wc)); _GL_CXXALIASWARN (towlower); _GL_CXXALIASWARN (towupper); +#if !@HAVE_WCTRANS_T@ +# if !GNULIB_defined_wctrans_t +typedef void * wctrans_t; +# define GNULIB_defined_wctrans_t 1 +# endif +#endif -#endif /* _GL_WCTYPE_H */ -#endif /* _GL_WCTYPE_H */ +/* Get a descriptor for a wide character case conversion. */ +#if @GNULIB_WCTRANS@ +# if !@HAVE_WCTRANS_T@ +_GL_FUNCDECL_SYS (wctrans, wctrans_t, (const char *name)); +# endif +_GL_CXXALIAS_SYS (wctrans, wctrans_t, (const char *name)); +_GL_CXXALIASWARN (wctrans); +#elif defined GNULIB_POSIXCHECK +# undef wctrans +# if HAVE_RAW_DECL_WCTRANS +_GL_WARN_ON_USE (wctrans, "wctrans is unportable - " + "use gnulib module wctrans for portability"); +# endif +#endif + +/* Perform a given case conversion on a wide character. + The argument WC must be either a wchar_t value or WEOF. + The argument DESC must have been returned by the wctrans() function. */ +#if @GNULIB_TOWCTRANS@ +# if !@HAVE_WCTRANS_T@ +_GL_FUNCDECL_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc)); +# endif +_GL_CXXALIAS_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc)); +_GL_CXXALIASWARN (towctrans); +#elif defined GNULIB_POSIXCHECK +# undef towctrans +# if HAVE_RAW_DECL_TOWCTRANS +_GL_WARN_ON_USE (towctrans, "towctrans is unportable - " + "use gnulib module towctrans for portability"); +# endif +#endif + +_GL_INLINE_HEADER_END + +#endif /* _@GUARD_PREFIX@_WCTYPE_H */ +#endif /* _@GUARD_PREFIX@_WCTYPE_H */ diff --git a/grub-core/gnulib/wcwidth.c b/grub-core/gnulib/wcwidth.c new file mode 100644 index 000000000..253fcaa65 --- /dev/null +++ b/grub-core/gnulib/wcwidth.c @@ -0,0 +1,50 @@ +/* Determine the number of screen columns needed for a character. + Copyright (C) 2006-2007, 2010-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* Get iswprint. */ +#include + +#include "localcharset.h" +#include "streq.h" +#include "uniwidth.h" + +int +wcwidth (wchar_t wc) +#undef wcwidth +{ + /* In UTF-8 locales, use a Unicode aware width function. */ + const char *encoding = locale_charset (); + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0 ,0)) + { + /* We assume that in a UTF-8 locale, a wide character is the same as a + Unicode character. */ + return uc_width (wc, encoding); + } + else + { + /* Otherwise, fall back to the system's wcwidth function. */ +#if HAVE_WCWIDTH + return wcwidth (wc); +#else + return wc == 0 ? 0 : iswprint (wc) ? 1 : -1; +#endif + } +} diff --git a/grub-core/gnulib/xsize.c b/grub-core/gnulib/xsize.c new file mode 100644 index 000000000..4b4914c2c --- /dev/null +++ b/grub-core/gnulib/xsize.c @@ -0,0 +1,3 @@ +#include +#define XSIZE_INLINE _GL_EXTERN_INLINE +#include "xsize.h" diff --git a/grub-core/gnulib/xsize.h b/grub-core/gnulib/xsize.h index fbd63290d..2922f3530 100644 --- a/grub-core/gnulib/xsize.h +++ b/grub-core/gnulib/xsize.h @@ -1,6 +1,6 @@ /* xsize.h -- Checked size_t computations. - Copyright (C) 2003, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2003, 2008-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,7 @@ GNU 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. */ + along with this program; if not, see . */ #ifndef _XSIZE_H #define _XSIZE_H @@ -28,6 +27,11 @@ # include #endif +_GL_INLINE_HEADER_BEGIN +#ifndef XSIZE_INLINE +# define XSIZE_INLINE _GL_INLINE +#endif + /* The size of memory objects is often computed through expressions of type size_t. Example: void* p = malloc (header_size + n * element_size). @@ -49,7 +53,7 @@ ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) /* Sum of two sizes, with overflow check. */ -static inline size_t +XSIZE_INLINE size_t #if __GNUC__ >= 3 __attribute__ ((__pure__)) #endif @@ -60,7 +64,7 @@ xsum (size_t size1, size_t size2) } /* Sum of three sizes, with overflow check. */ -static inline size_t +XSIZE_INLINE size_t #if __GNUC__ >= 3 __attribute__ ((__pure__)) #endif @@ -70,7 +74,7 @@ xsum3 (size_t size1, size_t size2, size_t size3) } /* Sum of four sizes, with overflow check. */ -static inline size_t +XSIZE_INLINE size_t #if __GNUC__ >= 3 __attribute__ ((__pure__)) #endif @@ -80,7 +84,7 @@ xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) } /* Maximum of two sizes, with overflow check. */ -static inline size_t +XSIZE_INLINE size_t #if __GNUC__ >= 3 __attribute__ ((__pure__)) #endif @@ -93,7 +97,7 @@ xmax (size_t size1, size_t 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 + This is a macro, not a 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) @@ -105,4 +109,6 @@ xmax (size_t size1, size_t size2) #define size_in_bounds_p(SIZE) \ ((SIZE) != SIZE_MAX) +_GL_INLINE_HEADER_END + #endif /* _XSIZE_H */ diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c index 2a315e2d8..22438277d 100644 --- a/grub-core/io/bufio.c +++ b/grub-core/io/bufio.c @@ -48,7 +48,7 @@ grub_bufio_open (grub_file_t io, int size) grub_file_t file; grub_bufio_t bufio = 0; - file = (grub_file_t) grub_malloc (sizeof (*file)); + file = (grub_file_t) grub_zalloc (sizeof (*file)); if (! file) return 0; @@ -61,7 +61,7 @@ grub_bufio_open (grub_file_t io, int size) size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE : io->size); - bufio = grub_malloc (sizeof (struct grub_bufio) + size); + bufio = grub_zalloc (sizeof (struct grub_bufio) + size); if (! bufio) { grub_free (file); @@ -70,14 +70,10 @@ grub_bufio_open (grub_file_t io, int size) bufio->file = io; bufio->block_size = size; - bufio->buffer_len = 0; - bufio->buffer_at = 0; file->device = io->device; - file->offset = 0; file->size = io->size; file->data = bufio; - file->read_hook = 0; file->fs = &grub_bufio_fs; file->not_easily_seekable = io->not_easily_seekable; diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 83c0b64cb..59ad6daff 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -363,8 +363,6 @@ static ush mask_bits[] = 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; -#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" - #define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<>=(n);k-=(n);} while (0) @@ -544,7 +542,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ z = 1 << j; /* table entries for j-bit table */ /* allocate and link in new table */ - q = (struct huft *) grub_malloc ((z + 1) * sizeof (struct huft)); + q = (struct huft *) grub_zalloc ((z + 1) * sizeof (struct huft)); if (! q) { if (h) @@ -1118,6 +1116,8 @@ initialize_tables (grub_gzio_t gzio) /* Reset memory allocation stuff. */ huft_free (gzio->tl); huft_free (gzio->td); + gzio->tl = NULL; + gzio->td = NULL; } @@ -1125,12 +1125,12 @@ initialize_tables (grub_gzio_t gzio) even if IO does not contain data compressed by gzip, return a valid file object. Note that this function won't close IO, even if an error occurs. */ static grub_file_t -grub_gzio_open (grub_file_t io) +grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused))) { grub_file_t file; grub_gzio_t gzio = 0; - file = (grub_file_t) grub_malloc (sizeof (*file)); + file = (grub_file_t) grub_zalloc (sizeof (*file)); if (! file) return 0; @@ -1144,9 +1144,7 @@ grub_gzio_open (grub_file_t io) gzio->file = io; file->device = io->device; - file->offset = 0; file->data = gzio; - file->read_hook = 0; file->fs = &grub_gzio_fs; file->not_easily_seekable = 1; @@ -1180,7 +1178,7 @@ test_zlib_header (grub_gzio_t gzio) return 0; } - if ((cmf * 256 + flg) % 31) + if ((cmf * 256U + flg) % 31U) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format")); return 0; diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index 77291d001..2895e2102 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -166,15 +166,17 @@ read_block_data (struct grub_lzopio *lzopio) if (lzopio->ccheck_fun) { - grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8]; + grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; - lzopio->ccheck_fun->init (context); - lzopio->ccheck_fun->write (context, lzopio->block.cdata, - lzopio->block.csize); - lzopio->ccheck_fun->final (context); + if (lzopio->ccheck_fun->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return -1; + + grub_crypto_hash (lzopio->ccheck_fun, computed_hash, + lzopio->block.cdata, + lzopio->block.csize); if (grub_memcmp - (lzopio->ccheck_fun->read (context), &lzopio->block.ccheck, + (computed_hash, &lzopio->block.ccheck, sizeof (lzopio->block.ccheck)) != 0) return -1; } @@ -212,15 +214,17 @@ uncompress_block (struct grub_lzopio *lzopio) if (lzopio->ucheck_fun) { - grub_uint64_t context[(lzopio->ucheck_fun->contextsize + 7) / 8]; + grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; - lzopio->ucheck_fun->init (context); - lzopio->ucheck_fun->write (context, lzopio->block.udata, - lzopio->block.usize); - lzopio->ucheck_fun->final (context); + if (lzopio->ucheck_fun->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return -1; + + grub_crypto_hash (lzopio->ucheck_fun, computed_hash, + lzopio->block.udata, + lzopio->block.usize); if (grub_memcmp - (lzopio->ucheck_fun->read (context), &lzopio->block.ucheck, + (computed_hash, &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != 0) return -1; } @@ -380,12 +384,8 @@ test_header (grub_file_t file) sizeof (checksum)) goto CORRUPTED; - if (hcheck) - { - checksum = checksum; - if (grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) - goto CORRUPTED; - } + if (hcheck && grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) + goto CORRUPTED; lzopio->start_block_off = grub_file_tell (lzopio->file); @@ -409,7 +409,8 @@ CORRUPTED: } static grub_file_t -grub_lzopio_open (grub_file_t io) +grub_lzopio_open (grub_file_t io, + const char *name __attribute__ ((unused))) { grub_file_t file; grub_lzopio_t lzopio; @@ -428,9 +429,7 @@ grub_lzopio_open (grub_file_t io) lzopio->file = io; file->device = io->device; - file->offset = 0; file->data = lzopio; - file->read_hook = 0; file->fs = &grub_lzopio_fs; file->size = GRUB_FILE_SIZE_UNKNOWN; file->not_easily_seekable = 1; diff --git a/grub-core/io/offset.c b/grub-core/io/offset.c new file mode 100644 index 000000000..ebed0ebe6 --- /dev/null +++ b/grub-core/io/offset.c @@ -0,0 +1,111 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_offset_file +{ + grub_file_t parent; + grub_off_t off; +}; + +static grub_ssize_t +grub_offset_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_offset_file *data = file->data; + if (grub_file_seek (data->parent, data->off + file->offset) == (grub_off_t) -1) + return -1; + return grub_file_read (data->parent, buf, len); +} + +static grub_err_t +grub_offset_close (grub_file_t file) +{ + struct grub_offset_file *data = file->data; + + if (data->parent) + grub_file_close (data->parent); + + /* No need to close the same device twice. */ + file->device = 0; + + return 0; +} + +static struct grub_fs grub_offset_fs = { + .name = "offset", + .dir = 0, + .open = 0, + .read = grub_offset_read, + .close = grub_offset_close, + .label = 0, + .next = 0 +}; + +void +grub_file_offset_close (grub_file_t file) +{ + struct grub_offset_file *off_data = file->data; + off_data->parent = NULL; + grub_file_close (file); +} + +grub_file_t +grub_file_offset_open (grub_file_t parent, grub_off_t start, grub_off_t size) +{ + struct grub_offset_file *off_data; + grub_file_t off_file, last_off_file; + grub_file_filter_id_t filter; + + off_file = grub_zalloc (sizeof (*off_file)); + off_data = grub_zalloc (sizeof (*off_data)); + if (!off_file || !off_data) + { + grub_free (off_file); + grub_free (off_data); + return 0; + } + + off_data->off = start; + off_data->parent = parent; + + off_file->device = parent->device; + off_file->data = off_data; + off_file->fs = &grub_offset_fs; + off_file->size = size; + + last_off_file = NULL; + for (filter = GRUB_FILE_FILTER_COMPRESSION_FIRST; + off_file && filter <= GRUB_FILE_FILTER_COMPRESSION_LAST; filter++) + if (grub_file_filters_enabled[filter]) + { + last_off_file = off_file; + off_file = grub_file_filters_enabled[filter] (off_file, parent->name); + } + + if (!off_file) + { + off_data->parent = NULL; + grub_file_close (last_off_file); + return 0; + } + return off_file; +} diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index ae30e6f80..bcce24290 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -169,7 +169,8 @@ ERROR: } static grub_file_t -grub_xzio_open (grub_file_t io) +grub_xzio_open (grub_file_t io, + const char *name __attribute__ ((unused))) { grub_file_t file; grub_xzio_t xzio; @@ -186,12 +187,9 @@ grub_xzio_open (grub_file_t io) } xzio->file = io; - xzio->saved_offset = 0; file->device = io->device; - file->offset = 0; file->data = xzio; - file->read_hook = 0; file->fs = &grub_xzio_fs; file->size = GRUB_FILE_SIZE_UNKNOWN; file->not_easily_seekable = 1; @@ -210,10 +208,7 @@ grub_xzio_open (grub_file_t io) } xzio->buf.in = xzio->inbuf; - xzio->buf.in_pos = 0; - xzio->buf.in_size = 0; xzio->buf.out = xzio->outbuf; - xzio->buf.out_pos = 0; xzio->buf.out_size = XZBUFSIZ; /* FIXME: don't test footer on not easily seekable files. */ diff --git a/grub-core/kern/arm/cache.S b/grub-core/kern/arm/cache.S new file mode 100644 index 000000000..8522d2470 --- /dev/null +++ b/grub-core/kern/arm/cache.S @@ -0,0 +1,136 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include + + .file "cache.S" + .text + .syntax unified + .arm +#if !defined (ARMV6) && !defined (ARMV7) +# error Unsupported architecture version! +#endif + + .align 2 + +/* + * Simple cache maintenance functions + */ + +dlinesz_addr: + .long EXT_C(grub_arch_cache_dlinesz) +ilinesz_addr: + .long EXT_C(grub_arch_cache_ilinesz) + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive) +clean_dcache_range: + @ Clean data cache for range to point-of-unification + ldr r2, dlinesz_addr + ldr r2, [r2] + sub r3, r2, #1 @ align "beg" to start of line + mvn r3, r3 + and r0, r0, r3 +1: cmp r0, r1 + bge 2f +#ifdef ARMV6 + mcr p15, 0, r0, c7, c10, 1 @ Clean data cache line by MVA +#else + mcr p15, 0, r0, c7, c11, 1 @ DCCMVAU +#endif + add r0, r0, r2 @ Next line + b 1b +2: DSB + bx lr + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive) +invalidate_icache_range: + @ Invalidate instruction cache for range to point-of-unification + ldr r2, ilinesz_addr + ldr r2, [r2] + sub r3, r2, #1 @ align "beg" to start of line + mvn r3, r3 + and r0, r0, r3 +1: cmp r0, r1 + bge 2f + mcr p15, 0, r0, c7, c5, 1 @ ICIMVAU + add r0, r0, r2 @ Next line + b 1b + @ Branch predictor invalidate all +2: mcr p15, 0, r0, c7, c5, 6 @ BPIALL + DSB + ISB + bx lr + +@void grub_arch_sync_caches (void *address, grub_size_t len) +#ifdef ARMV6 +FUNCTION(grub_arch_sync_caches_armv6) +#else +FUNCTION(grub_arch_sync_caches_armv7) +#endif + DSB + add r1, r0, r1 + push {r0-r2, lr} + bl clean_dcache_range + pop {r0, r1} + bl invalidate_icache_range + pop {r2, pc} + +#ifdef ARMV6 +FUNCTION(grub_arm_disable_caches_mmu_armv6) +#else +FUNCTION(grub_arm_disable_caches_mmu_armv7) +#endif + + push {r4, lr} + + @ disable D-cache + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) + mcr p15, 0, r0, c1, c0, 0 + DSB + ISB + + @ clean/invalidate D-cache + bl clean_invalidate_dcache + + @ disable I-cache + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 12) + mcr p15, 0, r0, c1, c0, 0 + DSB + ISB + + @ invalidate I-cache (also invalidates branch predictors) + mcr p15, 0, r0, c7, c5, 0 + DSB + ISB + + @ clear SCTLR M bit + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 0) + mcr p15, 0, r0, c1, c0, 0 + + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLB + mcr p15, 0, r0, c7, c5, 6 @ invalidate branch predictor + DSB + ISB + + pop {r4, pc} + diff --git a/grub-core/kern/arm/cache.c b/grub-core/kern/arm/cache.c new file mode 100644 index 000000000..f78d070a2 --- /dev/null +++ b/grub-core/kern/arm/cache.c @@ -0,0 +1,131 @@ +#include +#include +#include + +/* This is only about cache architecture. It doesn't imply + the CPU architecture. */ +static enum + { + ARCH_UNKNOWN, + ARCH_ARMV5_WRITE_THROUGH, + ARCH_ARMV6, + ARCH_ARMV6_UNIFIED, + ARCH_ARMV7 + } type = ARCH_UNKNOWN; + +grub_uint32_t grub_arch_cache_dlinesz; +grub_uint32_t grub_arch_cache_ilinesz; + +/* Prototypes for asm functions. */ +void grub_arch_sync_caches_armv6 (void *address, grub_size_t len); +void grub_arch_sync_caches_armv7 (void *address, grub_size_t len); +void grub_arm_disable_caches_mmu_armv6 (void); +void grub_arm_disable_caches_mmu_armv7 (void); +grub_uint32_t grub_arm_main_id (void); +grub_uint32_t grub_arm_cache_type (void); + +static void +probe_caches (void) +{ + grub_uint32_t main_id, cache_type; + + /* Read main ID Register */ + main_id = grub_arm_main_id (); + + switch ((main_id >> 16) & 0xf) + { + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0xf: + break; + default: + grub_fatal ("Unsupported ARM ID 0x%x", main_id); + } + + /* Read Cache Type Register */ + cache_type = grub_arm_cache_type (); + + switch (cache_type >> 24) + { + case 0x00: + case 0x01: + grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); + grub_arch_cache_ilinesz = 8 << (cache_type & 3); + type = ARCH_ARMV5_WRITE_THROUGH; + break; + case 0x04: + case 0x0a: + case 0x0c: + case 0x0e: + case 0x1c: + grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); + grub_arch_cache_ilinesz = 8 << (cache_type & 3); + type = ARCH_ARMV6_UNIFIED; + break; + case 0x05: + case 0x0b: + case 0x0d: + case 0x0f: + case 0x1d: + grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); + grub_arch_cache_ilinesz = 8 << (cache_type & 3); + type = ARCH_ARMV6; + break; + case 0x80 ... 0x8f: + grub_arch_cache_dlinesz = 4 << ((cache_type >> 16) & 0xf); + grub_arch_cache_ilinesz = 4 << (cache_type & 0xf); + type = ARCH_ARMV7; + break; + default: + grub_fatal ("Unsupported cache type 0x%x", cache_type); + } +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + if (type == ARCH_UNKNOWN) + probe_caches (); + switch (type) + { + case ARCH_ARMV6: + grub_arch_sync_caches_armv6 (address, len); + break; + case ARCH_ARMV7: + grub_arch_sync_caches_armv7 (address, len); + break; + /* Nothing to do. */ + case ARCH_ARMV5_WRITE_THROUGH: + case ARCH_ARMV6_UNIFIED: + break; + /* Pacify GCC. */ + case ARCH_UNKNOWN: + break; + } +} + +void +grub_arm_disable_caches_mmu (void) +{ + if (type == ARCH_UNKNOWN) + probe_caches (); + switch (type) + { + case ARCH_ARMV6_UNIFIED: + case ARCH_ARMV6: + grub_arm_disable_caches_mmu_armv6 (); + break; + case ARCH_ARMV7: + grub_arm_disable_caches_mmu_armv7 (); + break; + /* Nothing to do. */ + case ARCH_ARMV5_WRITE_THROUGH: + break; + /* Pacify GCC. */ + case ARCH_UNKNOWN: + break; + } +} diff --git a/grub-core/kern/arm/cache_armv6.S b/grub-core/kern/arm/cache_armv6.S new file mode 100644 index 000000000..c8f94abcf --- /dev/null +++ b/grub-core/kern/arm/cache_armv6.S @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include + + .file "cache_armv6.S" + .text + .syntax unified + .arm + .arch armv6 + +# define DMB mcr p15, 0, r0, c7, c10, 5 +# define DSB mcr p15, 0, r0, c7, c10, 4 +# define ISB mcr p15, 0, r0, c7, c5, 4 +#define ARMV6 1 + +clean_invalidate_dcache: + mcr p15, 0, r0, c7, c14, 0 @ Clean/Invalidate D-cache + bx lr + +#include "cache.S" + +FUNCTION(grub_arm_main_id) + mrc p15, 0, r0, c0, c0, 0 + bx lr + +FUNCTION(grub_arm_cache_type) + mrc p15, 0, r0, c0, c0, 1 + bx lr \ No newline at end of file diff --git a/grub-core/kern/arm/cache_armv7.S b/grub-core/kern/arm/cache_armv7.S new file mode 100644 index 000000000..0c16b1047 --- /dev/null +++ b/grub-core/kern/arm/cache_armv7.S @@ -0,0 +1,114 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include + + .file "cache_armv7.S" + .text + .syntax unified + .arm + .arch armv7a +# define DMB dmb +# define DSB dsb +# define ISB isb +#define ARMV7 1 + + @ r0 - CLIDR + @ r1 - LoC + @ r2 - current level + @ r3 - num sets + @ r4 - num ways + @ r5 - current set + @ r6 - current way + @ r7 - line size + @ r8 - scratch + @ r9 - scratch + @ r10 - scratch + @ r11 - scratch +clean_invalidate_dcache: + push {r4-r12, lr} + mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR + lsr r1, r0, #24 @ Extract LoC + and r1, r1, #0x7 + + mov r2, #0 @ First level, L1 +2: and r8, r0, #7 @ cache type at current level + cmp r8, #2 + blt 5f @ instruction only, or none, skip level + + @ set current cache level/type (for CCSIDR read) + lsl r8, r2, #1 + mcr p15, 2, r8, c0, c0, 0 @ Write CSSELR (level, type: data/uni) + + @ read current cache information + mrc p15, 1, r8, c0, c0, 0 @ Read CCSIDR + lsr r3, r8, #13 @ Number of sets -1 + ldr r9, =0x3fff + and r3, r3, r9 + lsr r4, r8, #3 @ Number of ways -1 + ldr r9, =0x1ff + and r4, r4, r9 + and r7, r8, #7 @ log2(line size in words) - 2 + add r7, r7, #2 @ adjust + mov r8, #1 + lsl r7, r8, r7 @ -> line size in words + lsl r7, r7, #2 @ -> bytes + + @ set loop + mov r5, #0 @ current set = 0 +3: lsl r8, r2, #1 @ insert level + clz r9, r7 @ calculate set field offset + mov r10, #31 + sub r9, r10, r9 + lsl r10, r5, r9 + orr r8, r8, r10 @ insert set field + + @ way loop + @ calculate way field offset + mov r6, #0 @ current way = 0 + add r10, r4, #1 + clz r9, r10 @ r9 = way field offset + add r9, r9, #1 +4: lsl r10, r6, r9 + orr r11, r8, r10 @ insert way field + + @ clean and invalidate line by set/way + mcr p15, 0, r11, c7, c14, 2 @ DCCISW + + @ next way + add r6, r6, #1 + cmp r6, r4 + ble 4b + + @ next set + add r5, r5, #1 + cmp r5, r3 + ble 3b + + @ next level +5: lsr r0, r0, #3 @ align next level CLIDR 'type' field + add r2, r2, #1 @ increment cache level counter + cmp r2, r1 + blt 2b @ outer loop + + @ return +6: DSB + ISB + pop {r4-r12, pc} + +#include "cache.S" \ No newline at end of file diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c new file mode 100644 index 000000000..4563a52f9 --- /dev/null +++ b/grub-core/kern/arm/dl.c @@ -0,0 +1,206 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/************************************************* + * Runtime dynamic linker with helper functions. * + *************************************************/ +static grub_err_t +do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) +{ + grub_dl_segment_t seg; + Elf_Rel *rel; + Elf_Sym *sym; + int i, entnum; + + entnum = relhdr->sh_size / sizeof (Elf_Rel); + + /* Find the target segment for this relocation section. */ + for (seg = mod->segment ; seg ; seg = seg->next) + if (seg->section == relhdr->sh_info) + break; + if (!seg) + return grub_error (GRUB_ERR_EOF, N_("relocation segment not found")); + + rel = (Elf_Rel *) ((grub_addr_t) e + relhdr->sh_offset); + + /* Step through all relocations */ + for (i = 0, sym = mod->symtab; i < entnum; i++) + { + Elf_Addr *target, sym_addr; + int relsym, reltype; + grub_err_t retval; + + if (seg->size < rel[i].r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + relsym = ELF_R_SYM (rel[i].r_info); + reltype = ELF_R_TYPE (rel[i].r_info); + target = (void *) ((grub_addr_t) seg->addr + rel[i].r_offset); + + sym_addr = sym[relsym].st_value; + + switch (reltype) + { + case R_ARM_ABS32: + { + /* Data will be naturally aligned */ + retval = grub_arm_reloc_abs32 (target, sym_addr); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + case R_ARM_CALL: + case R_ARM_JUMP24: + { + retval = grub_arm_reloc_jump24 (target, sym_addr); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + { + /* Thumb instructions can be 16-bit aligned */ + retval = grub_arm_reloc_thm_call ((grub_uint16_t *) target, sym_addr); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + /* Happens when compiled with -march=armv4. Since currently we need + at least armv5, keep bx as-is. + */ + case R_ARM_V4BX: + break; + case R_ARM_THM_JUMP19: + { + /* Thumb instructions can be 16-bit aligned */ + retval = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + reltype); + } + } + + return GRUB_ERR_NONE; +} + + +/* + * Check if EHDR is a valid ELF header. + */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_ARM) + return grub_error (GRUB_ERR_BAD_OS, + N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} + +/* + * Verify that provided ELF header contains reference to a symbol table + */ +static int +has_symtab (Elf_Ehdr * e) +{ + int i; + Elf_Shdr *s; + + for (i = 0, s = (Elf_Shdr *) ((grub_uint32_t) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((grub_uint32_t) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + return 1; + + return 0; +} + +/* + * grub_arch_dl_relocate_symbols(): + * Only externally visible function in this file. + * Locates the relocations section of the ELF object, and calls + * do_relocations() to deal with it. + */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + unsigned i; + + if (!has_symtab (e)) + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + +#define FIRST_SHDR(x) ((Elf_Shdr *) ((grub_addr_t)(x) + (x)->e_shoff)) +#define NEXT_SHDR(x, y) ((Elf_Shdr *) ((grub_addr_t)(y) + (x)->e_shentsize)) + + for (i = 0, s = FIRST_SHDR (e); i < e->e_shnum; i++, s = NEXT_SHDR (e, s)) + { + grub_err_t ret; + + switch (s->sh_type) + { + case SHT_REL: + { + /* Relocations, no addends */ + ret = do_relocations (s, e, mod); + if (ret != GRUB_ERR_NONE) + return ret; + } + break; + case SHT_NULL: + case SHT_PROGBITS: + case SHT_SYMTAB: + case SHT_STRTAB: + case SHT_NOBITS: + case SHT_ARM_ATTRIBUTES: + break; + case SHT_RELA: + default: + { + grub_dprintf ("dl", "unhandled section_type: %d (0x%08x)\n", + s->sh_type, s->sh_type); + return GRUB_ERR_NOT_IMPLEMENTED_YET; + }; + } + } + +#undef FIRST_SHDR +#undef NEXT_SHDR + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm/dl_helper.c b/grub-core/kern/arm/dl_helper.c new file mode 100644 index 000000000..68a9e3bbf --- /dev/null +++ b/grub-core/kern/arm/dl_helper.c @@ -0,0 +1,222 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * R_ARM_ABS32 + * + * Simple relocation of 32-bit value (in literal pool) + */ +grub_err_t +grub_arm_reloc_abs32 (Elf32_Word *target, Elf32_Addr sym_addr) +{ + Elf32_Addr tmp; + + tmp = grub_le_to_cpu32 (*target); + tmp += sym_addr; + *target = grub_cpu_to_le32 (tmp); + grub_dprintf ("dl", " %s: reloc_abs32 0x%08x => 0x%08x", __FUNCTION__, + (unsigned int) sym_addr, (unsigned int) tmp); + + return GRUB_ERR_NONE; +} + +/******************************************************************** + * Thumb (T32) relocations: * + * * + * 32-bit Thumb instructions can be 16-bit aligned, and are fetched * + * little-endian, requiring some additional fiddling. * + ********************************************************************/ + +/* + * R_ARM_THM_CALL/THM_JUMP24 + * + * Relocate Thumb (T32) instruction set relative branches: + * B.W, BL and BLX + */ +grub_err_t +grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr) +{ + grub_int32_t offset, offset_low, offset_high; + grub_uint32_t sign, j1, j2, is_blx; + grub_uint32_t insword, insmask; + + /* Extract instruction word in alignment-safe manner */ + insword = (grub_le_to_cpu16 (*target) << 16) + | (grub_le_to_cpu16(*(target + 1))); + insmask = 0xf800d000; + + /* B.W/BL or BLX? Affects range and expected target state */ + if (((insword >> 12) & 0xd) == 0xc) + is_blx = 1; + else + is_blx = 0; + + /* If BLX, target symbol must be ARM (target address LSB == 0) */ + if (is_blx && (sym_addr & 1)) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("Relocation targeting wrong execution state")); + + offset_low = -16777216; + offset_high = is_blx ? 16777212 : 16777214; + + /* Extract bitfields from instruction words */ + sign = (insword >> 26) & 1; + j1 = (insword >> 13) & 1; + j2 = (insword >> 11) & 1; + offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((insword & 0x03ff0000) >> 4) | ((insword & 0x000007ff) << 1); + + /* Sign adjust and calculate offset */ + if (offset & (1 << 24)) + offset -= (1 << 25); + + grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr); + + offset += sym_addr; +#ifndef GRUB_UTIL + offset -= (grub_uint32_t) target; +#endif + + grub_dprintf("dl", " %s: target=%p, sym_addr=0x%08x, offset=%d\n", + is_blx ? "BLX" : "BL", target, sym_addr, offset); + + if ((offset < offset_low) || (offset > offset_high)) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("THM_CALL Relocation out of range.")); + + grub_dprintf ("dl", " relative destination = %p", + (char *) target + offset); + + /* Reassemble instruction word */ + sign = (offset >> 24) & 1; + j1 = sign ^ (~(offset >> 23) & 1); + j2 = sign ^ (~(offset >> 22) & 1); + insword = (insword & insmask) | + (sign << 26) | + (((offset >> 12) & 0x03ff) << 16) | + (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff); + + /* Write instruction word back in alignment-safe manner */ + *target = grub_cpu_to_le16 ((insword >> 16) & 0xffff); + *(target + 1) = grub_cpu_to_le16 (insword & 0xffff); + + grub_dprintf ("dl", " *insword = 0x%08x", insword); + + return GRUB_ERR_NONE; +} + +/* + * R_ARM_THM_JUMP19 + * + * Relocate conditional Thumb (T32) B.W + */ +grub_err_t +grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr) +{ + grub_int32_t offset; + grub_uint32_t insword, insmask; + + /* Extract instruction word in alignment-safe manner */ + insword = grub_le_to_cpu16 ((*target)) << 16 + | grub_le_to_cpu16 (*(target + 1)); + insmask = 0xfbc0d000; + + /* Extract and sign extend offset */ + offset = ((insword >> 26) & 1) << 19 + | ((insword >> 11) & 1) << 18 + | ((insword >> 13) & 1) << 17 + | ((insword >> 16) & 0x3f) << 11 + | (insword & 0x7ff); + offset <<= 1; + if (offset & (1 << 20)) + offset -= (1 << 21); + + /* Adjust and re-truncate offset */ + offset += sym_addr; +#ifndef GRUB_UTIL + offset -= (grub_uint32_t) target; +#endif + if ((offset > 1048574) || (offset < -1048576)) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("THM_JUMP19 Relocation out of range.")); + + offset >>= 1; + offset &= 0xfffff; + + /* Reassemble instruction word and write back */ + insword &= insmask; + insword |= ((offset >> 19) & 1) << 26 + | ((offset >> 18) & 1) << 11 + | ((offset >> 17) & 1) << 13 + | ((offset >> 11) & 0x3f) << 16 + | (offset & 0x7ff); + *target = grub_cpu_to_le16 (insword >> 16); + *(target + 1) = grub_cpu_to_le16 (insword & 0xffff); + return GRUB_ERR_NONE; +} + + + +/*********************************************************** + * ARM (A32) relocations: * + * * + * ARM instructions are 32-bit in size and 32-bit aligned. * + ***********************************************************/ + +/* + * R_ARM_JUMP24 + * + * Relocate ARM (A32) B + */ +grub_err_t +grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr) +{ + grub_uint32_t insword; + grub_int32_t offset; + + if (sym_addr & 1) + return grub_error (GRUB_ERR_BAD_MODULE, + N_("Relocation targeting wrong execution state")); + + insword = grub_le_to_cpu32 (*target); + + offset = (insword & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset -= 0x04000000; + offset += sym_addr; +#ifndef GRUB_UTIL + offset -= (grub_uint32_t) target; +#endif + + insword &= 0xff000000; + insword |= (offset >> 2) & 0x00ffffff; + + *target = grub_cpu_to_le32 (insword); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c new file mode 100644 index 000000000..a6ae03475 --- /dev/null +++ b/grub-core/kern/arm/efi/init.c @@ -0,0 +1,74 @@ +/* init.c - initialize an arm-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static grub_uint64_t tmr; +static grub_efi_event_t tmr_evt; + +static grub_uint64_t +grub_efi_get_time_ms (void) +{ + return tmr; +} + +static void +increment_timer (grub_efi_event_t event __attribute__ ((unused)), + void *context __attribute__ ((unused))) +{ + tmr++; +} + +void +grub_machine_init (void) +{ + grub_efi_boot_services_t *b; + + grub_efi_init (); + + b = grub_efi_system_table->boot_services; + + efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, + GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt); + efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 10000); + + grub_install_get_time_ms (grub_efi_get_time_ms); +} + +void +grub_machine_fini (int flags) +{ + grub_efi_boot_services_t *b; + + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + + b = grub_efi_system_table->boot_services; + + efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 0); + efi_call_1 (b->close_event, tmr_evt); + + grub_efi_fini (); +} diff --git a/grub-core/kern/arm/efi/misc.c b/grub-core/kern/arm/efi/misc.c new file mode 100644 index 000000000..efec98061 --- /dev/null +++ b/grub-core/kern/arm/efi/misc.c @@ -0,0 +1,203 @@ +/* misc.c - various system functions for an arm-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +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_error (GRUB_ERR_IO, "cannot get memory map"); + return 0; + } + 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); +} + +#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) +#define PAGE_SHIFT 12 + +void * +grub_efi_allocate_loader_memory (grub_uint32_t min_offset, grub_uint32_t 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; + void *mem = NULL; + grub_addr_t min_start = 0; + + mmap_size = find_mmap_size(); + if (!mmap_size) + return NULL; + + mmap = grub_malloc(mmap_size); + if (!mmap) + return NULL; + + tmp_mmap_size = mmap_size; + if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0) + { + grub_error (GRUB_ERR_IO, "cannot get memory map"); + goto fail; + } + + mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size); + /* Find lowest accessible RAM location */ + { + int found = 0; + for (desc = mmap ; !found && (desc < mmap_end) ; + desc = NEXT_MEMORY_DESCRIPTOR(desc, desc_size)) + { + switch (desc->type) + { + case GRUB_EFI_CONVENTIONAL_MEMORY: + case GRUB_EFI_LOADER_CODE: + case GRUB_EFI_LOADER_DATA: + min_start = desc->physical_start + min_offset; + found = 1; + break; + default: + break; + } + } + } + + /* 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)) + { + grub_uint64_t start, end; + + grub_dprintf("mm", "%s: 0x%08x bytes @ 0x%08x\n", + __FUNCTION__, + (grub_uint32_t) (desc->num_pages << PAGE_SHIFT), + (grub_uint32_t) (desc->physical_start)); + + if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) + continue; + + start = desc->physical_start; + end = start + (desc->num_pages << PAGE_SHIFT); + grub_dprintf("mm", "%s: start=0x%016llx, end=0x%016llx\n", + __FUNCTION__, start, end); + start = start < min_start ? min_start : start; + if (start + size > end) + continue; + grub_dprintf("mm", "%s: let's allocate some (0x%x) pages @ 0x%08x...\n", + __FUNCTION__, (size >> PAGE_SHIFT), (grub_addr_t) start); + mem = grub_efi_allocate_pages (start, (size >> PAGE_SHIFT) + 1); + grub_dprintf("mm", "%s: retval=0x%08x\n", + __FUNCTION__, (grub_addr_t) mem); + if (! mem) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory"); + goto fail; + } + break; + } + + if (! mem) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory"); + goto fail; + } + + grub_free (mmap); + return mem; + + fail: + grub_free (mmap); + return NULL; +} + +grub_err_t +grub_efi_prepare_platform (void) +{ + grub_efi_uintn_t mmap_size; + grub_efi_uintn_t map_key; + grub_efi_uintn_t desc_size; + grub_efi_uint32_t desc_version; + grub_efi_memory_descriptor_t *mmap_buf; + grub_err_t err; + + /* + * Cloned from IA64 + * Must be done after grub_machine_fini because map_key is used by + *exit_boot_services. + */ + mmap_size = find_mmap_size (); + if (! mmap_size) + return GRUB_ERR_OUT_OF_MEMORY; + mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12); + if (! mmap_buf) + return GRUB_ERR_OUT_OF_MEMORY; + + err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, + &desc_size, &desc_version); + if (err != GRUB_ERR_NONE) + return err; + + grub_arm_disable_caches_mmu(); + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm/efi/startup.S b/grub-core/kern/arm/efi/startup.S new file mode 100644 index 000000000..9f8265315 --- /dev/null +++ b/grub-core/kern/arm/efi/startup.S @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2013 Free Software Foundation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include + + .file "startup.S" + .text + .arm +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in r1/r0. + */ + ldr ip, =EXT_C(grub_efi_image_handle) + str r0, [ip] + ldr ip, =EXT_C(grub_efi_system_table) + str r1, [ip] + ldr ip, =EXT_C(grub_main) + bx ip + END diff --git a/grub-core/kern/arm/misc.S b/grub-core/kern/arm/misc.S new file mode 100644 index 000000000..8943cc302 --- /dev/null +++ b/grub-core/kern/arm/misc.S @@ -0,0 +1,89 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + + .file "misc.S" + .text + .syntax unified +#if !defined (__thumb2__) + .arm +#else + .thumb +#endif + + .align 2 + +FUNCTION(__muldi3) +FUNCTION(__aeabi_lmul) + stmfd sp!, {r4, fp} + add fp, sp, #4 + sub sp, sp, #16 + str r0, [fp, #-12] + str r1, [fp, #-8] + str r2, [fp, #-20] + str r3, [fp, #-16] + ldr r3, [fp, #-8] + ldr r2, [fp, #-20] + mul r2, r3, r2 + ldr r3, [fp, #-16] + ldr r1, [fp, #-12] + mul r3, r1, r3 + add r2, r2, r3 + ldr r0, [fp, #-12] + ldr r1, [fp, #-20] + umull r3, r4, r0, r1 + add r2, r2, r4 + mov r4, r2 + mov r0, r3 + mov r1, r4 + mov sp, fp + sub sp, sp, #4 + ldmfd sp!, {r4, fp} + bx lr + + .macro division parent + + stmfd sp!, {lr} + sub sp, sp, #12 + mov r2, r1 + add r1, sp, #4 + str r1, [sp, #0] + mov r1, #0 + mov r3, #0 + bl \parent + ldr r1, [sp, #4] + add sp, sp, #12 + ldmfd sp!, {lr} + bx lr + .endm + +FUNCTION(__aeabi_uidivmod) + division grub_divmod64 + + +/* + * Null divide-by-zero handler + */ +FUNCTION(__aeabi_unwind_cpp_pr0) +FUNCTION(raise) + mov r0, #0 + bx lr + + END diff --git a/grub-core/kern/arm/uboot/startup.S b/grub-core/kern/arm/uboot/startup.S new file mode 100644 index 000000000..f54b14b57 --- /dev/null +++ b/grub-core/kern/arm/uboot/startup.S @@ -0,0 +1,188 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +/* + * GRUB is called from U-Boot as a Linux Kernel type image, which + * means among other things that it always enters in ARM state. + * + * + * Overview of GRUB image layout: + * + * _start: + * Entry point (1 ARM branch instruction, to "codestart") + * grub_total_module_size: + * Data field: Size of included module blob + * (when generated by grub-mkimage) + * codestart: + * Remainder of statically-linked executable code and data. + * __bss_start: + * Start of included module blob. + * Also where global/static variables are located. + * _end: + * End of bss region (but not necessarily module blob). + * : + * : + * Loadable modules, post relocation. + * : + */ + + .text + .arm +FUNCTION(_start) + b codestart + + @ Size of final image integrated module blob - set by grub-mkimage + .org _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE +VARIABLE(grub_total_module_size) + .long 0 + +VARIABLE(grub_uboot_machine_type) + .long 0 +VARIABLE(grub_uboot_boot_data) + .long 0 +VARIABLE(grub_modbase) + .long 0 +bss_start_ptr: + .long EXT_C(__bss_start) +end_ptr: + .long EXT_C(_end) + +FUNCTION(codestart) + @ Store context: Machine ID, atags/dtb, ... + @ U-Boot API signature is stored on the U-Boot heap + @ Stack pointer used as start address for signature probing + mov r12, sp + adr sp, entry_state + push {r4-r12,lr} @ store U-Boot context (sp in r12) + + str r1, EXT_C(grub_uboot_machine_type) + str r2, EXT_C(grub_uboot_boot_data) + + @ Modules have been stored as a blob in BSS, + @ they need to be manually relocated to _end + ldr r0, bss_start_ptr @ src + add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + and r0, r0, r1 + + ldr r1, end_ptr @ dst = End of BSS + ldr r2, grub_total_module_size @ blob size + + add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE + and r1, r1, #~0x7 @ Ensure 8-byte alignment + sub sp, r1, #8 + add r1, r1, #1024 + + str r1, EXT_C(grub_modbase) + + add r1, r1, r2 + add r0, r0, r2 + sub r1, r1, #4 + sub r0, r0, #4 + +1: ldr r3, [r0], #-4 @ r3 = *src-- + str r3, [r1], #-4 @ *dst-- = r3 + subs r2, #4 @ remaining -= 4 + bne 1b @ while remaining != 0 + + @ Since we _are_ the C run-time, we need to manually zero the BSS + @ region before continuing + ldr r0, bss_start_ptr @ zero from here + @ If unaligned, bytewise zero until base address aligned. + mov r2, #0 +1: tst r0, #3 + beq 2f + strb r2, [r0], #1 + b 1b +2: ldr r1, end_ptr @ to here +1: str r2, [r0], #4 + cmp r0, r1 + bne 1b + + b EXT_C(grub_main) + + /* + * uboot_syscall(): + * This function is effectively a veneer, so it cannot + * modify the stack or corrupt any registers other than + * r12 (ip). Furthermore it needs to restore r8 for + * U-Boot (Global Data Pointer) and preserve it for Grub. + */ +FUNCTION(grub_uboot_syscall) + str r8, transition_space + str lr, transition_space + 4 + str r9, transition_space + 8 + str sp, transition_space + 12 + + sub sp, sp, #0x20 + lsr sp, sp, #3 + lsl sp, sp, #3 + + ldr r8, gd_backup + ldr r9, gd_backup + 4 + + mov lr, pc + ldr pc, grub_uboot_syscall_ptr + str r8, gd_backup + + ldr r8, transition_space + ldr lr, transition_space + 4 + ldr r9, transition_space + 8 + ldr sp, transition_space + 12 + + bx lr + +FUNCTION(grub_uboot_return) + adr sp, entry_state_end + pop {r4-r12, lr} + mov sp, r12 + bx lr + + + .align 3 +@ U-boot context stack space +entry_state_end: + .long 0 @ r4 + .long 0 @ r5 + .long 0 @ r6 + .long 0 @ r7 +gd_backup: + .long 0 @ r8 - U-Boot global data pointer + .long 0 @ r9 + .long 0 @ r10 + .long 0 @ r11 +VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer - + .long 0 @ also API signature address hint. + .long 0 @ lr +entry_state: @ backup for U-Boot context + +@ GRUB context stack space +transition_space: + .long 0 @ r8 + .long 0 @ lr + .long 0 @ r9 + .long 0 @ sp + +VARIABLE(grub_uboot_syscall_ptr) + .long 0 @ + + END diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c index eec575c05..d9412a316 100644 --- a/grub-core/kern/corecmd.c +++ b/grub-core/kern/corecmd.c @@ -36,17 +36,11 @@ grub_core_cmd_set (struct grub_command *cmd __attribute__ ((unused)), char *var; char *val; - auto int print_env (struct grub_env_var *env); - - int print_env (struct grub_env_var *env) - { - grub_printf ("%s=%s\n", env->name, env->value); - return 0; - } - if (argc < 1) { - grub_env_iterate (print_env); + struct grub_env_var *env; + FOR_SORTED_ENV (env) + grub_printf ("%s=%s\n", env->name, grub_env_get (env->name)); return 0; } @@ -96,7 +90,7 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), } static int -grub_mini_print_devices (const char *name) +grub_mini_print_devices (const char *name, void *data __attribute__ ((unused))) { grub_printf ("(%s) ", name); @@ -105,7 +99,8 @@ grub_mini_print_devices (const char *name) static int grub_mini_print_files (const char *filename, - const struct grub_dirhook_info *info) + const struct grub_dirhook_info *info, + void *data __attribute__ ((unused))) { grub_printf ("%s%s ", filename, info->dir ? "/" : ""); @@ -119,7 +114,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), { if (argc < 1) { - grub_device_iterate (grub_mini_print_devices); + grub_device_iterate (grub_mini_print_devices, NULL); grub_xputs ("\n"); grub_refresh (); } @@ -144,13 +139,13 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), else path++; - if (! path && ! device_name) + if (! *path && ! device_name) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); goto fail; } - if (! path) + if (! *path) { if (grub_errno == GRUB_ERR_UNKNOWN_FS) grub_errno = GRUB_ERR_NONE; @@ -160,7 +155,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), } else if (fs) { - (fs->dir) (dev, path, grub_mini_print_files); + (fs->dir) (dev, path, grub_mini_print_files, NULL); grub_xputs ("\n"); grub_refresh (); } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 12615647d..73b8ecc0c 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -85,94 +85,107 @@ grub_device_close (grub_device_t device) return grub_errno; } -int -grub_device_iterate (int (*hook) (const char *name)) +struct part_ent { - auto int iterate_disk (const char *disk_name); - auto int iterate_partition (grub_disk_t disk, - const grub_partition_t partition); + struct part_ent *next; + char *name; +}; - struct part_ent - { - struct part_ent *next; - char *name; - } *ents; +/* Context for grub_device_iterate. */ +struct grub_device_iterate_ctx +{ + grub_device_iterate_hook_t hook; + void *hook_data; + struct part_ent *ents; +}; - int iterate_disk (const char *disk_name) +/* Helper for grub_device_iterate. */ +static int +iterate_partition (grub_disk_t disk, const grub_partition_t partition, + void *data) +{ + struct grub_device_iterate_ctx *ctx = data; + struct part_ent *p; + char *part_name; + + p = grub_malloc (sizeof (*p)); + if (!p) { - grub_device_t dev; + return 1; + } - if (hook (disk_name)) - return 1; + part_name = grub_partition_get_name (partition); + if (!part_name) + { + grub_free (p); + return 1; + } + p->name = grub_xasprintf ("%s,%s", disk->name, part_name); + grub_free (part_name); + if (!p->name) + { + grub_free (p); + return 1; + } - dev = grub_device_open (disk_name); - if (! dev) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } + p->next = ctx->ents; + ctx->ents = p; - if (dev->disk) - { - struct part_ent *p; - int ret = 0; + return 0; +} - ents = NULL; - (void) grub_partition_iterate (dev->disk, iterate_partition); - grub_device_close (dev); +/* Helper for grub_device_iterate. */ +static int +iterate_disk (const char *disk_name, void *data) +{ + struct grub_device_iterate_ctx *ctx = data; + grub_device_t dev; - grub_errno = GRUB_ERR_NONE; + if (ctx->hook (disk_name, ctx->hook_data)) + return 1; - p = ents; - while (p != NULL) - { - struct part_ent *next = p->next; - - if (!ret) - ret = hook (p->name); - grub_free (p->name); - grub_free (p); - p = next; - } - - return ret; - } - - grub_device_close (dev); + dev = grub_device_open (disk_name); + if (! dev) + { + grub_errno = GRUB_ERR_NONE; return 0; } - int iterate_partition (grub_disk_t disk, const grub_partition_t partition) + if (dev->disk) { struct part_ent *p; - char *part_name; + int ret = 0; - p = grub_malloc (sizeof (*p)); - if (!p) - { - return 1; - } + ctx->ents = NULL; + (void) grub_partition_iterate (dev->disk, iterate_partition, ctx); + grub_device_close (dev); - part_name = grub_partition_get_name (partition); - if (!part_name) + grub_errno = GRUB_ERR_NONE; + + p = ctx->ents; + while (p != NULL) { + struct part_ent *next = p->next; + + if (!ret) + ret = ctx->hook (p->name, ctx->hook_data); + grub_free (p->name); grub_free (p); - return 1; - } - p->name = grub_xasprintf ("%s,%s", disk->name, part_name); - grub_free (part_name); - if (!p->name) - { - grub_free (p); - return 1; + p = next; } - p->next = ents; - ents = p; - - return 0; + return ret; } - /* Only disk devices are supported at the moment. */ - return grub_disk_dev_iterate (iterate_disk); + grub_device_close (dev); + return 0; +} + +int +grub_device_iterate (grub_device_iterate_hook_t hook, void *hook_data) +{ + struct grub_device_iterate_ctx ctx = { hook, hook_data, NULL }; + + /* Only disk devices are supported at the moment. */ + return grub_disk_dev_iterate (iterate_disk, &ctx); } diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 1f55f90a8..2a44f65af 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -31,18 +31,7 @@ /* The last time the disk was used. */ static grub_uint64_t grub_last_time = 0; - -/* Disk cache. */ -struct grub_disk_cache -{ - enum grub_disk_dev_id dev_id; - unsigned long disk_id; - grub_disk_addr_t sector; - char *data; - int lock; -}; - -static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; +struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; void (*grub_disk_firmware_fini) (void); int grub_disk_firmware_is_tainted; @@ -59,35 +48,12 @@ grub_disk_cache_get_performance (unsigned long *hits, unsigned long *misses) } #endif -static unsigned -grub_disk_cache_get_index (unsigned long dev_id, unsigned long disk_id, - grub_disk_addr_t sector) -{ - return ((dev_id * 524287UL + disk_id * 2606459UL - + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS))) - % GRUB_DISK_CACHE_NUM); -} - -static void -grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, - grub_disk_addr_t sector) -{ - unsigned index; - struct grub_disk_cache *cache; - - sector &= ~(GRUB_DISK_CACHE_SIZE - 1); - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; - - if (cache->dev_id == dev_id && cache->disk_id == disk_id - && cache->sector == sector && cache->data) - { - cache->lock = 1; - grub_free (cache->data); - cache->data = 0; - cache->lock = 0; - } -} +grub_err_t (*grub_disk_write_weak) (grub_disk_t disk, + grub_disk_addr_t sector, + grub_off_t offset, + grub_size_t size, + const void *buf); +#include "disk_common.c" void grub_disk_cache_invalidate_all (void) @@ -111,10 +77,10 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector) { struct grub_disk_cache *cache; - unsigned index; + unsigned cache_index; - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; if (cache->dev_id == dev_id && cache->disk_id == disk_id && cache->sector == sector) @@ -138,10 +104,10 @@ grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector) { struct grub_disk_cache *cache; - unsigned index; + unsigned cache_index; - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; if (cache->dev_id == dev_id && cache->disk_id == disk_id && cache->sector == sector) @@ -152,11 +118,11 @@ static grub_err_t grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector, const char *data) { - unsigned index; + unsigned cache_index; struct grub_disk_cache *cache; - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; cache->lock = 1; grub_free (cache->data); @@ -233,6 +199,9 @@ grub_disk_open (const char *name) if (! disk) return 0; disk->log_sector_size = GRUB_DISK_SECTOR_BITS; + /* Default 1MiB of maximum agglomerate. */ + disk->max_agglomerate = 1048576 >> (GRUB_DISK_SECTOR_BITS + + GRUB_DISK_CACHE_BITS); p = find_part_sep (name); if (p) @@ -341,59 +310,12 @@ grub_disk_close (grub_disk_t disk) grub_free (disk); } -/* This function performs three tasks: - - Make sectors disk relative from partition relative. - - Normalize offset to be less than the sector size. - - Verify that the range is inside the partition. */ -static grub_err_t -grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, - grub_off_t *offset, grub_size_t size) -{ - grub_partition_t part; - *sector += *offset >> GRUB_DISK_SECTOR_BITS; - *offset &= GRUB_DISK_SECTOR_SIZE - 1; - - for (part = disk->partition; part; part = part->parent) - { - grub_disk_addr_t start; - grub_uint64_t len; - - start = part->start; - len = part->len; - - if (*sector >= len - || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("attempt to read or write outside of partition")); - - *sector += start; - } - - if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN - && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector - || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors - << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - *sector)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("attempt to read or write outside of disk `%s'"), disk->name); - - return GRUB_ERR_NONE; -} - -static inline grub_disk_addr_t -transform_sector (grub_disk_t disk, grub_disk_addr_t sector) -{ - return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); -} - /* Small read (less than cache size and not pass across cache unit boundaries). sector is already adjusted and is divisible by cache unit size. */ static grub_err_t -grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, - grub_off_t offset, grub_size_t size, void *buf) +grub_disk_read_small_real (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) { char *data; char *tmp_buf; @@ -470,15 +392,27 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, } } +static grub_err_t +grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) +{ + grub_err_t err; + + err = grub_disk_read_small_real (disk, sector, offset, size, buf); + if (err) + return err; + if (disk->read_hook) + (disk->read_hook) (sector + (offset >> GRUB_DISK_SECTOR_BITS), + offset & (GRUB_DISK_SECTOR_SIZE - 1), + size, disk->read_hook_data); + return GRUB_ERR_NONE; +} + /* Read data from the disk. */ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, void *buf) { - grub_off_t real_offset; - grub_disk_addr_t real_sector; - grub_size_t real_size; - /* First of all, check if the region is within the disk. */ if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) { @@ -489,10 +423,6 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } - real_sector = sector; - real_offset = offset; - real_size = size; - /* First read until first cache boundary. */ if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1))) { @@ -527,7 +457,8 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, /* agglomerate read until we find a first cached entry. */ for (agglomerate = 0; agglomerate - < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)); + < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)) + && agglomerate < disk->max_agglomerate; agglomerate++) { data = grub_disk_cache_fetch (disk->dev->id, disk->id, @@ -567,6 +498,11 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, + (i << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS))); + + if (disk->read_hook) + (disk->read_hook) (sector, 0, agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS), + disk->read_hook_data); + sector += agglomerate << GRUB_DISK_CACHE_BITS; size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); buf = (char *) buf @@ -575,6 +511,9 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, if (data) { + if (disk->read_hook) + (disk->read_hook) (sector, 0, (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS), + disk->read_hook_data); sector += GRUB_DISK_CACHE_SIZE; buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); @@ -590,103 +529,6 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return err; } - /* Call the read hook, if any. */ - if (disk->read_hook) - { - grub_disk_addr_t s = real_sector; - grub_size_t l = real_size; - grub_off_t o = real_offset; - - while (l) - { - grub_size_t cl; - cl = GRUB_DISK_SECTOR_SIZE - o; - if (cl > l) - cl = l; - (disk->read_hook) (s, o, cl); - s++; - l -= cl; - o = 0; - } - } - - return grub_errno; -} - -grub_err_t -grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, - grub_off_t offset, grub_size_t size, const void *buf) -{ - unsigned real_offset; - grub_disk_addr_t aligned_sector; - - grub_dprintf ("disk", "Writing `%s'...\n", disk->name); - - if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) - return -1; - - aligned_sector = (sector & ~((1 << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - 1)); - real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); - sector = aligned_sector; - - while (size) - { - if (real_offset != 0 || (size < (1U << disk->log_sector_size) - && size != 0)) - { - char tmp_buf[1 << disk->log_sector_size]; - grub_size_t len; - grub_partition_t part; - - part = disk->partition; - disk->partition = 0; - if (grub_disk_read (disk, sector, - 0, (1 << disk->log_sector_size), tmp_buf) - != GRUB_ERR_NONE) - { - disk->partition = part; - goto finish; - } - disk->partition = part; - - len = (1 << disk->log_sector_size) - real_offset; - if (len > size) - len = size; - - grub_memcpy (tmp_buf + real_offset, buf, len); - - grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); - - if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE) - goto finish; - - sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); - buf = (const char *) buf + len; - size -= len; - real_offset = 0; - } - else - { - grub_size_t len; - grub_size_t n; - - len = size & ~((1 << disk->log_sector_size) - 1); - n = size >> disk->log_sector_size; - - if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE) - goto finish; - - while (n--) - grub_disk_cache_invalidate (disk->dev->id, disk->id, sector++); - - buf = (const char *) buf + len; - size -= len; - } - } - - finish: - return grub_errno; } diff --git a/grub-core/kern/disk_common.c b/grub-core/kern/disk_common.c new file mode 100644 index 000000000..fb19778ae --- /dev/null +++ b/grub-core/kern/disk_common.c @@ -0,0 +1,55 @@ +/* This function performs three tasks: + - Make sectors disk relative from partition relative. + - Normalize offset to be less than the sector size. + - Verify that the range is inside the partition. */ +static grub_err_t +grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, + grub_off_t *offset, grub_size_t size) +{ + grub_partition_t part; + *sector += *offset >> GRUB_DISK_SECTOR_BITS; + *offset &= GRUB_DISK_SECTOR_SIZE - 1; + + for (part = disk->partition; part; part = part->parent) + { + grub_disk_addr_t start; + grub_uint64_t len; + + start = part->start; + len = part->len; + + if (*sector >= len + || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of partition")); + + *sector += start; + } + + if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN + && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector + || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors + << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - *sector)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of disk `%s'"), disk->name); + + return GRUB_ERR_NONE; +} + +static inline grub_disk_addr_t +transform_sector (grub_disk_t disk, grub_disk_addr_t sector) +{ + return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); +} + +static unsigned +grub_disk_cache_get_index (unsigned long dev_id, unsigned long disk_id, + grub_disk_addr_t sector) +{ + return ((dev_id * 524287UL + disk_id * 2606459UL + + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS))) + % GRUB_DISK_CACHE_NUM); +} diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 943eb0e62..437761de1 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -55,6 +55,7 @@ grub_dl_t grub_dl_head = 0; grub_err_t grub_dl_add (grub_dl_t mod); +/* Keep global so that GDB scripts work. */ grub_err_t grub_dl_add (grub_dl_t mod) { @@ -62,9 +63,6 @@ grub_dl_add (grub_dl_t mod) return grub_error (GRUB_ERR_BAD_MODULE, "`%s' is already loaded", mod->name); - mod->next = grub_dl_head; - grub_dl_head = mod; - return GRUB_ERR_NONE; } @@ -81,18 +79,6 @@ grub_dl_remove (grub_dl_t mod) } } -grub_dl_t -grub_dl_get (const char *name) -{ - grub_dl_t l; - - for (l = grub_dl_head; l; l = l->next) - if (grub_strcmp (name, l->name) == 0) - return l; - - return 0; -} - struct grub_symbol @@ -363,6 +349,8 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) #ifdef GRUB_MODULES_MACHINE_READONLY mod->symtab = grub_malloc (s->sh_size); + if (!mod->symtab) + return grub_errno; memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size); #else mod->symtab = (Elf_Sym *) ((char *) e + s->sh_offset); @@ -449,11 +437,22 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) return GRUB_ERR_NONE; } -static void -grub_dl_call_init (grub_dl_t mod) +static Elf_Shdr * +grub_dl_find_section (Elf_Ehdr *e, const char *name) { - if (mod->init) - (mod->init) (mod); + Elf_Shdr *s; + const char *str; + unsigned i; + + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); + str = (char *) e + s->sh_offset; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (grub_strcmp (str + s->sh_name, name) == 0) + return s; + return NULL; } /* Me, Vladimir Serbinenko, hereby I add this module check as per new @@ -467,24 +466,11 @@ grub_dl_call_init (grub_dl_t mod) static grub_err_t grub_dl_check_license (Elf_Ehdr *e) { - Elf_Shdr *s; - const char *str; - unsigned i; - - s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); - str = (char *) e + s->sh_offset; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (grub_strcmp (str + s->sh_name, ".module_license") == 0) - { - if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); + if (s && (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) - return GRUB_ERR_NONE; - } - + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0)) + return GRUB_ERR_NONE; return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); } @@ -492,25 +478,14 @@ static grub_err_t grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e) { Elf_Shdr *s; - const char *str; - unsigned i; - s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); - str = (char *) e + s->sh_offset; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (grub_strcmp (str + s->sh_name, ".modname") == 0) - { - mod->name = grub_strdup ((char *) e + s->sh_offset); - if (! mod->name) - return grub_errno; - break; - } - - if (i == e->e_shnum) + s = grub_dl_find_section (e, ".modname"); + if (!s) return grub_error (GRUB_ERR_BAD_MODULE, "no module name found"); + + mod->name = grub_strdup ((char *) e + s->sh_offset); + if (! mod->name) + return grub_errno; return GRUB_ERR_NONE; } @@ -519,42 +494,36 @@ static grub_err_t grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e) { Elf_Shdr *s; - const char *str; - unsigned i; - s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); - str = (char *) e + s->sh_offset; + s = grub_dl_find_section (e, ".moddeps"); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (grub_strcmp (str + s->sh_name, ".moddeps") == 0) - { - const char *name = (char *) e + s->sh_offset; - const char *max = name + s->sh_size; + if (!s) + return GRUB_ERR_NONE; - while ((name < max) && (*name)) - { - grub_dl_t m; - grub_dl_dep_t dep; + const char *name = (char *) e + s->sh_offset; + const char *max = name + s->sh_size; - m = grub_dl_load (name); - if (! m) - return grub_errno; + while ((name < max) && (*name)) + { + grub_dl_t m; + grub_dl_dep_t dep; - grub_dl_ref (m); + m = grub_dl_load (name); + if (! m) + return grub_errno; - dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep)); - if (! dep) - return grub_errno; + grub_dl_ref (m); - dep->mod = m; - dep->next = mod->dep; - mod->dep = dep; + dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep)); + if (! dep) + return grub_errno; - name += grub_strlen (name) + 1; - } - } + dep->mod = m; + dep->next = mod->dep; + mod->dep = dep; + + name += grub_strlen (name) + 1; + } return GRUB_ERR_NONE; } @@ -597,7 +566,7 @@ grub_dl_flush_cache (grub_dl_t mod) /* Load a module from core memory. */ grub_dl_t -grub_dl_load_core (void *addr, grub_size_t size) +grub_dl_load_core_noinit (void *addr, grub_size_t size) { Elf_Ehdr *e; grub_dl_t mod; @@ -652,7 +621,6 @@ grub_dl_load_core (void *addr, grub_size_t size) grub_dprintf ("modules", "module name: %s\n", mod->name); grub_dprintf ("modules", "init function: %p\n", mod->init); - grub_dl_call_init (mod); if (grub_dl_add (mod)) { @@ -663,6 +631,23 @@ grub_dl_load_core (void *addr, grub_size_t size) return mod; } +grub_dl_t +grub_dl_load_core (void *addr, grub_size_t size) +{ + grub_dl_t mod; + + mod = grub_dl_load_core_noinit (addr, size); + + if (!mod) + return NULL; + + grub_boot_time ("Initing module %s", mod->name); + grub_dl_init (mod); + grub_boot_time ("Module %s inited", mod->name); + + return mod; +} + /* Load a module from the file FILENAME. */ grub_dl_t grub_dl_load_file (const char *filename) @@ -726,6 +711,9 @@ grub_dl_load (const char *name) if (mod) return mod; + if (grub_no_modules) + return 0; + if (! grub_dl_dir) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index f0e48dc19..ed768ae54 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -337,7 +337,34 @@ grub_efi_modules_addr (void) char * grub_efi_get_filename (grub_efi_device_path_t *dp) { - char *name = 0; + char *name = 0, *p; + grub_size_t filesize = 0; + + while (1) + { + grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); + grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); + + if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) + break; + if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) + { + grub_efi_uint16_t len; + len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) + / sizeof (grub_efi_char16_t)); + filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 1; + } + + dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); + } + + if (!filesize) + return NULL; + + p = name = grub_malloc (filesize); + if (!name) + return NULL; while (1) { @@ -351,45 +378,25 @@ grub_efi_get_filename (grub_efi_device_path_t *dp) { grub_efi_file_path_device_path_t *fp; grub_efi_uint16_t len; - char *p; - grub_size_t size; - if (name) - { - size = grub_strlen (name); - name[size] = '/'; - size++; - } - else - size = 0; + if (p != name) + *p++ = '/'; len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) / sizeof (grub_efi_char16_t)); - p = grub_realloc (name, size + len * 4 + 1); - if (! p) - { - grub_free (name); - return 0; - } - - name = p; fp = (grub_efi_file_path_device_path_t *) dp; - *grub_utf16_to_utf8 ((grub_uint8_t *) name + size, - fp->path_name, len) = '\0'; + p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, fp->path_name, len); } dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); } - if (name) - { - /* EFI breaks paths with backslashes. */ - char *p; + *p = '\0'; - for (p = name; *p; p++) - if (*p == '\\') - *p = '/'; - } + /* EFI breaks paths with backslashes. */ + for (p = name; *p; p++) + if (*p == '\\') + *p = '/'; return name; } diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c index 88b2557a9..477aca400 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -141,37 +141,36 @@ grub_efi_free_pages (grub_efi_physical_address_t address, #if defined (__i386__) || defined (__x86_64__) +/* Helper for stop_broadcom. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint8_t cap; + grub_uint16_t pm_state; + + if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK) + return 0; + cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT); + if (!cap) + return 0; + addr = grub_pci_make_address (dev, cap + 4); + pm_state = grub_pci_read_word (addr); + pm_state = pm_state | 0x03; + grub_pci_write_word (addr, pm_state); + grub_pci_read_word (addr); + return 0; +} + static void stop_broadcom (void) { - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid); - - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint8_t cap; - grub_uint16_t pm_state; - - if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM) - return 0; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK) - return 0; - cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT); - if (!cap) - return 0; - addr = grub_pci_make_address (dev, cap + 4); - pm_state = grub_pci_read_word (addr); - pm_state = pm_state | 0x03; - grub_pci_write_word (addr, pm_state); - grub_pci_read_word (addr); - return 0; - } - - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, NULL); } #endif @@ -193,27 +192,41 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, apple, sizeof (apple)) == 0); #endif - if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, - &finish_desc_size, &finish_desc_version) < 0) - return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + while (1) + { + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) < 0) + return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); - if (outbuf && *outbuf_size < finish_mmap_size) - return grub_error (GRUB_ERR_IO, "memory map buffer is too small"); + if (outbuf && *outbuf_size < finish_mmap_size) + return grub_error (GRUB_ERR_IO, "memory map buffer is too small"); - finish_mmap_buf = grub_malloc (finish_mmap_size); - if (!finish_mmap_buf) - return grub_errno; + finish_mmap_buf = grub_malloc (finish_mmap_size); + if (!finish_mmap_buf) + return grub_errno; - if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, - &finish_desc_size, &finish_desc_version) <= 0) - return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) <= 0) + { + grub_free (finish_mmap_buf); + return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + } - b = grub_efi_system_table->boot_services; - status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, - finish_key); - if (status != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services"); + b = grub_efi_system_table->boot_services; + status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, + finish_key); + if (status == GRUB_EFI_SUCCESS) + break; + if (status != GRUB_EFI_INVALID_PARAMETER) + { + grub_free (finish_mmap_buf); + return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services"); + } + + grub_free (finish_mmap_buf); + grub_printf ("Trying to terminate EFI services again\n"); + } grub_efi_is_finished = 1; if (outbuf_size) *outbuf_size = finish_mmap_size; @@ -530,7 +543,7 @@ grub_efi_mm_init (void) grub_printf ("printing memory map\n"); print_memory_map (memory_map, desc_size, NEXT_MEMORY_DESCRIPTOR (memory_map, map_size)); - grub_abort (); + grub_fatal ("Debug. "); #endif /* Release the memory maps. */ diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c index 682cfbdb2..5f99c43cc 100644 --- a/grub-core/kern/elf.c +++ b/grub-core/kern/elf.c @@ -51,6 +51,7 @@ grub_elf_close (grub_elf_t elf) grub_file_t file = elf->file; grub_free (elf->phdrs); + grub_free (elf->filename); grub_free (elf); if (file) @@ -85,9 +86,14 @@ grub_elf_file (grub_file_t file, const char *filename) if (grub_elf_check_header (elf)) goto fail; + elf->filename = grub_strdup (filename); + if (!elf->filename) + goto fail; + return elf; fail: + grub_free (elf->filename); grub_free (elf->phdrs); grub_free (elf); return 0; @@ -112,381 +118,41 @@ grub_elf_open (const char *name) /* 32-bit */ +#define ehdrXX ehdr32 +#define ELFCLASSXX ELFCLASS32 +#define ElfXX_Addr Elf32_Addr +#define grub_elfXX_size grub_elf32_size +#define grub_elfXX_load grub_elf32_load +#define FOR_ELFXX_PHDRS FOR_ELF32_PHDRS +#define grub_elf_is_elfXX grub_elf_is_elf32 +#define grub_elfXX_load_phdrs grub_elf32_load_phdrs +#define ElfXX_Phdr Elf32_Phdr +#define grub_uintXX_t grub_uint32_t -int -grub_elf_is_elf32 (grub_elf_t elf) -{ - return elf->ehdr.ehdr32.e_ident[EI_CLASS] == ELFCLASS32; -} +#include "elfXX.c" -static grub_err_t -grub_elf32_load_phdrs (grub_elf_t elf, const char *filename) -{ - grub_ssize_t phdrs_size; - - phdrs_size = elf->ehdr.ehdr32.e_phnum * elf->ehdr.ehdr32.e_phentsize; - - grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", - (unsigned long long) elf->ehdr.ehdr32.e_phoff, - (unsigned long) phdrs_size); - - elf->phdrs = grub_malloc (phdrs_size); - if (! elf->phdrs) - return grub_errno; - - if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1) - || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_elf32_phdr_iterate (grub_elf_t elf, - const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *), - void *hook_arg) -{ - Elf32_Phdr *phdrs; - unsigned int i; - - if (! elf->phdrs) - if (grub_elf32_load_phdrs (elf, filename)) - return grub_errno; - phdrs = elf->phdrs; - - for (i = 0; i < elf->ehdr.ehdr32.e_phnum; i++) - { - Elf32_Phdr *phdr = phdrs + i; - grub_dprintf ("elf", - "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx " - "filesz %lx\n", - i, phdr->p_type, - (unsigned long) phdr->p_paddr, - (unsigned long) phdr->p_memsz, - (unsigned long) phdr->p_filesz); - if (hook (elf, phdr, hook_arg)) - break; - } - - return grub_errno; -} - -/* Calculate the amount of memory spanned by the segments. */ -grub_size_t -grub_elf32_size (grub_elf_t elf, const char *filename, - Elf32_Addr *base, grub_uint32_t *max_align) -{ - Elf32_Addr segments_start = (Elf32_Addr) -1; - Elf32_Addr segments_end = 0; - int nr_phdrs = 0; - grub_uint32_t curr_align = 1; - - /* Run through the program headers to calculate the total memory size we - * should claim. */ - auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg); - int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), - Elf32_Phdr *phdr, - void *_arg __attribute__ ((unused))) - { - /* Only consider loadable segments. */ - if (phdr->p_type != PT_LOAD) - return 0; - nr_phdrs++; - if (phdr->p_paddr < segments_start) - segments_start = phdr->p_paddr; - if (phdr->p_paddr + phdr->p_memsz > segments_end) - segments_end = phdr->p_paddr + phdr->p_memsz; - if (curr_align < phdr->p_align) - curr_align = phdr->p_align; - return 0; - } - - grub_elf32_phdr_iterate (elf, filename, calcsize, 0); - - if (base) - *base = 0; - - if (nr_phdrs == 0) - { - grub_error (GRUB_ERR_BAD_OS, "no program headers present"); - return 0; - } - - if (segments_end < segments_start) - { - /* Very bad addresses. */ - grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); - return 0; - } - - if (base) - *base = segments_start; - if (max_align) - *max_align = curr_align; - return segments_end - segments_start; -} - -/* Load every loadable segment into memory specified by `_load_hook'. */ -grub_err_t -grub_elf32_load (grub_elf_t _elf, const char *filename, - grub_elf32_load_hook_t _load_hook, - grub_addr_t *base, grub_size_t *size) -{ - grub_addr_t load_base = (grub_addr_t) -1ULL; - grub_size_t load_size = 0; - grub_err_t err; - - auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook); - int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook) - { - grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook; - grub_addr_t load_addr; - int do_load = 1; - - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr, &do_load)) - return 1; - - if (! do_load) - return 0; - - if (load_addr < load_base) - load_base = load_addr; - - grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_memsz); - - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - return grub_errno; - - if (phdr->p_filesz) - { - grub_ssize_t read; - read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); - if (read != (grub_ssize_t) phdr->p_filesz) - { - /* XXX How can we free memory from `load_hook'? */ - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - load_size += phdr->p_memsz; - - return 0; - } - - err = grub_elf32_phdr_iterate (_elf, filename, - grub_elf32_load_segment, _load_hook); - - if (base) - *base = load_base; - if (size) - *size = load_size; - - return err; -} +#undef ehdrXX +#undef ELFCLASSXX +#undef ElfXX_Addr +#undef grub_elfXX_size +#undef grub_elfXX_load +#undef FOR_ELFXX_PHDRS +#undef grub_elf_is_elfXX +#undef grub_elfXX_load_phdrs +#undef ElfXX_Phdr +#undef grub_uintXX_t /* 64-bit */ +#define ehdrXX ehdr64 +#define ELFCLASSXX ELFCLASS64 +#define ElfXX_Addr Elf64_Addr +#define grub_elfXX_size grub_elf64_size +#define grub_elfXX_load grub_elf64_load +#define FOR_ELFXX_PHDRS FOR_ELF64_PHDRS +#define grub_elf_is_elfXX grub_elf_is_elf64 +#define grub_elfXX_load_phdrs grub_elf64_load_phdrs +#define ElfXX_Phdr Elf64_Phdr +#define grub_uintXX_t grub_uint64_t -int -grub_elf_is_elf64 (grub_elf_t elf) -{ - return elf->ehdr.ehdr64.e_ident[EI_CLASS] == ELFCLASS64; -} - -static grub_err_t -grub_elf64_load_phdrs (grub_elf_t elf, const char *filename) -{ - grub_ssize_t phdrs_size; - - phdrs_size = elf->ehdr.ehdr64.e_phnum * elf->ehdr.ehdr64.e_phentsize; - - grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", - (unsigned long long) elf->ehdr.ehdr64.e_phoff, - (unsigned long) phdrs_size); - - elf->phdrs = grub_malloc (phdrs_size); - if (! elf->phdrs) - return grub_errno; - - if ((grub_file_seek (elf->file, elf->ehdr.ehdr64.e_phoff) == (grub_off_t) -1) - || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_elf64_phdr_iterate (grub_elf_t elf, - const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *), - void *hook_arg) -{ - Elf64_Phdr *phdrs; - unsigned int i; - - if (! elf->phdrs) - if (grub_elf64_load_phdrs (elf, filename)) - return grub_errno; - phdrs = elf->phdrs; - - for (i = 0; i < elf->ehdr.ehdr64.e_phnum; i++) - { - Elf64_Phdr *phdr = phdrs + i; - grub_dprintf ("elf", - "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx " - "filesz %lx\n", - i, phdr->p_type, - (unsigned long) phdr->p_paddr, - (unsigned long) phdr->p_memsz, - (unsigned long) phdr->p_filesz); - if (hook (elf, phdr, hook_arg)) - break; - } - - return grub_errno; -} - -/* Calculate the amount of memory spanned by the segments. */ -grub_size_t -grub_elf64_size (grub_elf_t elf, const char *filename, - Elf64_Addr *base, grub_uint64_t *max_align) -{ - Elf64_Addr segments_start = (Elf64_Addr) -1; - Elf64_Addr segments_end = 0; - int nr_phdrs = 0; - grub_uint64_t curr_align = 1; - - /* Run through the program headers to calculate the total memory size we - * should claim. */ - auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg); - int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), - Elf64_Phdr *phdr, - void *_arg __attribute__ ((unused))) - { - /* Only consider loadable segments. */ - if (phdr->p_type != PT_LOAD) - return 0; - nr_phdrs++; - if (phdr->p_paddr < segments_start) - segments_start = phdr->p_paddr; - if (phdr->p_paddr + phdr->p_memsz > segments_end) - segments_end = phdr->p_paddr + phdr->p_memsz; - if (curr_align < phdr->p_align) - curr_align = phdr->p_align; - return 0; - } - - grub_elf64_phdr_iterate (elf, filename, calcsize, 0); - - if (base) - *base = 0; - - if (nr_phdrs == 0) - { - grub_error (GRUB_ERR_BAD_OS, "no program headers present"); - return 0; - } - - if (segments_end < segments_start) - { - /* Very bad addresses. */ - grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); - return 0; - } - - if (base) - *base = segments_start; - if (max_align) - *max_align = curr_align; - return segments_end - segments_start; -} - -/* Load every loadable segment into memory specified by `_load_hook'. */ -grub_err_t -grub_elf64_load (grub_elf_t _elf, const char *filename, - grub_elf64_load_hook_t _load_hook, - grub_addr_t *base, grub_size_t *size) -{ - grub_addr_t load_base = (grub_addr_t) -1ULL; - grub_size_t load_size = 0; - grub_err_t err; - - auto int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, - void *hook); - int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *hook) - { - grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook; - grub_addr_t load_addr; - int do_load = 1; - - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr, &do_load)) - return 1; - - if (! do_load) - return 0; - - if (load_addr < load_base) - load_base = load_addr; - - grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_memsz); - - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - return grub_errno; - - if (phdr->p_filesz) - { - grub_ssize_t read; - read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); - if (read != (grub_ssize_t) phdr->p_filesz) - { - /* XXX How can we free memory from `load_hook'? */ - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - load_size += phdr->p_memsz; - - return 0; - } - - err = grub_elf64_phdr_iterate (_elf, filename, - grub_elf64_load_segment, _load_hook); - - if (base) - *base = load_base; - if (size) - *size = load_size; - - return err; -} +#include "elfXX.c" diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c new file mode 100644 index 000000000..2e4544919 --- /dev/null +++ b/grub-core/kern/elfXX.c @@ -0,0 +1,156 @@ +int +grub_elf_is_elfXX (grub_elf_t elf) +{ + return elf->ehdr.ehdrXX.e_ident[EI_CLASS] == ELFCLASSXX; +} + +grub_err_t +grub_elfXX_load_phdrs (grub_elf_t elf) +{ + grub_ssize_t phdrs_size; + + if (elf->phdrs) + return GRUB_ERR_NONE; + + phdrs_size = elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize; + + grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", + (unsigned long long) elf->ehdr.ehdrXX.e_phoff, + (unsigned long) phdrs_size); + + elf->phdrs = grub_malloc (phdrs_size); + if (! elf->phdrs) + return grub_errno; + + if ((grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_phoff) == (grub_off_t) -1) + || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + elf->filename); + return grub_errno; + } + + return GRUB_ERR_NONE; +} + +/* Calculate the amount of memory spanned by the segments. */ +grub_size_t +grub_elfXX_size (grub_elf_t elf, + ElfXX_Addr *base, grub_uintXX_t *max_align) +{ + ElfXX_Addr segments_start = (ElfXX_Addr) -1; + ElfXX_Addr segments_end = 0; + int nr_phdrs = 0; + grub_uint32_t curr_align = 1; + ElfXX_Phdr *phdr; + + /* Run through the program headers to calculate the total memory size we + * should claim. */ + FOR_ELFXX_PHDRS (elf, phdr) + { + /* Only consider loadable segments. */ + if (phdr->p_type != PT_LOAD) + continue; + nr_phdrs++; + if (phdr->p_paddr < segments_start) + segments_start = phdr->p_paddr; + if (phdr->p_paddr + phdr->p_memsz > segments_end) + segments_end = phdr->p_paddr + phdr->p_memsz; + if (curr_align < phdr->p_align) + curr_align = phdr->p_align; + } + + if (base) + *base = 0; + + if (nr_phdrs == 0) + { + grub_error (GRUB_ERR_BAD_OS, "no program headers present"); + return 0; + } + + if (segments_end < segments_start) + { + /* Very bad addresses. */ + grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); + return 0; + } + + if (base) + *base = segments_start; + if (max_align) + *max_align = curr_align; + return segments_end - segments_start; +} + +grub_err_t +grub_elfXX_load (grub_elf_t elf, const char *filename, + void *load_offset, enum grub_elf_load_flags load_flags, + grub_addr_t *base, grub_size_t *size) +{ + grub_addr_t load_base = (grub_addr_t) -1ULL; + grub_size_t load_size = 0; + ElfXX_Phdr *phdr; + + FOR_ELFXX_PHDRS(elf, phdr) + { + grub_addr_t load_addr; + + if (phdr->p_type != PT_LOAD && !((load_flags & GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC) && phdr->p_type == PT_DYNAMIC)) + continue; + + load_addr = (grub_addr_t) phdr->p_paddr; + switch (load_flags & GRUB_ELF_LOAD_FLAGS_BITS) + { + case GRUB_ELF_LOAD_FLAGS_ALL_BITS: + break; + case GRUB_ELF_LOAD_FLAGS_28BITS: + load_addr &= 0xFFFFFFF; + break; + case GRUB_ELF_LOAD_FLAGS_30BITS: + load_addr &= 0x3FFFFFFF; + break; + case GRUB_ELF_LOAD_FLAGS_62BITS: + load_addr &= 0x3FFFFFFFFFFFFFFFULL; + break; + } + load_addr += (grub_addr_t) load_offset; + + if (load_addr < load_base) + load_base = load_addr; + + grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_memsz); + + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + return grub_errno; + + if (phdr->p_filesz) + { + grub_ssize_t read; + read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); + if (read != (grub_ssize_t) phdr->p_filesz) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } + } + + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (long) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); + + load_size += phdr->p_memsz; + } + + if (base) + *base = load_base; + if (size) + *size = load_size; + + return grub_errno; +} diff --git a/grub-core/kern/emu/argp_common.c b/grub-core/kern/emu/argp_common.c index d6080ba25..e519b529e 100644 --- a/grub-core/kern/emu/argp_common.c +++ b/grub-core/kern/emu/argp_common.c @@ -18,6 +18,7 @@ */ #include +#include #define _GNU_SOURCE 1 #include diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index b167a141b..97d59fd32 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -24,6 +24,8 @@ #include #include +const int grub_no_modules = 1; + void grub_register_exported_symbols (void) { @@ -44,12 +46,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) return GRUB_ERR_BAD_MODULE; } -void -grub_emu_init (void) -{ - grub_no_autoload = 1; -} - #if defined (__ia64__) || defined (__powerpc__) void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)), grub_size_t *tramp, grub_size_t *got) @@ -66,7 +62,3 @@ grub_arch_dl_init_linker (void) } #endif -void -grub_emu_post_init (void) -{ -} diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index be77b0416..c88d84348 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -17,6 +17,8 @@ * along with GRUB. If not, see . */ +#include + #include #include #include @@ -44,77 +46,11 @@ #ifdef __linux__ # include /* ioctl */ # include -# if !defined(__GLIBC__) || \ - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) -/* Maybe libc doesn't have large file support. */ -# include /* _llseek */ -# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */ # ifndef BLKFLSBUF # define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */ # endif /* ! BLKFLSBUF */ -# include /* ioctl */ -# ifndef HDIO_GETGEO -# define HDIO_GETGEO 0x0301 /* get device geometry */ -/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is - defined. */ -struct hd_geometry -{ - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - unsigned long start; -}; -# endif /* ! HDIO_GETGEO */ -# ifndef BLKGETSIZE64 -# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size */ -# endif /* ! BLKGETSIZE64 */ #endif /* __linux__ */ -#ifdef __CYGWIN__ -# include -# include /* BLKGETSIZE64 */ -# include /* HDIO_GETGEO */ -#endif - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -# include /* DIOCGMEDIASIZE */ -# include -# include -# include -#include -#endif - -#if defined (__sun__) -# include -#endif - -#if defined(__APPLE__) -# include -#endif - -#ifdef HAVE_DEVICE_MAPPER -# include -#endif - -#if defined(__NetBSD__) -# define HAVE_DIOCGDINFO -# include -# include /* struct disklabel */ -# include /* struct dkwedge_info */ -#else /* !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */ -# undef HAVE_DIOCGDINFO -#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */ - -#if defined(__NetBSD__) -# ifdef HAVE_GETRAWPARTITION -# include /* getrawpartition */ -# endif /* HAVE_GETRAWPARTITION */ -# include -# ifndef RAW_FLOPPY_MAJOR -# define RAW_FLOPPY_MAJOR 9 -# endif /* ! RAW_FLOPPY_MAJOR */ -#endif /* defined(__NetBSD__) */ - static struct { char *drive; @@ -122,58 +58,6 @@ static struct int device_map; } map[256]; -struct grub_util_biosdisk_data -{ - char *dev; - int access_mode; - int fd; - int is_disk; - int device_map; -}; - -#ifdef __linux__ -/* Check if we have devfs support. */ -static int -have_devfs (void) -{ - static int dev_devfsd_exists = -1; - - if (dev_devfsd_exists < 0) - { - struct stat st; - - dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0; - } - - return dev_devfsd_exists; -} -#endif /* __linux__ */ - -#if defined(__NetBSD__) -/* Adjust device driver parameters. This function should be called just - after successfully opening the device. For now, it simply prevents the - floppy driver from retrying operations on failure, as otherwise the - driver takes a while to abort when there is no floppy in the drive. */ -static void -configure_device_driver (int fd) -{ - struct stat st; - - if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) - return; - if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) - { - int floppy_opts; - - if (ioctl (fd, FDIOCGETOPTS, &floppy_opts) == -1) - return; - floppy_opts |= FDOPT_NORETRY; - if (ioctl (fd, FDIOCSETOPTS, &floppy_opts) == -1) - return; - } -} -#endif /* defined(__NetBSD__) */ - static int unescape_cmp (const char *a, const char *b_escaped) { @@ -223,7 +107,7 @@ find_free_slot (void) } static int -grub_util_biosdisk_iterate (int (*hook) (const char *name), +grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { unsigned i; @@ -232,734 +116,119 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), return 0; for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) - if (map[i].drive && hook (map[i].drive)) + if (map[i].drive && hook (map[i].drive, hook_data)) return 1; return 0; } -#if !defined(__MINGW32__) -grub_uint64_t -grub_util_get_fd_size (int fd, const char *name, unsigned *log_secsize) -{ -#if !defined (__GNU__) -# if defined(__NetBSD__) - struct disklabel label; -# elif defined (__sun__) - struct dk_minfo minfo; -# else - unsigned long long nr; -# endif -#endif - unsigned sector_size, log_sector_size; - struct stat st; - - if (fstat (fd, &st) < 0) - /* TRANSLATORS: "stat" comes from the name of POSIX function. */ - grub_util_error (_("cannot stat `%s': %s"), name, strerror (errno)); - -#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \ - || defined (__sun__) - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) - if (! S_ISCHR (st.st_mode)) -# else - if (! S_ISBLK (st.st_mode)) -# endif - goto fail; - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (ioctl (fd, DIOCGMEDIASIZE, &nr)) -# elif defined(__APPLE__) - if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr)) -# elif defined(__NetBSD__) - configure_device_driver (fd); - if (ioctl (fd, DIOCGDINFO, &label) == -1) -# elif defined (__sun__) - if (!ioctl (fd, DKIOCGMEDIAINFO, &minfo)) -# else - if (ioctl (fd, BLKGETSIZE64, &nr)) -# endif - goto fail; - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (ioctl (fd, DIOCGSECTORSIZE, §or_size)) - goto fail; -# elif defined(__APPLE__) - if (ioctl (fd, DKIOCGETBLOCKSIZE, §or_size)) - goto fail; -# elif defined(__sun__) - sector_size = minfo.dki_lbsize; -# elif defined(__NetBSD__) - sector_size = label.d_secsize; -# else - if (ioctl (fd, BLKSSZGET, §or_size)) - goto fail; -# endif - if (sector_size & (sector_size - 1) || !sector_size) - goto fail; - for (log_sector_size = 0; - (1 << log_sector_size) < sector_size; - log_sector_size++); - - if (log_secsize) - *log_secsize = log_sector_size; - -# if defined (__APPLE__) - return nr << log_sector_size; -# elif defined(__NetBSD__) - return (grub_uint64_t) label.d_secperunit << log_sector_size; -# elif defined (__sun__) - return minfo.dki_capacity << log_sector_size; -# else - if (nr & ((1 << log_sector_size) - 1)) - grub_util_error ("%s", _("unaligned device size")); - - return nr; -# endif - - fail: - - /* In GNU/Hurd, stat() will return the right size. */ -#elif !defined (__GNU__) -# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." -#endif - - sector_size = 512; - log_sector_size = 9; - - if (log_secsize) - *log_secsize = 9; - - return st.st_size; -} -#endif - static grub_err_t grub_util_biosdisk_open (const char *name, grub_disk_t disk) { int drive; - struct stat st; - struct grub_util_biosdisk_data *data; + struct grub_util_hostdisk_data *data; drive = find_grub_drive (name); + grub_util_info ("drive = %d", drive); if (drive < 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no mapping exists for `%s'", name); disk->id = drive; - disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); + disk->data = data = xmalloc (sizeof (struct grub_util_hostdisk_data)); data->dev = NULL; data->access_mode = 0; - data->fd = -1; + data->fd = GRUB_UTIL_FD_INVALID; data->is_disk = 0; data->device_map = map[drive].device_map; /* Get the size. */ -#if defined(__MINGW32__) { - grub_uint64_t size; + grub_util_fd_t fd; - size = grub_util_get_disk_size (map[drive].device); + fd = grub_util_fd_open (map[drive].device, GRUB_UTIL_FD_O_RDONLY); - if (size % 512) - grub_util_error (_("unaligned device size")); - - disk->total_sectors = size >> 9; - - grub_util_info ("the size of %s is %llu", name, disk->total_sectors); - - return GRUB_ERR_NONE; - } -#else - { - int fd; - - fd = open (map[drive].device, O_RDONLY); - if (fd == -1) + if (!GRUB_UTIL_FD_IS_VALID(fd)) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"), - map[drive].device, strerror (errno)); + map[drive].device, grub_util_fd_strerror ()); disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device, &disk->log_sector_size); disk->total_sectors >>= disk->log_sector_size; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) - if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) +#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL + { + struct stat st; +# if GRUB_DISK_DEVS_ARE_CHAR + if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) # else - if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode)) + if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode)) # endif - data->is_disk = 1; + data->is_disk = 1; + } +#endif - close (fd); + grub_util_fd_close (fd); grub_util_info ("the size of %s is %" PRIuGRUB_UINT64_T, name, disk->total_sectors); return GRUB_ERR_NONE; } -#endif -} - -int -grub_util_device_is_mapped (const char *dev) -{ -#ifdef HAVE_DEVICE_MAPPER - struct stat st; - - if (!grub_device_mapper_supported ()) - return 0; - - if (stat (dev, &st) < 0) - return 0; - - return dm_is_dm_major (major (st.st_rdev)); -#else - return 0; -#endif /* HAVE_DEVICE_MAPPER */ -} - -#ifdef HAVE_DEVICE_MAPPER -int -grub_util_get_dm_node_linear_info (const char *dev, - int *maj, int *min, - grub_disk_addr_t *st) -{ - struct dm_task *dmt; - void *next = NULL; - uint64_t length, start; - char *target, *params; - char *ptr; - int major, minor; - int first = 1; - grub_disk_addr_t partstart = 0; - - while (1) - { - dmt = dm_task_create(DM_DEVICE_TABLE); - if (!dmt) - break; - - if (! (first ? dm_task_set_name (dmt, dev) - : dm_task_set_major_minor (dmt, major, minor, 0))) - { - dm_task_destroy (dmt); - break; - } - dm_task_no_open_count(dmt); - if (!dm_task_run(dmt)) - { - dm_task_destroy (dmt); - break; - } - next = dm_get_next_target(dmt, next, &start, &length, - &target, ¶ms); - if (grub_strcmp (target, "linear") != 0) - { - dm_task_destroy (dmt); - break; - } - major = grub_strtoul (params, &ptr, 10); - if (grub_errno) - { - dm_task_destroy (dmt); - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (*ptr != ':') - { - dm_task_destroy (dmt); - return 0; - } - ptr++; - minor = grub_strtoul (ptr, &ptr, 10); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - dm_task_destroy (dmt); - return 0; - } - - if (*ptr != ' ') - { - dm_task_destroy (dmt); - return 0; - } - ptr++; - partstart += grub_strtoull (ptr, &ptr, 10); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - dm_task_destroy (dmt); - return 0; - } - - dm_task_destroy (dmt); - first = 0; - } - if (first) - return 0; - if (maj) - *maj = major; - if (min) - *min = minor; - if (st) - *st = partstart; - return 1; -} -#endif - -#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) - -/* FIXME: geom actually gives us the whole container hierarchy. - It can be used more efficiently than this. */ -void -grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out) -{ - struct gmesh mesh; - struct gclass *class; - int error; - struct ggeom *geom; - - grub_util_info ("following geom '%s'", name); - - error = geom_gettree (&mesh); - if (error != 0) - /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. - Usually left untranslated. - */ - grub_util_error ("%s", _("couldn't open geom")); - - LIST_FOREACH (class, &mesh.lg_class, lg_class) - if (strcasecmp (class->lg_name, "part") == 0) - break; - if (!class) - /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. - Usually left untranslated. "part" is the identifier of one of its - classes. */ - grub_util_error ("%s", _("couldn't find geom `part' class")); - - LIST_FOREACH (geom, &class->lg_geom, lg_geom) - { - struct gprovider *provider; - LIST_FOREACH (provider, &geom->lg_provider, lg_provider) - if (strcmp (provider->lg_name, name) == 0) - { - char *name_tmp = xstrdup (geom->lg_name); - grub_disk_addr_t off = 0; - struct gconfig *config; - grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name); - - grub_util_follow_gpart_up (name_tmp, &off, name_out); - free (name_tmp); - LIST_FOREACH (config, &provider->lg_config, lg_config) - if (strcasecmp (config->lg_name, "start") == 0) - off += strtoull (config->lg_val, 0, 10); - if (off_out) - *off_out = off; - return; - } - } - grub_util_info ("geom '%s' has no parent", name); - if (name_out) - *name_out = xstrdup (name); - if (off_out) - *off_out = 0; -} - -grub_disk_addr_t -grub_hostdisk_find_partition_start (const char *dev) -{ - grub_disk_addr_t out; - if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0) - return 0; - grub_util_follow_gpart_up (dev + sizeof ("/dev/") - 1, &out, NULL); - - return out; -} - -#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined (__sun__) -grub_disk_addr_t -grub_hostdisk_find_partition_start (const char *dev) -{ - int fd; -#ifdef __sun__ - struct extpart_info pinfo; -# elif !defined(HAVE_DIOCGDINFO) - struct hd_geometry hdg; -# else /* defined(HAVE_DIOCGDINFO) */ -# if defined(__NetBSD__) - struct dkwedge_info dkw; -# endif /* defined(__NetBSD__) */ - struct disklabel label; - int p_index; -# endif /* !defined(HAVE_DIOCGDINFO) */ - -# ifdef HAVE_DEVICE_MAPPER - grub_disk_addr_t partition_start; - if (grub_util_device_is_mapped (dev) - && grub_util_get_dm_node_linear_info (dev, 0, 0, &partition_start)) - return partition_start; -# endif /* HAVE_DEVICE_MAPPER */ - - fd = open (dev, O_RDONLY); - if (fd == -1) - { - grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - dev, strerror (errno)); - return 0; - } - -#if defined(__sun__) - if (ioctl (fd, DKIOCEXTPARTINFO, &pinfo)) -# elif !defined(HAVE_DIOCGDINFO) - if (ioctl (fd, HDIO_GETGEO, &hdg)) -# else /* defined(HAVE_DIOCGDINFO) */ -# if defined(__NetBSD__) - configure_device_driver (fd); - /* First handle the case of disk wedges. */ - if (ioctl (fd, DIOCGWEDGEINFO, &dkw) == 0) - { - close (fd); - return (grub_disk_addr_t) dkw.dkw_offset; - } -# endif /* defined(__NetBSD__) */ - if (ioctl (fd, DIOCGDINFO, &label) == -1) -# endif /* !defined(HAVE_DIOCGDINFO) */ - { - grub_error (GRUB_ERR_BAD_DEVICE, -# if !defined(HAVE_DIOCGDINFO) - "cannot get disk geometry of `%s'", dev); -# else /* defined(HAVE_DIOCGDINFO) */ - "cannot get disk label of `%s'", dev); -# endif /* !defined(HAVE_DIOCGDINFO) */ - close (fd); - return 0; - } - - close (fd); - -#ifdef __sun__ - return pinfo.p_start; -# elif !defined(HAVE_DIOCGDINFO) - return hdg.start; -# else /* defined(HAVE_DIOCGDINFO) */ - if (dev[0]) - p_index = dev[strlen(dev) - 1] - 'a'; - else - p_index = -1; - - if (p_index >= label.d_npartitions || p_index < 0) - { - grub_error (GRUB_ERR_BAD_DEVICE, - "no disk label entry for `%s'", dev); - return 0; - } - return (grub_disk_addr_t) label.d_partitions[p_index].p_offset; -# endif /* !defined(HAVE_DIOCGDINFO) */ -} -#endif /* __linux__ || __CYGWIN__ || HAVE_DIOCGDINFO */ - -#ifdef __linux__ -/* Cache of partition start sectors for each disk. */ -struct linux_partition_cache -{ - struct linux_partition_cache *next; - struct linux_partition_cache **prev; - char *dev; - unsigned long start; - int partno; -}; - -struct linux_partition_cache *linux_partition_cache_list; - -static int -linux_find_partition (char *dev, grub_disk_addr_t sector) -{ - size_t len = strlen (dev); - const char *format; - char *p; - int i; - char real_dev[PATH_MAX]; - struct linux_partition_cache *cache; - int missing = 0; - - strcpy(real_dev, dev); - - if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0) - { - p = real_dev + len - 4; - format = "part%d"; - } - else if (strncmp (real_dev, "/dev/disk/by-id/", - sizeof ("/dev/disk/by-id/") - 1) == 0) - { - p = real_dev + len; - format = "-part%d"; - } - else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9') - { - p = real_dev + len; - format = "p%d"; - } - else - { - p = real_dev + len; - format = "%d"; - } - - for (cache = linux_partition_cache_list; cache; cache = cache->next) - { - if (strcmp (cache->dev, dev) == 0 && cache->start == sector) - { - sprintf (p, format, cache->partno); - strcpy (dev, real_dev); - return 1; - } - } - - for (i = 1; i < 10000; i++) - { - int fd; - grub_disk_addr_t start; - - sprintf (p, format, i); - - fd = open (real_dev, O_RDONLY); - if (fd == -1) - { - if (missing++ < 10) - continue; - else - return 0; - } - missing = 0; - close (fd); - - start = grub_hostdisk_find_partition_start (real_dev); - /* We don't care about errors here. */ - grub_errno = GRUB_ERR_NONE; - - if (start == sector) - { - struct linux_partition_cache *new_cache_item; - - new_cache_item = xmalloc (sizeof *new_cache_item); - new_cache_item->dev = xstrdup (dev); - new_cache_item->start = start; - new_cache_item->partno = i; - grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list), - GRUB_AS_LIST (new_cache_item)); - - strcpy (dev, real_dev); - return 1; - } - } - - return 0; -} -#endif /* __linux__ */ - -#if defined(__linux__) && (!defined(__GLIBC__) || \ - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) - /* Maybe libc doesn't have large file support. */ -grub_err_t -grub_util_fd_seek (int fd, const char *name, grub_uint64_t off) -{ - loff_t offset, result; - static int _llseek (uint filedes, ulong hi, ulong lo, - loff_t *res, uint wh); - _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, - loff_t *, res, uint, wh); - - offset = (loff_t) off; - if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), - name, strerror (errno)); - return GRUB_ERR_NONE; -} -#else -grub_err_t -grub_util_fd_seek (int fd, const char *name, grub_uint64_t off) -{ - off_t offset = (off_t) off; - - if (lseek (fd, offset, SEEK_SET) != offset) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), - name, strerror (errno)); - return 0; -} -#endif - -static void -flush_initial_buffer (const char *os_dev __attribute__ ((unused))) -{ -#ifdef __linux__ - int fd; - struct stat st; - - fd = open (os_dev, O_RDONLY); - if (fd >= 0 && fstat (fd, &st) >= 0 && S_ISBLK (st.st_mode)) - ioctl (fd, BLKFLSBUF, 0); - if (fd >= 0) - close (fd); -#endif } const char * grub_hostdisk_os_dev_to_grub_drive (const char *os_disk, int add) { unsigned int i; + char *canon; + + canon = canonicalize_file_name (os_disk); + if (!canon) + canon = xstrdup (os_disk); for (i = 0; i < ARRAY_SIZE (map); i++) if (! map[i].device) break; - else if (strcmp (map[i].device, os_disk) == 0) - return map[i].drive; + else if (strcmp (map[i].device, canon) == 0) + { + free (canon); + return map[i].drive; + } if (!add) - return NULL; + { + free (canon); + return NULL; + } if (i == ARRAY_SIZE (map)) /* TRANSLATORS: it refers to the lack of free slots. */ grub_util_error ("%s", _("device count exceeds limit")); - map[i].device = xstrdup (os_disk); + map[i].device = canon; map[i].drive = xmalloc (sizeof ("hostdisk/") + strlen (os_disk)); strcpy (map[i].drive, "hostdisk/"); strcpy (map[i].drive + sizeof ("hostdisk/") - 1, os_disk); map[i].device_map = 0; - flush_initial_buffer (os_disk); + grub_hostdisk_flush_initial_buffer (os_disk); return map[i].drive; } -static int -open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, - grub_disk_addr_t *max) +#ifndef __linux__ +grub_util_fd_t +grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, + grub_disk_addr_t *max) { - int fd; - struct grub_util_biosdisk_data *data = disk->data; + grub_util_fd_t fd; + struct grub_util_hostdisk_data *data = disk->data; *max = ~0ULL; -#ifdef O_LARGEFILE - flags |= O_LARGEFILE; -#endif -#ifdef O_SYNC - flags |= O_SYNC; -#endif -#ifdef O_FSYNC - flags |= O_FSYNC; -#endif -#ifdef O_BINARY - flags |= O_BINARY; -#endif - -#ifdef __linux__ - /* Linux has a bug that the disk cache for a whole disk is not consistent - with the one for a partition of the disk. */ - { - int is_partition = 0; - char dev[PATH_MAX]; - grub_disk_addr_t part_start = 0; - - part_start = grub_partition_get_start (disk->partition); - - strcpy (dev, map[disk->id].device); - if (disk->partition - && strncmp (map[disk->id].device, "/dev/", 5) == 0) - { - if (sector >= part_start) - is_partition = linux_find_partition (dev, part_start); - else - *max = part_start - sector; - } - - reopen: - - if (data->dev && strcmp (data->dev, dev) == 0 && - data->access_mode == (flags & O_ACCMODE)) - { - grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev); - fd = data->fd; - } - else - { - free (data->dev); - data->dev = 0; - if (data->fd != -1) - { - if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) - { - fsync (data->fd); -#ifdef __linux__ - if (data->is_disk) - ioctl (data->fd, BLKFLSBUF, 0); -#endif - } - - close (data->fd); - data->fd = -1; - } - - /* Open the partition. */ - grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev); - fd = open (dev, flags); - if (fd < 0) - { - grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - dev, strerror (errno)); - return -1; - } - - data->dev = xstrdup (dev); - data->access_mode = (flags & O_ACCMODE); - data->fd = fd; - -#ifdef __linux__ - if (data->is_disk) - ioctl (data->fd, BLKFLSBUF, 0); -#endif - } - - if (is_partition) - { - *max = grub_util_get_fd_size (fd, dev, 0); - *max >>= disk->log_sector_size; - if (sector - part_start >= *max) - { - *max = disk->partition->len - (sector - part_start); - if (*max == 0) - *max = ~0ULL; - is_partition = 0; - strcpy (dev, map[disk->id].device); - goto reopen; - } - sector -= part_start; - *max -= sector; - } - } -#else /* ! __linux__ */ -#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) - int sysctl_flags, sysctl_oldflags; - size_t sysctl_size = sizeof (sysctl_flags); - - if (sysctlbyname ("kern.geom.debugflags", &sysctl_oldflags, &sysctl_size, NULL, 0)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current flags of sysctl kern.geom.debugflags"); - return -1; - } - sysctl_flags = sysctl_oldflags | 0x10; - if (! (sysctl_oldflags & 0x10) - && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_flags, sysctl_size)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags"); - return -1; - } -#endif + flags |= GRUB_UTIL_FD_O_SYNC; if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 && data->access_mode == (flags & O_ACCMODE)) @@ -971,22 +240,16 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, { free (data->dev); data->dev = 0; - if (data->fd != -1) + if (GRUB_UTIL_FD_IS_VALID(data->fd)) { if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) - { - fsync (data->fd); -#ifdef __linux__ - if (data->is_disk) - ioctl (data->fd, BLKFLSBUF, 0); -#endif - } - close (data->fd); - data->fd = -1; + grub_util_fd_sync (data->fd); + grub_util_fd_close (data->fd); + data->fd = GRUB_UTIL_FD_INVALID; } - fd = open (map[disk->id].device, flags); - if (fd >= 0) + fd = grub_util_fd_open (map[disk->id].device, flags); + if (GRUB_UTIL_FD_IS_VALID(fd)) { data->dev = xstrdup (map[disk->id].device); data->access_mode = (flags & O_ACCMODE); @@ -994,94 +257,26 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, } } -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (! (sysctl_oldflags & 0x10) - && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_oldflags, sysctl_size)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags back to the old value for sysctl kern.geom.debugflags"); - return -1; - } -#endif - -#if defined(__APPLE__) - /* If we can't have exclusive access, try shared access */ - if (fd < 0) - fd = open(map[disk->id].device, flags | O_SHLOCK); -#endif - - if (fd < 0) + if (!GRUB_UTIL_FD_IS_VALID(data->fd)) { grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - map[disk->id].device, strerror (errno)); - return -1; + map[disk->id].device, grub_util_fd_strerror ()); + return GRUB_UTIL_FD_INVALID; } -#endif /* ! __linux__ */ -#if defined(__NetBSD__) - configure_device_driver (fd); -#endif /* defined(__NetBSD__) */ - - if (grub_util_fd_seek (fd, map[disk->id].device, - sector << disk->log_sector_size)) + if (grub_util_fd_seek (fd, sector << disk->log_sector_size)) { - close (fd); - return -1; + grub_util_fd_close (fd); + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + map[disk->id].device, grub_util_fd_strerror ()); + + return GRUB_UTIL_FD_INVALID; } return fd; } +#endif -/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an - error occurs, otherwise return LEN. */ -ssize_t -grub_util_fd_read (int fd, char *buf, size_t len) -{ - ssize_t size = len; - - while (len) - { - ssize_t ret = read (fd, buf, len); - - if (ret <= 0) - { - if (errno == EINTR) - continue; - else - return ret; - } - - len -= ret; - buf += ret; - } - - return size; -} - -/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an - error occurs, otherwise return LEN. */ -ssize_t -grub_util_fd_write (int fd, const char *buf, size_t len) -{ - ssize_t size = len; - - while (len) - { - ssize_t ret = write (fd, buf, len); - - if (ret <= 0) - { - if (errno == EINTR) - continue; - else - return ret; - } - - len -= ret; - buf += ret; - } - - return size; -} static grub_err_t grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, @@ -1089,10 +284,10 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, { while (size) { - int fd; + grub_util_fd_t fd; grub_disk_addr_t max = ~0ULL; - fd = open_device (disk, sector, O_RDONLY, &max); - if (fd < 0) + fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_RDONLY, &max); + if (!GRUB_UTIL_FD_IS_VALID (fd)) return grub_errno; #ifdef __linux__ @@ -1110,7 +305,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, if (grub_util_fd_read (fd, buf, max << disk->log_sector_size) != (ssize_t) (max << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - map[disk->id].device, strerror (errno)); + map[disk->id].device, grub_util_fd_strerror ()); size -= max; buf += (max << disk->log_sector_size); sector += max; @@ -1124,10 +319,10 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { while (size) { - int fd; + grub_util_fd_t fd; grub_disk_addr_t max = ~0ULL; - fd = open_device (disk, sector, O_WRONLY, &max); - if (fd < 0) + fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_WRONLY, &max); + if (!GRUB_UTIL_FD_IS_VALID (fd)) return grub_errno; #ifdef __linux__ @@ -1145,7 +340,7 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, if (grub_util_fd_write (fd, buf, max << disk->log_sector_size) != (ssize_t) (max << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"), - map[disk->id].device, strerror (errno)); + map[disk->id].device, grub_util_fd_strerror ()); size -= max; buf += (max << disk->log_sector_size); } @@ -1155,18 +350,18 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk) { - struct grub_util_biosdisk_data *data = disk->data; + struct grub_util_hostdisk_data *data = disk->data; if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID) return GRUB_ERR_NONE; - if (data->fd == -1) + if (!GRUB_UTIL_FD_IS_VALID (data->fd)) { grub_disk_addr_t max; - data->fd = open_device (disk, 0, O_RDONLY, &max); - if (data->fd < 0) + data->fd = grub_util_fd_open_device (disk, 0, GRUB_UTIL_FD_O_RDONLY, &max); + if (!GRUB_UTIL_FD_IS_VALID (data->fd)) return grub_errno; } - fsync (data->fd); + grub_util_fd_sync (data->fd); #ifdef __linux__ if (data->is_disk) ioctl (data->fd, BLKFLSBUF, 0); @@ -1177,14 +372,14 @@ grub_util_biosdisk_flush (struct grub_disk *disk) static void grub_util_biosdisk_close (struct grub_disk *disk) { - struct grub_util_biosdisk_data *data = disk->data; + struct grub_util_hostdisk_data *data = disk->data; free (data->dev); - if (data->fd != -1) + if (GRUB_UTIL_FD_IS_VALID (data->fd)) { if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) grub_util_biosdisk_flush (disk); - close (data->fd); + grub_util_fd_close (data->fd); } free (data); } @@ -1201,20 +396,31 @@ static struct grub_disk_dev grub_util_biosdisk_dev = .next = 0 }; +static int +grub_util_check_file_presence (const char *p) +{ +#if !GRUB_UTIL_FD_STAT_IS_FUNCTIONAL + grub_util_fd_t h; + h = grub_util_fd_open (p, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID(h)) + return 0; + grub_util_fd_close (h); + return 1; +#else + struct stat st; + + if (stat (p, &st) == -1) + return 0; + return 1; +#endif +} + static void read_device_map (const char *dev_map) { FILE *fp; char buf[1024]; /* XXX */ int lineno = 0; - struct stat st; - - auto void show_error (const char *msg) - __attribute__ ((noreturn)); - void __attribute__ ((noreturn)) show_error (const char *msg) - { - grub_util_error ("%s:%d: %s", dev_map, lineno, msg); - } if (dev_map[0] == '\0') { @@ -1222,7 +428,7 @@ read_device_map (const char *dev_map) return; } - fp = fopen (dev_map, "r"); + fp = grub_util_fopen (dev_map, "r"); if (! fp) { grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno)); @@ -1250,14 +456,14 @@ read_device_map (const char *dev_map) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), '('); - show_error (tmp); + grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); } p++; /* Find a free slot. */ drive = find_free_slot (); if (drive < 0) - show_error (_("device count exceeds limit")); + grub_util_error ("%s:%d: %s", dev_map, lineno, _("device count exceeds limit")); e = p; p = strchr (p, ')'); @@ -1265,7 +471,7 @@ read_device_map (const char *dev_map) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), ')'); - show_error (tmp); + grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); } map[drive].drive = 0; @@ -1310,7 +516,7 @@ read_device_map (const char *dev_map) p++; if (*p == '\0') - show_error (_("filename expected")); + grub_util_error ("%s:%d: %s", dev_map, lineno, _("filename expected")); /* NUL-terminate the filename. */ e = p; @@ -1318,12 +524,7 @@ read_device_map (const char *dev_map) e++; *e = '\0'; -#ifdef __MINGW32__ - (void) st; - if (grub_util_get_disk_size (p) == -1LL) -#else - if (stat (p, &st) == -1) -#endif + if (!grub_util_check_file_presence (p)) { free (map[drive].drive); map[drive].drive = NULL; @@ -1343,19 +544,13 @@ 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. Leave /dev/mapper/ alone, though. */ - if (strncmp (p, "/dev/mapper/", 12) != 0) - { - map[drive].device = xmalloc (PATH_MAX); - if (! realpath (p, map[drive].device)) - grub_util_error (_("failed to get canonical path of %s"), p); - } - else -#endif - map[drive].device = xstrdup (p); + symbolic links. */ + map[drive].device = canonicalize_file_name (p); + if (! map[drive].device) + map[drive].device = xstrdup (p); + if (!map[drive].drive) { char c; @@ -1377,7 +572,10 @@ read_device_map (const char *dev_map) *drive_p = c; } - flush_initial_buffer (map[drive].device); + grub_util_info ("adding `%s' -> `%s' from device.map", map[drive].drive, + map[drive].device); + + grub_hostdisk_flush_initial_buffer (map[drive].device); } fclose (fp); diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c index 3cb089c3f..b51462641 100644 --- a/grub-core/kern/emu/hostfs.c +++ b/grub-core/kern/emu/hostfs.c @@ -16,6 +16,9 @@ * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ + +#include + #define _BSD_SOURCE #include #include @@ -27,13 +30,8 @@ #include #include -#include #include #include - - -/* dirent.d_type is a BSD extension, not part of POSIX */ -#include #include static int @@ -51,51 +49,47 @@ is_dir (const char *path, const char *name) strcat (pathname, name); - struct stat st; - if (stat (pathname, &st)) - return 0; - return S_ISDIR (st.st_mode); + return grub_util_is_directory (pathname); } struct grub_hostfs_data { char *filename; - FILE *f; + grub_util_fd_t f; }; static grub_err_t grub_hostfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { - DIR *dir; + grub_util_fd_dir_t dir; /* Check if the disk is our dummy disk. */ if (grub_strcmp (device->disk->name, "host")) return grub_error (GRUB_ERR_BAD_FS, "not a hostfs"); - dir = opendir (path); + dir = grub_util_fd_opendir (path); if (! dir) return grub_error (GRUB_ERR_BAD_FILENAME, N_("can't open `%s': %s"), path, - strerror (errno)); + grub_util_fd_strerror ()); while (1) { - struct dirent *de; + grub_util_fd_dirent_t de; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); - de = readdir (dir); + de = grub_util_fd_readdir (dir); if (! de) break; info.dir = !! is_dir (path, de->d_name); - hook (de->d_name, &info); + hook (de->d_name, &info, hook_data); } - closedir (dir); + grub_util_fd_closedir (dir); return GRUB_ERR_NONE; } @@ -104,25 +98,25 @@ grub_hostfs_dir (grub_device_t device, const char *path, static grub_err_t grub_hostfs_open (struct grub_file *file, const char *name) { - FILE *f; + grub_util_fd_t f; struct grub_hostfs_data *data; - f = fopen (name, "rb"); - if (! f) + f = grub_util_fd_open (name, GRUB_UTIL_FD_O_RDONLY); + if (! GRUB_UTIL_FD_IS_VALID (f)) return grub_error (GRUB_ERR_BAD_FILENAME, N_("can't open `%s': %s"), name, strerror (errno)); data = grub_malloc (sizeof (*data)); if (!data) { - fclose (f); + grub_util_fd_close (f); return grub_errno; } data->filename = grub_strdup (name); if (!data->filename) { grub_free (data); - fclose (f); + grub_util_fd_close (f); return grub_errno; } @@ -130,11 +124,7 @@ grub_hostfs_open (struct grub_file *file, const char *name) file->data = data; -#ifdef __MINGW32__ - file->size = grub_util_get_disk_size (name); -#else - file->size = grub_util_get_fd_size (fileno (f), name, NULL); -#endif + file->size = grub_util_get_fd_size (f, name, NULL); return GRUB_ERR_NONE; } @@ -145,17 +135,17 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hostfs_data *data; data = file->data; - if (fseeko (data->f, file->offset, SEEK_SET) != 0) + if (grub_util_fd_seek (data->f, file->offset) != 0) { grub_error (GRUB_ERR_OUT_OF_RANGE, N_("cannot seek `%s': %s"), - data->filename, strerror (errno)); + data->filename, grub_util_fd_strerror ()); return -1; } - unsigned int s = fread (buf, 1, len, data->f); + unsigned int s = grub_util_fd_read (data->f, buf, len); if (s != len) grub_error (GRUB_ERR_FILE_READ_ERROR, N_("cannot read `%s': %s"), - data->filename, strerror (errno)); + data->filename, grub_util_fd_strerror ()); return (signed) s; } @@ -166,7 +156,7 @@ grub_hostfs_close (grub_file_t file) struct grub_hostfs_data *data; data = file->data; - fclose (data->f); + grub_util_fd_close (data->f); grub_free (data->filename); grub_free (data); diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c index 947c669aa..00b811bf5 100644 --- a/grub-core/kern/emu/lite.c +++ b/grub-core/kern/emu/lite.c @@ -21,6 +21,8 @@ #error "No target cpu type is defined" #endif +const int grub_no_modules = 0; + /* grub-emu-lite supports dynamic module loading, so it won't have any embedded modules. */ void @@ -34,14 +36,3 @@ grub_fini_all (void) { return; } - -void -grub_emu_init (void) -{ - return; -} - -void -grub_emu_post_init (void) -{ -} diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 0418aae64..94c2902f6 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -16,15 +16,16 @@ * along with GRUB. If not, see . */ +#include +#include + #include #include #include #include -#include #include #include #include -#include #include #include @@ -40,6 +41,8 @@ #include #include #include +#include +#include #include "progname.h" #include @@ -52,8 +55,6 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ static char *root_dev = NULL, *dir = NULL; -int grub_no_autoload; - grub_addr_t grub_modbase = 0; void @@ -75,9 +76,10 @@ grub_machine_get_bootlocation (char **device, char **path) } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_console_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_console_fini (); } @@ -164,12 +166,6 @@ static struct argp argp = { -void grub_hostfs_init (void); -void grub_hostfs_fini (void); -void grub_host_init (void); -void grub_host_fini (void); -void grub_emu_init (void); - int main (int argc, char *argv[]) { @@ -180,7 +176,7 @@ main (int argc, char *argv[]) }; volatile int hold = 0; - set_program_name (argv[0]); + grub_util_host_init (&argc, &argv); dir = xstrdup (DEFAULT_DIRECTORY); @@ -205,7 +201,6 @@ main (int argc, char *argv[]) } signal (SIGINT, SIG_IGN); - grub_emu_init (); grub_console_init (); grub_host_init (); @@ -216,8 +211,6 @@ main (int argc, char *argv[]) grub_hostfs_init (); - grub_emu_post_init (); - /* Make sure that there is a root device. */ if (! root_dev) root_dev = grub_strdup ("host"); @@ -232,29 +225,7 @@ main (int argc, char *argv[]) grub_hostfs_fini (); grub_host_fini (); - grub_machine_fini (); + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); return 0; } - -#ifdef __MINGW32__ - -void -grub_millisleep (grub_uint32_t ms) -{ - Sleep (ms); -} - -#else - -void -grub_millisleep (grub_uint32_t ms) -{ - struct timespec ts; - - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000; - nanosleep (&ts, NULL); -} - -#endif diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 21954ed50..43471b4ef 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -27,11 +27,6 @@ #include #include #include -#include -#include -#ifdef HAVE_LIMITS_H -#include -#endif #include #include @@ -42,27 +37,6 @@ #include #include -#ifdef HAVE_DEVICE_MAPPER -# include -#endif - -#ifdef HAVE_SYS_PARAM_H -# include -#endif - -#ifdef HAVE_SYS_MOUNT_H -# include -#endif - -#ifdef HAVE_SYS_MNTTAB_H -# include /* Needed by sys/mnttab.h. */ -# include -#endif - -#ifdef HAVE_SYS_MKDEV_H -# include /* makedev */ -#endif - int verbosity; void @@ -145,36 +119,7 @@ xstrdup (const char *str) return newstr; } -#ifndef HAVE_VASPRINTF - -int -vasprintf (char **buf, const char *fmt, va_list ap) -{ - /* Should be large enough. */ - *buf = xmalloc (512); - - return vsnprintf (*buf, 512, fmt, ap); -} - -#endif - -#ifndef HAVE_ASPRINTF - -int -asprintf (char **buf, const char *fmt, ...) -{ - int status; - va_list ap; - - va_start (ap, fmt); - status = vasprintf (buf, fmt, ap); - va_end (ap); - - return status; -} - -#endif - +#if !defined (GRUB_MKFONT) && !defined (GRUB_BUILD) char * xasprintf (const char *fmt, ...) { @@ -182,15 +127,13 @@ xasprintf (const char *fmt, ...) char *result; va_start (ap, fmt); - if (vasprintf (&result, fmt, ap) < 0) - { - if (errno == ENOMEM) - grub_util_error ("%s", _("out of memory")); - return NULL; - } + result = grub_xvasprintf (fmt, ap); + if (!result) + grub_util_error ("%s", _("out of memory")); return result; } +#endif void grub_exit (void) @@ -207,68 +150,3 @@ grub_get_time_ms (void) return (tv.tv_sec * 1000 + tv.tv_usec / 1000); } - -grub_uint32_t -grub_get_rtc (void) -{ - struct timeval tv; - - gettimeofday (&tv, 0); - - return (tv.tv_sec * GRUB_TICKS_PER_SECOND - + (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec) - * GRUB_TICKS_PER_SECOND / 1000000)); -} - -char * -canonicalize_file_name (const char *path) -{ - char *ret; -#ifdef __MINGW32__ - ret = xmalloc (PATH_MAX); - if (!_fullpath (ret, path, PATH_MAX)) - return NULL; -#elif defined (PATH_MAX) - ret = xmalloc (PATH_MAX); - if (!realpath (path, ret)) - return NULL; -#else - ret = realpath (path, NULL); -#endif - return ret; -} - -#ifdef HAVE_DEVICE_MAPPER -static void device_mapper_null_log (int level __attribute__ ((unused)), - const char *file __attribute__ ((unused)), - int line __attribute__ ((unused)), - int dm_errno __attribute__ ((unused)), - const char *f __attribute__ ((unused)), - ...) -{ -} - -int -grub_device_mapper_supported (void) -{ - static int supported = -1; - - if (supported == -1) - { - struct dm_task *dmt; - - /* Suppress annoying log messages. */ - dm_log_with_errno_init (&device_mapper_null_log); - - dmt = dm_task_create (DM_DEVICE_VERSION); - supported = (dmt != NULL); - if (dmt) - dm_task_destroy (dmt); - - /* Restore the original logger. */ - dm_log_with_errno_init (NULL); - } - - return supported; -} -#endif /* HAVE_DEVICE_MAPPER */ diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c index 0461ea51c..10e1cc0d9 100644 --- a/grub-core/kern/emu/mm.c +++ b/grub-core/kern/emu/mm.c @@ -63,22 +63,20 @@ grub_realloc (void *ptr, grub_size_t size) return ret; } +#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) void * grub_memalign (grub_size_t align, grub_size_t size) { void *p; -#if defined(HAVE_POSIX_MEMALIGN) if (align < sizeof (void *)) align = sizeof (void *); + +#if defined(HAVE_POSIX_MEMALIGN) if (posix_memalign (&p, align, size) != 0) p = 0; #elif defined(HAVE_MEMALIGN) p = memalign (align, size); -#else - (void) align; - (void) size; - grub_util_error (_("grub_memalign is not supported on your system")); #endif if (!p) @@ -86,3 +84,4 @@ grub_memalign (grub_size_t align, grub_size_t size) return p; } +#endif diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c index 7bfa238e1..c40862642 100644 --- a/grub-core/kern/env.c +++ b/grub-core/kern/env.c @@ -166,11 +166,10 @@ grub_env_unset (const char *name) grub_free (var); } -void -grub_env_iterate (int (*func) (struct grub_env_var *var)) +struct grub_env_var * +grub_env_update_get_sorted (void) { - struct grub_env_sorted_var *sorted_list = 0; - struct grub_env_sorted_var *sorted_var; + struct grub_env_var *sorted_list = 0; int i; /* Add variables associated with this context into a sorted list. */ @@ -180,40 +179,20 @@ grub_env_iterate (int (*func) (struct grub_env_var *var)) for (var = grub_current_context->vars[i]; var; var = var->next) { - struct grub_env_sorted_var *p, **q; + struct grub_env_var *p, **q; - sorted_var = grub_malloc (sizeof (*sorted_var)); - if (! sorted_var) - goto fail; - - sorted_var->var = var; - - for (q = &sorted_list, p = *q; p; q = &((*q)->next), p = *q) + for (q = &sorted_list, p = *q; p; q = &((*q)->sorted_next), p = *q) { - if (grub_strcmp (p->var->name, var->name) > 0) + if (grub_strcmp (p->name, var->name) > 0) break; } - sorted_var->next = *q; - *q = sorted_var; + var->sorted_next = *q; + *q = var; } } - /* Iterate FUNC on the sorted list. */ - for (sorted_var = sorted_list; sorted_var; sorted_var = sorted_var->next) - if (func (sorted_var->var)) - break; - - fail: - - /* Free the sorted list. */ - for (sorted_var = sorted_list; sorted_var; ) - { - struct grub_env_sorted_var *tmp = sorted_var->next; - - grub_free (sorted_var); - sorted_var = tmp; - } + return sorted_list; } grub_err_t diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c index 52ba6de62..53c734de7 100644 --- a/grub-core/kern/err.c +++ b/grub-core/kern/err.c @@ -47,18 +47,6 @@ grub_error (grub_err_t n, const char *fmt, ...) return n; } -void -grub_fatal (const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - grub_vprintf (_(fmt), ap); - va_end (ap); - - grub_abort (); -} - void grub_error_push (void) { diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 495326f12..ea1817a41 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -64,7 +64,7 @@ grub_file_open (const char *name) grub_device_t device = 0; grub_file_t file = 0, last_file = 0; char *device_name; - char *file_name; + const char *file_name; grub_file_filter_id_t filter; device_name = grub_file_get_device_name (name); @@ -76,7 +76,7 @@ grub_file_open (const char *name) if (file_name) file_name++; else - file_name = (char *) name; + file_name = name; device = grub_device_open (device_name); grub_free (device_name); @@ -87,6 +87,9 @@ grub_file_open (const char *name) if (! file) goto fail; + file->name = grub_strdup (name); + grub_errno = GRUB_ERR_NONE; + file->device = device; if (device->disk && file_name[0] != '/') @@ -107,7 +110,7 @@ grub_file_open (const char *name) if (grub_file_filters_enabled[filter]) { last_file = file; - file = grub_file_filters_enabled[filter] (file); + file = grub_file_filters_enabled[filter] (file, name); } if (!file) grub_file_close (last_file); @@ -131,10 +134,14 @@ grub_file_open (const char *name) return 0; } +grub_disk_read_hook_t grub_file_progress_hook; + grub_ssize_t grub_file_read (grub_file_t file, void *buf, grub_size_t len) { grub_ssize_t res; + grub_disk_read_hook_t read_hook; + void *read_hook_data; if (file->offset > file->size) { @@ -155,7 +162,17 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; + read_hook = file->read_hook; + read_hook_data = file->read_hook_data; + if (!file->read_hook) + { + file->read_hook = grub_file_progress_hook; + file->read_hook_data = file; + file->progress_offset = file->offset; + } res = (file->fs->read) (file, buf, len); + file->read_hook = read_hook; + file->read_hook_data = read_hook_data; if (res > 0) file->offset += res; diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 51d89d1b8..9085895b6 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -32,18 +32,19 @@ grub_fs_t grub_fs_list = 0; grub_fs_autoload_hook_t grub_fs_autoload_hook = 0; +/* Helper for grub_fs_probe. */ +static int +probe_dummy_iter (const char *filename __attribute__ ((unused)), + const struct grub_dirhook_info *info __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + return 1; +} + grub_fs_t grub_fs_probe (grub_device_t device) { grub_fs_t p; - auto int dummy_func (const char *filename, - const struct grub_dirhook_info *info); - - int dummy_func (const char *filename __attribute__ ((unused)), - const struct grub_dirhook_info *info __attribute__ ((unused))) - { - return 1; - } if (device->disk) { @@ -69,7 +70,7 @@ grub_fs_probe (grub_device_t device) } else #endif - (p->dir) (device, "/", dummy_func); + (p->dir) (device, "/", probe_dummy_iter, NULL); if (grub_errno == GRUB_ERR_NONE) return p; @@ -93,7 +94,7 @@ grub_fs_probe (grub_device_t device) { p = grub_fs_list; - (p->dir) (device, "/", dummy_func); + (p->dir) (device, "/", probe_dummy_iter, NULL); if (grub_errno == GRUB_ERR_NONE) { count--; diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c new file mode 100644 index 000000000..6cdfc9645 --- /dev/null +++ b/grub-core/kern/i386/coreboot/cbtable.c @@ -0,0 +1,83 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* Helper for grub_linuxbios_table_iterate. */ +static int +check_signature (grub_linuxbios_table_header_t tbl_header) +{ + if (! grub_memcmp (tbl_header->signature, "LBIO", 4)) + return 1; + + return 0; +} + +grub_err_t +grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t, + void *), + void *hook_data) +{ + grub_linuxbios_table_header_t table_header; + grub_linuxbios_table_item_t table_item; + + /* Assuming table_header is aligned to its size (8 bytes). */ + + for (table_header = (grub_linuxbios_table_header_t) 0x500; + table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++) + if (check_signature (table_header)) + goto signature_found; + + for (table_header = (grub_linuxbios_table_header_t) 0xf0000; + table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++) + if (check_signature (table_header)) + goto signature_found; + + grub_fatal ("Could not find coreboot table\n"); + +signature_found: + + table_item = + (grub_linuxbios_table_item_t) ((long) table_header + + (long) table_header->header_size); + for (; table_item < (grub_linuxbios_table_item_t) ((long) table_header + + (long) table_header->header_size + + (long) table_header->table_size); + table_item = (grub_linuxbios_table_item_t) ((long) table_item + (long) table_item->size)) + { + if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK + && check_signature ((grub_linuxbios_table_header_t) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1))) + { + table_header = (grub_linuxbios_table_header_t) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1); + goto signature_found; + } + if (hook (table_item, hook_data)) + return 1; + } + + return 0; +} diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 52fbba4e8..6b150b47d 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,9 +34,7 @@ #include #include #include -#ifdef GRUB_MACHINE_QEMU -#include -#endif +#include extern grub_uint8_t _start[]; extern grub_uint8_t _end[]; @@ -51,64 +49,80 @@ grub_exit (void) grub_cpu_idle (); } -#ifdef GRUB_MACHINE_QEMU -grub_addr_t grub_modbase; -#else -grub_addr_t grub_modbase = ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN); +grub_addr_t grub_modbase = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR; +static grub_uint64_t modend; + +/* Helper for grub_machine_init. */ +static int +heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + grub_uint64_t begin = addr, end = addr + size; + +#if GRUB_CPU_SIZEOF_VOID_P == 4 + /* Restrict ourselves to 32-bit memory space. */ + if (begin > GRUB_ULONG_MAX) + return 0; + if (end > GRUB_ULONG_MAX) + end = GRUB_ULONG_MAX; #endif + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* Avoid the lower memory. */ + if (begin < GRUB_MEMORY_MACHINE_LOWER_SIZE) + begin = GRUB_MEMORY_MACHINE_LOWER_SIZE; + + if (modend && begin < modend) + begin = modend; + + if (end <= begin) + return 0; + + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin)); + + return 0; +} + +#ifndef GRUB_MACHINE_MULTIBOOT + void grub_machine_init (void) { -#ifdef GRUB_MACHINE_QEMU - grub_modbase = grub_core_entry_addr + (_edata - _start); + modend = grub_modules_get_end (); + + grub_video_coreboot_fb_early_init (); - grub_qemu_init_cirrus (); -#endif - /* Initialize the console as early as possible. */ grub_vga_text_init (); - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, - grub_memory_type_t type) - { -#if GRUB_CPU_SIZEOF_VOID_P == 4 - /* Restrict ourselves to 32-bit memory space. */ - if (addr > GRUB_ULONG_MAX) - return 0; - if (addr + size > GRUB_ULONG_MAX) - size = GRUB_ULONG_MAX - addr; -#endif + grub_machine_mmap_iterate (heap_init, NULL); - if (type != GRUB_MEMORY_AVAILABLE) - return 0; + grub_video_coreboot_fb_late_init (); - /* Avoid the lower memory. */ - if (addr < GRUB_MEMORY_MACHINE_LOWER_SIZE) - { - if (addr + size <= GRUB_MEMORY_MACHINE_LOWER_SIZE) - return 0; - else - { - size -= GRUB_MEMORY_MACHINE_LOWER_SIZE - addr; - addr = GRUB_MEMORY_MACHINE_LOWER_SIZE; - } - } - - grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size); - - return 0; - } - -#if defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU) - grub_machine_mmap_init (); -#endif - grub_machine_mmap_iterate (heap_init); + grub_font_init (); + grub_gfxterm_init (); grub_tsc_init (); } +#else + +void +grub_machine_init (void) +{ + modend = grub_modules_get_end (); + + grub_vga_text_init (); + + grub_machine_mmap_init (); + grub_machine_mmap_iterate (heap_init, NULL); + + grub_tsc_init (); +} + +#endif + void grub_machine_get_bootlocation (char **device __attribute__ ((unused)), char **path __attribute__ ((unused))) @@ -116,8 +130,9 @@ grub_machine_get_bootlocation (char **device __attribute__ ((unused)), } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_vga_text_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_vga_text_fini (); grub_stop_floppy (); } diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c index 8b0b20265..119797551 100644 --- a/grub-core/kern/i386/coreboot/mmap.c +++ b/grub-core/kern/i386/coreboot/mmap.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2007,2008,2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,87 +22,51 @@ #include #include -static grub_err_t -grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t)) +/* Context for grub_machine_mmap_iterate. */ +struct grub_machine_mmap_iterate_ctx { - grub_linuxbios_table_header_t table_header; - grub_linuxbios_table_item_t table_item; + grub_memory_hook_t hook; + void *hook_data; +}; - auto int check_signature (grub_linuxbios_table_header_t); - int check_signature (grub_linuxbios_table_header_t tbl_header) - { - if (! grub_memcmp (tbl_header->signature, "LBIO", 4)) - return 1; +#define GRUB_MACHINE_MEMORY_BADRAM 5 +/* Helper for grub_machine_mmap_iterate. */ +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data) +{ + struct grub_machine_mmap_iterate_ctx *ctx = data; + mem_region_t mem_region; + + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_MEMORY) return 0; - } - /* Assuming table_header is aligned to its size (8 bytes). */ - - for (table_header = (grub_linuxbios_table_header_t) 0x500; - table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++) - if (check_signature (table_header)) - goto signature_found; - - for (table_header = (grub_linuxbios_table_header_t) 0xf0000; - table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++) - if (check_signature (table_header)) - goto signature_found; - - grub_fatal ("Could not find coreboot table\n"); - -signature_found: - - table_item = - (grub_linuxbios_table_item_t) ((long) table_header + - (long) table_header->size); - for (; table_item->size; - table_item = (grub_linuxbios_table_item_t) ((long) table_item + (long) table_item->size)) + mem_region = + (mem_region_t) ((long) table_item + + sizeof (struct grub_linuxbios_table_item)); + while ((long) mem_region < (long) table_item + (long) table_item->size) { - if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK - && check_signature ((grub_linuxbios_table_header_t) (grub_addr_t) - *(grub_uint64_t *) (table_item + 1))) - { - table_header = (grub_linuxbios_table_header_t) (grub_addr_t) - *(grub_uint64_t *) (table_item + 1); - goto signature_found; - } - if (hook (table_item)) - return 1; + if (ctx->hook (mem_region->addr, mem_region->size, + /* Multiboot mmaps match with the coreboot mmap + definition. Therefore, we can just pass type + through. */ + (((mem_region->type <= GRUB_MACHINE_MEMORY_BADRAM) && (mem_region->type >= GRUB_MACHINE_MEMORY_AVAILABLE)) + || mem_region->type == GRUB_MEMORY_COREBOOT_TABLES) ? mem_region->type : GRUB_MEMORY_RESERVED, + ctx->hook_data)) + return 1; + + mem_region++; } return 0; } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { - mem_region_t mem_region; + struct grub_machine_mmap_iterate_ctx ctx = { hook, hook_data }; - auto int iterate_linuxbios_table (grub_linuxbios_table_item_t); - int iterate_linuxbios_table (grub_linuxbios_table_item_t table_item) - { - if (table_item->tag != GRUB_LINUXBIOS_MEMBER_MEMORY) - return 0; - - mem_region = - (mem_region_t) ((long) table_item + - sizeof (struct grub_linuxbios_table_item)); - while ((long) mem_region < (long) table_item + (long) table_item->size) - { - if (hook (mem_region->addr, mem_region->size, - /* Multiboot mmaps match with the coreboot mmap definition. - Therefore, we can just pass type through. */ - mem_region->type)) - return 1; - - mem_region++; - } - - return 0; - } - - grub_linuxbios_table_iterate (iterate_linuxbios_table); + grub_linuxbios_table_iterate (iterate_linuxbios_table, &ctx); return 0; } diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c index 6bd8f3e87..a28316cc6 100644 --- a/grub-core/kern/i386/efi/init.c +++ b/grub-core/kern/i386/efi/init.c @@ -26,6 +26,7 @@ #include #include #include +#include void grub_machine_init (void) @@ -35,7 +36,8 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_efi_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_efi_fini (); } diff --git a/grub-core/kern/i386/multiboot_mmap.c b/grub-core/kern/i386/multiboot_mmap.c index 1cb422fef..e8f4f34b9 100644 --- a/grub-core/kern/i386/multiboot_mmap.c +++ b/grub-core/kern/i386/multiboot_mmap.c @@ -57,13 +57,13 @@ grub_machine_mmap_init (void) } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr; while ((unsigned long) entry < kern_multiboot_info.mmap_addr + kern_multiboot_info.mmap_length) { - if (hook (entry->addr, entry->len, entry->type)) + if (hook (entry->addr, entry->len, entry->type, hook_data)) break; entry = (void *) ((grub_addr_t) entry + entry->size + sizeof (entry->size)); diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 0841d8bb1..2319adf12 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -52,8 +52,8 @@ void (*grub_pc_net_config) (char **device, char **path); * return the real time in ticks, of which there are about * 18-20 per second */ -grub_uint32_t -grub_get_rtc (void) +grub_uint64_t +grub_rtc_get_time_ms (void) { struct grub_bios_int_registers regs; @@ -61,7 +61,7 @@ grub_get_rtc (void) regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x1a, ®s); - return (regs.ecx << 16) | (regs.edx & 0xffff); + return ((regs.ecx << 16) | (regs.edx & 0xffff)) * 55ULL; } void @@ -154,6 +154,36 @@ compact_mem_regions (void) grub_addr_t grub_modbase; extern grub_uint8_t _start[], _edata[]; +/* Helper for grub_machine_init. */ +static int +mmap_iterate_hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + /* Avoid the lower memory. */ + if (addr < 0x100000) + { + if (size <= 0x100000 - addr) + return 0; + + size -= 0x100000 - addr; + addr = 0x100000; + } + + /* Ignore >4GB. */ + if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) + { + grub_size_t len; + + len = (grub_size_t) ((addr + size > 0xFFFFFFFF) + ? 0xFFFFFFFF - addr + : size); + add_mem_region (addr, len); + } + + return 0; +} + void grub_machine_init (void) { @@ -161,6 +191,7 @@ grub_machine_init (void) #if 0 int grub_lower_mem; #endif + grub_addr_t modend; grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); @@ -188,48 +219,29 @@ grub_machine_init (void) grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_memory_type_t type) - { - /* Avoid the lower memory. */ - if (addr < 0x100000) - { - if (size <= 0x100000 - addr) - return 0; - - size -= 0x100000 - addr; - addr = 0x100000; - } - - /* Ignore >4GB. */ - if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) - { - grub_size_t len; - - len = (grub_size_t) ((addr + size > 0xFFFFFFFF) - ? 0xFFFFFFFF - addr - : size); - add_mem_region (addr, len); - } - - return 0; - } - - grub_machine_mmap_iterate (hook); + grub_machine_mmap_iterate (mmap_iterate_hook, NULL); compact_mem_regions (); + modend = grub_modules_get_end (); for (i = 0; i < num_regions; i++) - grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size); + { + grub_addr_t beg = mem_regions[i].addr; + grub_addr_t fin = mem_regions[i].addr + mem_regions[i].size; + if (modend && beg < modend) + beg = modend; + if (beg >= fin) + continue; + grub_mm_init_region ((void *) beg, fin - beg); + } grub_tsc_init (); } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_console_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_console_fini (); grub_stop_floppy (); } diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c index 480ffa949..b34cbad03 100644 --- a/grub-core/kern/i386/pc/mmap.c +++ b/grub-core/kern/i386/pc/mmap.c @@ -139,7 +139,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { grub_uint32_t cont; struct grub_machine_mmap_entry *entry @@ -156,7 +156,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) 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)) + entry->type, hook_data)) break; if (! cont) @@ -172,18 +172,19 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) grub_uint32_t eisa_mmap = grub_get_eisa_mmap (); if (hook (0x0, ((grub_uint32_t) grub_get_conv_memsize ()) << 10, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 0; if (eisa_mmap) { if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, - GRUB_MEMORY_AVAILABLE) == 0) - hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data) == 0) + hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE, + hook_data); } else hook (0x100000, ((grub_uint32_t) grub_get_ext_memsize ()) << 10, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); } return 0; diff --git a/grub-core/kern/i386/pit.c b/grub-core/kern/i386/pit.c deleted file mode 100644 index 82a17d3e0..000000000 --- a/grub-core/kern/i386/pit.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include - -#define TIMER2_REG_CONTROL 0x42 -#define TIMER_REG_COMMAND 0x43 -#define TIMER2_REG_LATCH 0x61 - -#define TIMER2_SELECT 0x80 -#define TIMER_ENABLE_LSB 0x20 -#define TIMER_ENABLE_MSB 0x10 -#define TIMER2_LATCH 0x20 -#define TIMER2_SPEAKER 0x02 -#define TIMER2_GATE 0x01 - -void -grub_pit_wait (grub_uint16_t tics) -{ - /* Disable timer2 gate and speaker. */ - grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE), - TIMER2_REG_LATCH); - - /* Set tics. */ - grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND); - grub_outb (tics & 0xff, TIMER2_REG_CONTROL); - grub_outb (tics >> 8, TIMER2_REG_CONTROL); - - /* Enable timer2 gate, keep speaker disabled. */ - grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE, - TIMER2_REG_LATCH); - - /* Wait. */ - while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00); - - /* Disable timer2 gate and speaker. */ - grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE), - TIMER2_REG_LATCH); -} diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c new file mode 100644 index 000000000..e05ccee96 --- /dev/null +++ b/grub-core/kern/i386/qemu/init.c @@ -0,0 +1,285 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern grub_uint8_t _start[]; +extern grub_uint8_t _end[]; +extern grub_uint8_t _edata[]; + +void __attribute__ ((noreturn)) +grub_exit (void) +{ + /* We can't use grub_fatal() in this function. This would create an infinite + loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */ + while (1) + grub_cpu_idle (); +} + +grub_addr_t grub_modbase; + +/* Helper for grub_machine_init. */ +static int +heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + grub_uint64_t begin = addr, end = addr + size; + +#if GRUB_CPU_SIZEOF_VOID_P == 4 + /* Restrict ourselves to 32-bit memory space. */ + if (begin > GRUB_ULONG_MAX) + return 0; + if (end > GRUB_ULONG_MAX) + end = GRUB_ULONG_MAX; +#endif + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* Avoid the lower memory. */ + if (begin < GRUB_MEMORY_MACHINE_LOWER_SIZE) + begin = GRUB_MEMORY_MACHINE_LOWER_SIZE; + + if (end <= begin) + return 0; + + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin)); + + return 0; +} + +struct resource +{ + grub_pci_device_t dev; + int type; + grub_size_t size; + int bar; +}; + +struct iterator_ctx +{ + struct resource *resources; + grub_size_t nresources; +}; + +static int +count_cards (grub_pci_device_t dev __attribute__ ((unused)), + grub_pci_id_t pciid __attribute__ ((unused)), + void *data) +{ + int *cnt = data; + + (*cnt)++; + + return 0; +} + +static int +find_resources (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused)), + void *data) +{ + struct iterator_ctx *ctx = data; + int bar; + + for (bar = 0; bar < 6; bar++) + { + grub_pci_address_t addr; + grub_uint32_t ones, zeros, mask; + struct resource *res; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0 + + 4 * bar); + grub_pci_write (addr, 0xffffffff); + grub_pci_read (addr); + ones = grub_pci_read (addr); + grub_pci_write (addr, 0); + grub_pci_read (addr); + zeros = grub_pci_read (addr); + if (ones == zeros) + continue; + res = &ctx->resources[ctx->nresources++]; + if ((zeros & GRUB_PCI_ADDR_SPACE_MASK) == GRUB_PCI_ADDR_SPACE_IO) + mask = GRUB_PCI_ADDR_SPACE_MASK; + else + mask = (GRUB_PCI_ADDR_MEM_TYPE_MASK | GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_PREFETCH); + + res->type = ones & mask; + res->dev = dev; + res->bar = bar; + res->size = (~((zeros ^ ones)) | mask) + 1; + if ((zeros & (GRUB_PCI_ADDR_MEM_TYPE_MASK | GRUB_PCI_ADDR_SPACE_MASK)) + == (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_64)) + bar++; + } + return 0; +} + +static int +enable_cards (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_uint16_t cmd = 0; + grub_pci_address_t addr; + grub_uint32_t class; + int bar; + + for (bar = 0; bar < 6; bar++) + { + grub_uint32_t val; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0 + + 4 * bar); + val = grub_pci_read (addr); + if (!val) + continue; + if ((val & GRUB_PCI_ADDR_SPACE_MASK) == GRUB_PCI_ADDR_SPACE_IO) + cmd |= GRUB_PCI_COMMAND_IO_ENABLED; + else + cmd |= GRUB_PCI_COMMAND_MEM_ENABLED; + } + + class = (grub_pci_read (addr) >> 16) & 0xffff; + + if (class == GRUB_PCI_CLASS_SUBCLASS_VGA) + cmd |= GRUB_PCI_COMMAND_IO_ENABLED + | GRUB_PCI_COMMAND_MEM_ENABLED; + + if (class == GRUB_PCI_CLASS_SUBCLASS_USB) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, cmd); + + return 0; +} + +static void +grub_pci_assign_addresses (void) +{ + int ncards = 0; + struct iterator_ctx ctx; + + grub_pci_iterate (count_cards, &ncards); + + { + struct resource resources[ncards * 6]; + int done; + unsigned i; + ctx.nresources = 0; + ctx.resources = resources; + grub_uint32_t memptr = 0xf0000000; + grub_uint16_t ioptr = 0x1000; + + grub_pci_iterate (find_resources, &ctx); + /* FIXME: do we need a better sort here? */ + do + { + done = 0; + for (i = 0; i + 1 < ctx.nresources; i++) + if (resources[i].size < resources[i+1].size) + { + struct resource t; + t = resources[i]; + resources[i] = resources[i+1]; + resources[i+1] = t; + done = 1; + } + } + while (done); + + for (i = 0; i < ctx.nresources; i++) + { + grub_pci_address_t addr; + addr = grub_pci_make_address (resources[i].dev, + GRUB_PCI_REG_ADDRESS_REG0 + + 4 * resources[i].bar); + if ((resources[i].type & GRUB_PCI_ADDR_SPACE_MASK) + == GRUB_PCI_ADDR_SPACE_IO) + { + grub_pci_write (addr, ioptr | resources[i].type); + ioptr += resources[i].size; + } + else + { + grub_pci_write (addr, memptr | resources[i].type); + memptr += resources[i].size; + if ((resources[i].type & (GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_SPACE_MASK)) + == (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_64)) + { + addr = grub_pci_make_address (resources[i].dev, + GRUB_PCI_REG_ADDRESS_REG0 + + 4 * resources[i].bar + 4); + grub_pci_write (addr, 0); + } + } + } + grub_pci_iterate (enable_cards, NULL); + } +} + +void +grub_machine_init (void) +{ + grub_modbase = grub_core_entry_addr + (_edata - _start); + + grub_pci_assign_addresses (); + + grub_qemu_init_cirrus (); + + grub_vga_text_init (); + + grub_machine_mmap_init (); + grub_machine_mmap_iterate (heap_init, NULL); + + + grub_tsc_init (); +} + +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + +void +grub_machine_fini (int flags) +{ + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_vga_text_fini (); + grub_stop_floppy (); +} diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index ffb61a47a..f449637ef 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -69,38 +69,38 @@ grub_machine_mmap_init (void) } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { if (hook (0x0, (grub_addr_t) _start, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; if (hook ((grub_addr_t) _end, 0xa0000 - (grub_addr_t) _end, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; if (hook (GRUB_MEMORY_MACHINE_UPPER, 0x100000 - GRUB_MEMORY_MACHINE_UPPER, - GRUB_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED, hook_data)) return 1; /* Everything else is free. */ if (hook (0x100000, min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; /* Protect boot.img, which contains the gdt. It is mapped at the top of memory (it is also mapped below 0x100000, but we already reserved that area). */ if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE, GRUB_BOOT_MACHINE_SIZE, - GRUB_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED, hook_data)) return 1; if (above_4g != 0 && hook (0x100000000ULL, above_4g, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; return 0; diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c index c4645f043..3a4cae601 100644 --- a/grub-core/kern/i386/tsc.c +++ b/grub-core/kern/i386/tsc.c @@ -24,46 +24,124 @@ #include #include #include +#include +#ifdef GRUB_MACHINE_XEN +#include +#else #include +#endif +#include /* This defines the value TSC had at the epoch (that is, when we calibrated it). */ static grub_uint64_t tsc_boot_time; -/* Calibrated TSC rate. (In TSC ticks per millisecond.) */ -static grub_uint64_t tsc_ticks_per_ms; +/* Calibrated TSC rate. (In ms per 2^32 ticks) */ +/* We assume that the tick is less than 1 ms and hence this value fits + in 32-bit. */ +grub_uint32_t grub_tsc_rate; - -grub_uint64_t -grub_tsc_get_time_ms (void) +/* Read the TSC value, which increments with each CPU clock cycle. */ +static __inline grub_uint64_t +grub_get_tsc (void) { - return tsc_boot_time + grub_divmod64 (grub_get_tsc (), tsc_ticks_per_ms, 0); + grub_uint32_t lo, hi; + grub_uint32_t a,b,c,d; + + /* The CPUID instruction is a 'serializing' instruction, and + avoids out-of-order execution of the RDTSC instruction. */ + grub_cpuid (0,a,b,c,d); + /* Read TSC value. We cannot use "=A", since this would use + %rax on x86_64. */ + __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi)); + + return (((grub_uint64_t) hi) << 32) | lo; } +static __inline int +grub_cpu_is_tsc_supported (void) +{ + grub_uint32_t a,b,c,d; + if (! grub_cpu_is_cpuid_supported ()) + return 0; -/* How many RTC ticks to use for calibration loop. (>= 1) */ -#define CALIBRATION_TICKS 2 + grub_cpuid(1,a,b,c,d); + return (d & (1 << 4)) != 0; +} + +#ifndef GRUB_MACHINE_XEN + +static void +grub_pit_wait (grub_uint16_t tics) +{ + /* Disable timer2 gate and speaker. */ + grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) + & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), + GRUB_PIT_SPEAKER_PORT); + + /* Set tics. */ + grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD, + GRUB_PIT_CTRL); + grub_outb (tics & 0xff, GRUB_PIT_COUNTER_2); + grub_outb (tics >> 8, GRUB_PIT_COUNTER_2); + + /* Enable timer2 gate, keep speaker disabled. */ + grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA) + | GRUB_PIT_SPK_TMR2, + GRUB_PIT_SPEAKER_PORT); + + /* Wait. */ + while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00); + + /* Disable timer2 gate and speaker. */ + grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) + & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), + GRUB_PIT_SPEAKER_PORT); +} +#endif + +static grub_uint64_t +grub_tsc_get_time_ms (void) +{ + grub_uint64_t a = grub_get_tsc () - tsc_boot_time; + grub_uint64_t ah = a >> 32; + grub_uint64_t al = a & 0xffffffff; + + return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate; +} + +#ifndef GRUB_MACHINE_XEN /* Calibrate the TSC based on the RTC. */ static void calibrate_tsc (void) { /* First calibrate the TSC rate (relative, not absolute time). */ - grub_uint64_t start_tsc; grub_uint64_t end_tsc; - start_tsc = grub_get_tsc (); + tsc_boot_time = grub_get_tsc (); grub_pit_wait (0xffff); end_tsc = grub_get_tsc (); - tsc_ticks_per_ms = grub_divmod64 (end_tsc - start_tsc, 55, 0); + grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0); } +#endif void grub_tsc_init (void) { +#ifdef GRUB_MACHINE_XEN + grub_uint64_t t; + tsc_boot_time = grub_get_tsc (); + t = grub_xen_shared_info->vcpu_info[0].time.tsc_to_system_mul; + if (grub_xen_shared_info->vcpu_info[0].time.tsc_shift > 0) + t <<= grub_xen_shared_info->vcpu_info[0].time.tsc_shift; + else + t >>= -grub_xen_shared_info->vcpu_info[0].time.tsc_shift; + grub_tsc_rate = grub_divmod64 (t, 1000000, 0); + grub_install_get_time_ms (grub_tsc_get_time_ms); +#else if (grub_cpu_is_tsc_supported ()) { - tsc_boot_time = grub_get_tsc (); calibrate_tsc (); grub_install_get_time_ms (grub_tsc_get_time_ms); } @@ -75,4 +153,5 @@ grub_tsc_init (void) grub_fatal ("no TSC found"); #endif } +#endif } diff --git a/grub-core/kern/i386/xen/hypercall.S b/grub-core/kern/i386/xen/hypercall.S new file mode 100644 index 000000000..aa47cac2c --- /dev/null +++ b/grub-core/kern/i386/xen/hypercall.S @@ -0,0 +1,43 @@ +/* hypercall.S - wrappers for Xen hypercalls */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +FUNCTION(grub_xen_hypercall) + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %edi + pushl %ebx + + /* call number already in %eax. */ + /* %edx -> %ebx*/ + /* %ecx -> %ecx*/ + movl %edx, %ebx + movl 8(%ebp), %edx + movl 12(%ebp), %esi + movl 16(%ebp), %edi + movl 20(%ebp), %ebp + int $0x82 + popl %ebx + popl %edi + popl %esi + popl %ebp + retl $16 diff --git a/grub-core/kern/i386/xen/startup.S b/grub-core/kern/i386/xen/startup.S new file mode 100644 index 000000000..fbe8300a7 --- /dev/null +++ b/grub-core/kern/i386/xen/startup.S @@ -0,0 +1,38 @@ +/* startup.S - bootstrap GRUB itself */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + + .file "startup.S" + .text + .globl start, _start + .code32 + +start: +_start: + leal LOCAL(stack_end), %esp + movl %esi, EXT_C(grub_xen_start_page_addr) + + call EXT_C(grub_main) + /* Doesn't return. */ + + .bss + .space (1 << 22) +LOCAL(stack_end): diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 7c22b0b06..957ceaae6 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -23,6 +23,9 @@ #include #include #include +#include + +#define MASK19 ((1 << 19) - 1) /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -41,126 +44,6 @@ grub_arch_dl_check_header (void *ehdr) #pragma GCC diagnostic ignored "-Wcast-align" -#define MASK20 ((1 << 20) - 1) -#define MASK19 ((1 << 19) - 1) - -struct unaligned_uint32 -{ - grub_uint32_t val; -} __attribute__ ((packed)); - -static void -add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) -{ - struct unaligned_uint32 *p; - switch (addr & 3) - { - case 0: - p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); - p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2) - | (p->val & ~(MASK20 << 2))); - break; - case 1: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); - p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3) - | (p->val & ~(MASK20 << 3))); - break; - case 2: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); - p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4) - | (p->val & ~(MASK20 << 4))); - break; - } -} - -#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) ) - -static grub_uint32_t -add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) -{ - grub_uint32_t high, mid, low, c; - low = (a & 0x00007f); - mid = (a & 0x7fc000) >> 7; - high = (a & 0x003e00) << 7; - c = (low | mid | high) + value; - return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00 -} - -static void -add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) -{ - struct unaligned_uint32 *p; - switch (addr & 3) - { - case 0: - p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); - p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2)); - break; - case 1: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); - p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3)); - break; - case 2: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); - p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4)); - break; - } -} - -static const grub_uint8_t nopm[5] = - { - /* [MLX] nop.m 0x0 */ - 0x05, 0x00, 0x00, 0x00, 0x01 - }; - -static const grub_uint8_t jump[0x20] = - { - /* ld8 r16=[r15],8 */ - 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14, - /* mov r14=r1;; */ - 0xe0, 0x00, 0x04, 0x00, 0x42, 0x00, - /* nop.i 0x0 */ - 0x00, 0x00, 0x04, 0x00, - /* ld8 r1=[r15] */ - 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, - /* mov b6=r16 */ - 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, - /* br.few b6;; */ - 0x60, 0x00, 0x80, 0x00 - }; - -struct ia64_trampoline -{ - /* nop.m */ - grub_uint8_t nop[5]; - /* movl r15 = addr*/ - grub_uint8_t addr_hi[6]; - grub_uint8_t e0; - grub_uint8_t addr_lo[4]; - grub_uint8_t jump[0x20]; -}; - -static void -make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) -{ - COMPILE_TIME_ASSERT (sizeof (struct ia64_trampoline) - == GRUB_IA64_DL_TRAMP_SIZE); - grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); - tr->addr_hi[0] = ((addr & 0xc00000) >> 16); - tr->addr_hi[1] = (addr >> 24) & 0xff; - tr->addr_hi[2] = (addr >> 32) & 0xff; - tr->addr_hi[3] = (addr >> 40) & 0xff; - tr->addr_hi[4] = (addr >> 48) & 0xff; - tr->addr_hi[5] = (addr >> 56) & 0xff; - tr->e0 = 0xe0; - tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; - tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) - | ((addr & 0x200000) >> 17)); - tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); - tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; - grub_memcpy (tr->jump, jump, sizeof (tr->jump)); -} - /* Relocate symbols. */ grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) @@ -170,7 +53,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) Elf_Word entsize; unsigned i; grub_uint64_t *gp, *gpptr; - struct ia64_trampoline *tr; + struct grub_ia64_trampoline *tr; gp = (grub_uint64_t *) mod->base; gpptr = (grub_uint64_t *) mod->got; @@ -230,13 +113,13 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) case R_IA64_PCREL21B: { grub_uint64_t noff; - make_trampoline (tr, value); + grub_ia64_make_trampoline (tr, value); noff = ((char *) tr - (char *) (addr & ~3)) >> 4; - tr++; + tr = (struct grub_ia64_trampoline *) ((char *) tr + GRUB_IA64_DL_TRAMP_SIZE); if (noff & ~MASK19) return grub_error (GRUB_ERR_BAD_OS, "trampoline offset too big (%lx)", noff); - add_value_to_slot_20b (addr, noff); + grub_ia64_add_value_to_slot_20b (addr, noff); } break; case R_IA64_SEGREL64LSB: @@ -250,7 +133,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) *(grub_uint64_t *) addr += value - addr; break; case R_IA64_GPREL22: - add_value_to_slot_21 (addr, value - (grub_addr_t) gp); + grub_ia64_add_value_to_slot_21 (addr, value - (grub_addr_t) gp); break; case R_IA64_LTOFF22X: @@ -259,7 +142,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) value = *(grub_uint64_t *) sym->st_value + rel->r_addend; case R_IA64_LTOFF_FPTR22: *gpptr = value; - add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp); + grub_ia64_add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp); gpptr++; break; diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index 9394e32e2..e2209ca0a 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -22,9 +22,154 @@ #include #include #include +#include +#include #pragma GCC diagnostic ignored "-Wcast-align" +#define MASK20 ((1 << 20) - 1) +#define MASK3 (~(grub_addr_t) 3) + +void +grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) +{ + grub_uint32_t val; + switch (addr & 3) + { + case 0: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 2))); + val = (((((val & MASK20) + value) & MASK20) << 2) + | (val & ~(MASK20 << 2))); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 2), + grub_cpu_to_le32 (val)); + break; + case 1: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 7))); + val = ((((((val >> 3) & MASK20) + value) & MASK20) << 3) + | (val & ~(MASK20 << 3))); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 7), + grub_cpu_to_le32 (val)); + break; + case 2: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 12))); + val = ((((((val >> 4) & MASK20) + value) & MASK20) << 4) + | (val & ~(MASK20 << 4))); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 12), + grub_cpu_to_le32 (val)); + break; + } +} + +#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) ) + +static grub_uint32_t +add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) +{ + grub_uint32_t high, mid, low, c; + low = (a & 0x00007f); + mid = (a & 0x7fc000) >> 7; + high = (a & 0x003e00) << 7; + c = (low | mid | high) + value; + return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00 +} + +void +grub_ia64_add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) +{ + grub_uint32_t val; + switch (addr & 3) + { + case 0: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 2))); + val = ((add_value_to_slot_21_real (((val >> 2) & MASKF21), value) + & MASKF21) << 2) | (val & ~(MASKF21 << 2)); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 2), + grub_cpu_to_le32 (val)); + break; + case 1: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 7))); + val = ((add_value_to_slot_21_real (((val >> 3) & MASKF21), value) + & MASKF21) << 3) | (val & ~(MASKF21 << 3)); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 7), + grub_cpu_to_le32 (val)); + break; + case 2: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 12))); + val = ((add_value_to_slot_21_real (((val >> 4) & MASKF21), value) + & MASKF21) << 4) | (val & ~(MASKF21 << 4)); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 12), + grub_cpu_to_le32 (val)); + break; + } +} + +static const grub_uint8_t nopm[5] = + { + /* [MLX] nop.m 0x0 */ + 0x05, 0x00, 0x00, 0x00, 0x01 + }; + +#ifdef GRUB_UTIL +static grub_uint8_t jump[0x20] = + { + /* [MMI] add r15=r15,r1;; */ + 0x0b, 0x78, 0x3c, 0x02, 0x00, 0x20, + /* ld8 r16=[r15],8 */ + 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, + /* mov r14=r1;; */ + 0x01, 0x08, 0x00, 0x84, + /* [MIB] ld8 r1=[r15] */ + 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, + /* mov b6=r16 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, + /* br.few b6;; */ + 0x60, 0x00, 0x80, 0x00 + }; +#else +static const grub_uint8_t jump[0x20] = + { + /* ld8 r16=[r15],8 */ + 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14, + /* mov r14=r1;; */ + 0xe0, 0x00, 0x04, 0x00, 0x42, 0x00, + /* nop.i 0x0 */ + 0x00, 0x00, 0x04, 0x00, + /* ld8 r1=[r15] */ + 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, + /* mov b6=r16 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, + /* br.few b6;; */ + 0x60, 0x00, 0x80, 0x00 + }; +#endif + +void +grub_ia64_make_trampoline (struct grub_ia64_trampoline *tr, grub_uint64_t addr) +{ + COMPILE_TIME_ASSERT (sizeof (struct grub_ia64_trampoline) + == GRUB_IA64_DL_TRAMP_SIZE); + grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); + tr->addr_hi[0] = ((addr & 0xc00000) >> 16); + tr->addr_hi[1] = (addr >> 24) & 0xff; + tr->addr_hi[2] = (addr >> 32) & 0xff; + tr->addr_hi[3] = (addr >> 40) & 0xff; + tr->addr_hi[4] = (addr >> 48) & 0xff; + tr->addr_hi[5] = (addr >> 56) & 0xff; + tr->e0 = 0xe0; + tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; + tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) + | ((addr & 0x200000) >> 17)); + tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); + tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; + grub_memcpy (tr->jump, jump, sizeof (tr->jump)); +} + void grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) @@ -35,26 +180,26 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, unsigned i; /* Find a symbol table. */ - for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu64 (e->e_shoff)); i < grub_le_to_cpu16 (e->e_shnum); i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) - if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) + if (s->sh_type == grub_cpu_to_le32_compile_time (SHT_SYMTAB)) break; if (i == grub_le_to_cpu16 (e->e_shnum)) return; - for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu64 (e->e_shoff)); i < grub_le_to_cpu16 (e->e_shnum); i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) - if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) + if (s->sh_type == grub_cpu_to_le32_compile_time (SHT_RELA)) { Elf64_Rela *rel, *max; - for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), - max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); + for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu64 (s->sh_offset)), + max = rel + grub_le_to_cpu64 (s->sh_size) / grub_le_to_cpu64 (s->sh_entsize); rel < max; rel++) - switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) + switch (ELF64_R_TYPE (grub_le_to_cpu64 (rel->r_info))) { case R_IA64_PCREL21B: cntt++; diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index 7fa6fbf71..5587d9cd8 100644 --- a/grub-core/kern/ia64/efi/init.c +++ b/grub-core/kern/ia64/efi/init.c @@ -26,6 +26,7 @@ #include #include #include +#include static grub_uint64_t divisor = 1; @@ -68,9 +69,10 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_efi_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_efi_fini (); } void diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index dd04d3976..d92ae14f5 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -22,7 +22,7 @@ #include #include -int (*grub_ieee1275_entry_fn) (void *); +int (*grub_ieee1275_entry_fn) (void *) GRUB_IEEE1275_ENTRY_FN_ATTRIBUTE; grub_ieee1275_phandle_t grub_ieee1275_chosen; grub_ieee1275_ihandle_t grub_ieee1275_mmu; @@ -43,9 +43,6 @@ grub_ieee1275_set_flag (enum grub_ieee1275_flag flag) grub_ieee1275_flags |= (1 << flag); } -#define SF "SmartFirmware(tm)" -#define OHW "PPC Open Hack'Ware" - static void grub_ieee1275_find_options (void) { @@ -76,7 +73,8 @@ grub_ieee1275_find_options (void) rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright", tmp, sizeof (tmp), 0); - if (rc >= 0 && !grub_strncmp (tmp, SF, sizeof (SF) - 1)) + if (rc >= 0 && !grub_strncmp (tmp, "SmartFirmware(tm)", + sizeof ("SmartFirmware(tm)") - 1)) is_smartfirmware = 1; rc = grub_ieee1275_get_property (root, "architecture", @@ -117,6 +115,7 @@ grub_ieee1275_find_options (void) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS); grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX); grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN); break; } } @@ -187,10 +186,12 @@ grub_ieee1275_find_options (void) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); } - if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom)) + if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom) + || ! grub_ieee1275_finddevice ("/boot-rom", &bootrom)) { rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0); - if (rc >= 0 && !grub_strncmp (tmp, OHW, sizeof (OHW) - 1)) + if (rc >= 0 && !grub_strncmp (tmp, "PPC Open Hack'Ware", + sizeof ("PPC Open Hack'Ware") - 1)) { grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT); grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS); @@ -201,9 +202,6 @@ grub_ieee1275_find_options (void) } } -#undef SF -#undef OHW - void grub_ieee1275_init (void) { diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 4f56e82f2..ecce45005 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -34,6 +34,10 @@ #include #include #include +#include +#ifdef __i386__ +#include +#endif #ifdef __sparc__ #include #endif @@ -92,18 +96,30 @@ grub_machine_get_bootlocation (char **device __attribute__ ((unused)), void grub_machine_get_bootlocation (char **device, char **path) { - char bootpath[64]; /* XXX check length */ + char *bootpath; + grub_ssize_t bootpath_size; char *filename; char *type; - - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, - sizeof (bootpath), 0)) + + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath", + &bootpath_size) + || bootpath_size <= 0) { /* Should never happen. */ grub_printf ("/chosen/bootpath property missing!\n"); return; } + bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64); + if (! bootpath) + { + grub_print_error (); + return; + } + grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath, + (grub_size_t) bootpath_size + 1, 0); + bootpath[bootpath_size] = '\0'; + /* Transform an OF device path to a GRUB path. */ type = grub_ieee1275_get_device_type (bootpath); @@ -142,6 +158,7 @@ grub_machine_get_bootlocation (char **device, char **path) *path = filename; } } + grub_free (bootpath); } #endif @@ -154,74 +171,77 @@ grub_claim_heap (void) + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); } #else +/* Helper for grub_claim_heap. */ +static int +heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + void *data) +{ + unsigned long *total = data; + + if (type != 1) + return 0; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) + return 0; + + if (addr < 0x180000) + { + len = addr + len - 0x180000; + addr = 0x180000; + } + } + len -= 1; /* Required for some firmware. */ + + /* Never exceed HEAP_MAX_SIZE */ + if (*total + len > HEAP_MAX_SIZE) + len = HEAP_MAX_SIZE - *total; + + /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */ + if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */ + (addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */ + (*total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */ + len = HEAP_MAX_ADDR - addr; + + /* In theory, firmware should already prevent this from happening by not + listing our own image in /memory/available. The check below is intended + as a safeguard in case that doesn't happen. However, it doesn't protect + us from corrupting our module area, which extends up to a + yet-undetermined region above _end. */ + if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start)) + { + grub_printf ("Warning: attempt to claim over our own code!\n"); + len = 0; + } + + if (len) + { + grub_err_t err; + /* Claim and use it. */ + err = grub_claimmap (addr, len); + if (err) + return err; + grub_mm_init_region ((void *) (grub_addr_t) addr, len); + } + + *total += len; + if (*total >= HEAP_MAX_SIZE) + return 1; + + return 0; +} + 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_memory_type_t type); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, - grub_memory_type_t type) - { - if (type != 1) - return 0; - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) - { - if (addr + len <= 0x180000) - return 0; - - if (addr < 0x180000) - { - len = addr + len - 0x180000; - addr = 0x180000; - } - } - len -= 1; /* Required for some firmware. */ - - /* Never exceed HEAP_MAX_SIZE */ - if (total + len > HEAP_MAX_SIZE) - len = HEAP_MAX_SIZE - total; - - /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */ - if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */ - (addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */ - (total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */ - len = HEAP_MAX_ADDR - addr; - - /* In theory, firmware should already prevent this from happening by not - listing our own image in /memory/available. The check below is intended - as a safeguard in case that doesn't happen. However, it doesn't protect - us from corrupting our module area, which extends up to a - yet-undetermined region above _end. */ - if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start)) - { - grub_printf ("Warning: attempt to claim over our own code!\n"); - len = 0; - } - - if (len) - { - grub_err_t err; - /* Claim and use it. */ - err = grub_claimmap (addr, len); - if (err) - return err; - grub_mm_init_region ((void *) (grub_addr_t) addr, len); - } - - total += len; - if (total >= HEAP_MAX_SIZE) - return 1; - - return 0; - } - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) - heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1); + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) + heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN, + 1, &total); else - grub_machine_mmap_iterate (heap_init); + grub_machine_mmap_iterate (heap_init, &total); } #endif @@ -265,8 +285,6 @@ grub_parse_cmdline (void) } } -static grub_uint64_t ieee1275_get_time_ms (void); - grub_addr_t grub_modbase; void @@ -284,18 +302,25 @@ grub_machine_init (void) grub_parse_cmdline (); - grub_install_get_time_ms (ieee1275_get_time_ms); +#ifdef __i386__ + grub_tsc_init (); +#else + grub_install_get_time_ms (grub_rtc_get_time_ms); +#endif } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_ofdisk_fini (); - grub_console_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + { + grub_ofdisk_fini (); + grub_console_fini (); + } } -static grub_uint64_t -ieee1275_get_time_ms (void) +grub_uint64_t +grub_rtc_get_time_ms (void) { grub_uint32_t msecs = 0; diff --git a/grub-core/kern/ieee1275/mmap.c b/grub-core/kern/ieee1275/mmap.c index 2e4e085bb..911bb0011 100644 --- a/grub-core/kern/ieee1275/mmap.c +++ b/grub-core/kern/ieee1275/mmap.c @@ -21,7 +21,7 @@ #include grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t memory; @@ -72,7 +72,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) if (size_cells == 2) size = (size << 32) | available[i++]; - if (hook (address, size, GRUB_MEMORY_AVAILABLE)) + if (hook (address, size, GRUB_MEMORY_AVAILABLE, hook_data)) break; } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 40abaa373..07c90f7cb 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -32,184 +32,231 @@ enum grub_ieee1275_parse_type GRUB_PARSE_DEVICE_TYPE }; -/* Walk children of 'devpath', calling hook for each. */ -int -grub_children_iterate (const char *devpath, - int (*hook) (struct grub_ieee1275_devalias *alias)) +static int +fill_alias (struct grub_ieee1275_devalias *alias) +{ + grub_ssize_t actual; + + if (grub_ieee1275_get_property (alias->phandle, "device_type", alias->type, + IEEE1275_MAX_PROP_LEN, &actual)) + alias->type[0] = 0; + + if (alias->parent_dev == alias->phandle) + return 0; + + if (grub_ieee1275_package_to_path (alias->phandle, alias->path, + IEEE1275_MAX_PATH_LEN, &actual)) + return 0; + + if (grub_strcmp (alias->parent_path, alias->path) == 0) + return 0; + + if (grub_ieee1275_get_property (alias->phandle, "name", alias->name, + IEEE1275_MAX_PROP_LEN, &actual)) + return 0; + grub_dprintf ("devalias", "device path=%s\n", alias->path); + return 1; +} + +void +grub_ieee1275_devalias_free (struct grub_ieee1275_devalias *alias) +{ + grub_free (alias->name); + grub_free (alias->type); + grub_free (alias->path); + grub_free (alias->parent_path); + alias->name = 0; + alias->type = 0; + alias->path = 0; + alias->parent_path = 0; + alias->phandle = GRUB_IEEE1275_PHANDLE_INVALID; +} + +void +grub_ieee1275_children_peer (struct grub_ieee1275_devalias *alias) +{ + while (grub_ieee1275_peer (alias->phandle, &alias->phandle) != -1) + if (fill_alias (alias)) + return; + grub_ieee1275_devalias_free (alias); +} + +void +grub_ieee1275_children_first (const char *devpath, + struct grub_ieee1275_devalias *alias) { grub_ieee1275_phandle_t dev; - grub_ieee1275_phandle_t child; - char *childtype, *childpath; - char *childname; - int ret = 0; + + grub_dprintf ("devalias", "iterating children of %s\n", + devpath); + + alias->name = 0; + alias->path = 0; + alias->parent_path = 0; + alias->type = 0; if (grub_ieee1275_finddevice (devpath, &dev)) - return 0; + return; - if (grub_ieee1275_child (dev, &child)) - return 0; + if (grub_ieee1275_child (dev, &alias->phandle)) + return; - childtype = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!childtype) - return 0; - childpath = grub_malloc (IEEE1275_MAX_PATH_LEN); - if (!childpath) + alias->type = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->type) + return; + alias->path = grub_malloc (IEEE1275_MAX_PATH_LEN); + if (!alias->path) { - grub_free (childtype); - return 0; + grub_free (alias->type); + return; } - childname = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!childname) + alias->parent_path = grub_strdup (devpath); + if (!alias->parent_path) { - grub_free (childpath); - grub_free (childtype); - return 0; + grub_free (alias->path); + grub_free (alias->type); + return; } - do + alias->name = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->name) { - struct grub_ieee1275_devalias alias; - grub_ssize_t actual; + grub_free (alias->path); + grub_free (alias->type); + grub_free (alias->parent_path); + return; + } + if (!fill_alias (alias)) + grub_ieee1275_children_peer (alias); +} - if (grub_ieee1275_get_property (child, "device_type", childtype, - IEEE1275_MAX_PROP_LEN, &actual)) - childtype[0] = 0; +static int +iterate_recursively (const char *path, + int (*hook) (struct grub_ieee1275_devalias *alias)) +{ + struct grub_ieee1275_devalias alias; + int ret = 0; - if (dev == child) - continue; - - if (grub_ieee1275_package_to_path (child, childpath, - IEEE1275_MAX_PATH_LEN, &actual)) - continue; - - if (grub_strcmp (devpath, childpath) == 0) - continue; - - if (grub_ieee1275_get_property (child, "name", childname, - IEEE1275_MAX_PROP_LEN, &actual)) - continue; - - alias.type = childtype; - alias.path = childpath; - alias.name = childname; + FOR_IEEE1275_DEVCHILDREN(path, alias) + { ret = hook (&alias); if (ret) break; + ret = iterate_recursively (alias.path, hook); + if (ret) + break; } - while (grub_ieee1275_peer (child, &child) != -1); - - grub_free (childname); - grub_free (childpath); - grub_free (childtype); - + grub_ieee1275_devalias_free (&alias); return ret; } int grub_ieee1275_devices_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) { - auto int it_through (struct grub_ieee1275_devalias *alias); - int it_through (struct grub_ieee1275_devalias *alias) - { - if (hook (alias)) - return 1; - return grub_children_iterate (alias->path, it_through); - } - - return grub_children_iterate ("/", it_through); + return iterate_recursively ("/", hook); } -/* Iterate through all device aliases. This function can be used to - find a device of a specific type. */ -int -grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) +void +grub_ieee1275_devalias_init_iterator (struct grub_ieee1275_devalias *alias) { - grub_ieee1275_phandle_t aliases; - char *aliasname, *devtype; - grub_ssize_t actual; - struct grub_ieee1275_devalias alias; - int ret = 0; + alias->name = 0; + alias->path = 0; + alias->parent_path = 0; + alias->type = 0; - if (grub_ieee1275_finddevice ("/aliases", &aliases)) - return 0; + grub_dprintf ("devalias", "iterating aliases\n"); - aliasname = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!aliasname) - return 0; - devtype = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!devtype) + if (grub_ieee1275_finddevice ("/aliases", &alias->parent_dev)) + return; + + alias->name = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->name) + return; + + alias->type = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->type) { - grub_free (aliasname); - return 0; + grub_free (alias->name); + alias->name = 0; + return; } - /* Find the first property. */ - aliasname[0] = '\0'; + alias->name[0] = '\0'; +} - while (grub_ieee1275_next_property (aliases, aliasname, aliasname) > 0) +int +grub_ieee1275_devalias_next (struct grub_ieee1275_devalias *alias) +{ + if (!alias->name) + return 0; + while (1) { - grub_ieee1275_phandle_t dev; grub_ssize_t pathlen; - char *devpath; + grub_ssize_t actual; + char *tmp; - grub_dprintf ("devalias", "devalias name = %s\n", aliasname); + if (alias->path) + { + grub_free (alias->path); + alias->path = 0; + } + tmp = grub_strdup (alias->name); + if (grub_ieee1275_next_property (alias->parent_dev, tmp, + alias->name) <= 0) + { + grub_free (tmp); + grub_ieee1275_devalias_free (alias); + return 0; + } + grub_free (tmp); - grub_ieee1275_get_property_length (aliases, aliasname, &pathlen); + grub_dprintf ("devalias", "devalias name = %s\n", alias->name); + + grub_ieee1275_get_property_length (alias->parent_dev, alias->name, &pathlen); /* The property `name' is a special case we should skip. */ - if (!grub_strcmp (aliasname, "name")) + if (grub_strcmp (alias->name, "name") == 0) continue; /* Sun's OpenBoot often doesn't zero terminate the device alias strings, so we will add a NULL byte at the end explicitly. */ pathlen += 1; - devpath = grub_malloc (pathlen + 1); - if (! devpath) + alias->path = grub_malloc (pathlen + 1); + if (! alias->path) { - grub_free (devtype); - grub_free (aliasname); + grub_ieee1275_devalias_free (alias); return 0; } - if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen, - &actual) || actual < 0) + if (grub_ieee1275_get_property (alias->parent_dev, alias->name, alias->path, + pathlen, &actual) || actual < 0) { - grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname); - goto nextprop; + grub_dprintf ("devalias", "get_property (%s) failed\n", alias->name); + grub_free (alias->path); + continue; } if (actual > pathlen) actual = pathlen; - devpath[actual] = '\0'; - devpath[pathlen] = '\0'; + alias->path[actual] = '\0'; + alias->path[pathlen] = '\0'; - if (grub_ieee1275_finddevice (devpath, &dev)) + if (grub_ieee1275_finddevice (alias->path, &alias->phandle)) { - grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath); - goto nextprop; + grub_dprintf ("devalias", "finddevice (%s) failed\n", alias->path); + grub_free (alias->path); + alias->path = 0; + continue; } - if (grub_ieee1275_get_property (dev, "device_type", devtype, + if (grub_ieee1275_get_property (alias->phandle, "device_type", alias->type, IEEE1275_MAX_PROP_LEN, &actual)) { /* NAND device don't have device_type property. */ - devtype[0] = 0; + alias->type[0] = 0; } - - alias.name = aliasname; - alias.path = devpath; - alias.type = devtype; - ret = hook (&alias); - -nextprop: - grub_free (devpath); - if (ret) - break; + return 1; } - - grub_free (devtype); - grub_free (aliasname); - return ret; } /* Call the "map" method of /chosen/mmu. */ @@ -286,37 +333,28 @@ grub_ieee1275_get_devargs (const char *path) } /* Get the device path of the Open Firmware node name `path'. */ -static char * +char * grub_ieee1275_get_devname (const char *path) { char *colon = grub_strchr (path, ':'); - char *newpath = 0; int pathlen = grub_strlen (path); - auto int match_alias (struct grub_ieee1275_devalias *alias); - - int match_alias (struct grub_ieee1275_devalias *curalias) - { - /* briQ firmware can change capitalization in /chosen/bootpath. */ - if (grub_strncasecmp (curalias->path, path, pathlen) == 0 - && curalias->path[pathlen] == 0) - { - newpath = grub_strdup (curalias->name); - return 1; - } - - return 0; - } - + struct grub_ieee1275_devalias curalias; if (colon) pathlen = (int)(colon - path); /* Try to find an alias for this device. */ - grub_devalias_iterate (match_alias); + FOR_IEEE1275_DEVALIASES (curalias) + /* briQ firmware can change capitalization in /chosen/bootpath. */ + if (grub_strncasecmp (curalias.path, path, pathlen) == 0 + && curalias.path[pathlen] == 0) + { + char *newpath; + newpath = grub_strdup (curalias.name); + grub_ieee1275_devalias_free (&curalias); + return newpath; + } - if (! newpath) - newpath = grub_strndup (path, pathlen); - - return newpath; + return grub_strndup (path, pathlen); } static char * diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index ff540dcdf..e1165042d 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -30,8 +30,10 @@ #include #include -/* This is actualy platform-independant but used only on loongson and sparc. */ -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64) +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif + grub_addr_t grub_modules_get_end (void) { @@ -45,7 +47,6 @@ grub_modules_get_end (void) return grub_modbase + modinfo->size; } -#endif /* Load all modules in core. */ static void @@ -67,6 +68,8 @@ grub_load_modules (void) } } +static char *load_config; + static void grub_load_config (void) { @@ -76,9 +79,17 @@ grub_load_config (void) /* Not an embedded config, skip. */ if (header->type != OBJ_TYPE_CONFIG) continue; - - grub_parser_execute ((char *) header + - sizeof (struct grub_module_header)); + + load_config = grub_malloc (header->size - sizeof (struct grub_module_header) + 1); + if (!load_config) + { + grub_print_error (); + break; + } + grub_memcpy (load_config, (char *) header + + sizeof (struct grub_module_header), + header->size - sizeof (struct grub_module_header)); + load_config[header->size - sizeof (struct grub_module_header)] = 0; break; } } @@ -168,7 +179,16 @@ grub_set_prefix_and_root (void) else grub_free (fwdevice); if (fwpath && !path) - path = fwpath; + { + grub_size_t len = grub_strlen (fwpath); + while (len > 1 && fwpath[len - 1] == '/') + fwpath[--len] = 0; + if (len >= sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1 + && grub_memcmp (fwpath + len - (sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1), GRUB_TARGET_CPU "-" GRUB_PLATFORM, + sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1) == 0) + fwpath[len - (sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1)] = 0; + path = fwpath; + } else grub_free (fwpath); if (device) @@ -203,6 +223,30 @@ grub_load_normal_mode (void) grub_command_execute ("normal", 0, 0); } +static void +reclaim_module_space (void) +{ + grub_addr_t modstart, modend; + + if (!grub_modbase) + return; + +#ifdef GRUB_MACHINE_PCBIOS + modstart = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR; +#else + modstart = grub_modbase; +#endif + modend = grub_modules_get_end (); + grub_modbase = 0; + +#if GRUB_KERNEL_PRELOAD_SPACE_REUSABLE + grub_mm_init_region ((void *) modstart, modend - modstart); +#else + (void) modstart; + (void) modend; +#endif +} + /* The main routine. */ void __attribute__ ((noreturn)) grub_main (void) @@ -214,6 +258,8 @@ grub_main (void) /* First of all, initialize the machine. */ grub_machine_init (); + grub_boot_time ("After machine init."); + #ifdef QUIET_BOOT /* Disable the cursor until we need it. */ FOR_ACTIVE_TERM_OUTPUTS(term) @@ -225,6 +271,10 @@ grub_main (void) grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); #endif + grub_load_config (); + + grub_boot_time ("Before loading embedded modules."); + /* Load pre-loaded modules and free the space. */ grub_register_exported_symbols (); #ifdef GRUB_LINKER_HAVE_INIT @@ -232,15 +282,28 @@ grub_main (void) #endif grub_load_modules (); + grub_boot_time ("After loading embedded modules."); + /* It is better to set the root device as soon as possible, for convenience. */ grub_set_prefix_and_root (); grub_env_export ("root"); grub_env_export ("prefix"); + /* Reclaim space used for modules. */ + reclaim_module_space (); + + grub_boot_time ("After reclaiming module space."); + grub_register_core_commands (); - grub_load_config (); + grub_boot_time ("Before execution of embedded config."); + + if (load_config) + grub_parser_execute (load_config); + + grub_boot_time ("After execution of embedded config. Attempt to go to normal mode"); + grub_load_normal_mode (); #ifdef QUIET_BOOT diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 44b417147..f12026e95 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include const char *type_names[] = { #ifdef GRUB_CPU_WORDS_BIGENDIAN @@ -43,13 +45,16 @@ const char *type_names[] = { "eisa", "tc", "scsi", "dti", "multi", "disk", "tape", "cdrom", "worm", "serial", "net", "video", "par", "point", "key", "audio", "other", "rdisk", "fdisk", "tape", "modem", "monitor", "print", "pointer", - "keyboard", "term", "other", "line", "network", NULL + "keyboard", "term", +#ifndef GRUB_CPU_WORDS_BIGENDIAN + "other", +#endif + "line", "network", NULL }; static int iterate_rec (const char *prefix, const struct grub_arc_component *parent, - int (*hook) (const char *name, - const struct grub_arc_component *comp), + grub_arc_iterate_devs_hook_t hook, void *hook_data, int alt_names) { const struct grub_arc_component *comp; @@ -67,12 +72,13 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent, name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key); if (!name) return 1; - if (hook (name, comp)) + if (hook (name, comp, hook_data)) { grub_free (name); return 1; } - if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names)) + if (iterate_rec ((parent ? name : prefix), comp, hook, hook_data, + alt_names)) { grub_free (name); return 1; @@ -83,15 +89,15 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent, } int -grub_arc_iterate_devs (int (*hook) (const char *name, - const struct grub_arc_component *comp), +grub_arc_iterate_devs (grub_arc_iterate_devs_hook_t hook, void *hook_data, int alt_names) { - return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names); + return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, hook_data, + alt_names); } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { struct grub_arc_memory_descriptor *cur = NULL; while (1) @@ -120,20 +126,105 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) break; } if (hook (((grub_uint64_t) cur->start_page) << 12, - ((grub_uint64_t) cur->num_pages) << 12, type)) + ((grub_uint64_t) cur->num_pages) << 12, type, hook_data)) return GRUB_ERR_NONE; } } +char * +grub_arc_alt_name_to_norm (const char *name, const char *suffix) +{ + char *optr; + const char *iptr; + char * ret = grub_malloc (2 * grub_strlen (name) + grub_strlen (suffix)); + int state = 0; + + if (!ret) + return NULL; + optr = ret; + for (iptr = name + 4; *iptr; iptr++) + if (state == 0) + { + if (!grub_isdigit (*iptr)) + *optr++ = *iptr; + else + { + *optr++ = '('; + *optr++ = *iptr; + state = 1; + } + } + else + { + if (grub_isdigit (*iptr)) + *optr++ = *iptr; + else + { + *optr++ = ')'; + state = 0; + } + } + if (state) + *optr++ = ')'; + grub_strcpy (optr, suffix); + return ret; +} + +static char * +norm_name_to_alt (const char *name) +{ + char *optr; + const char *iptr; + int state = 0; + char * ret = grub_malloc (grub_strlen (name) + sizeof ("arc/")); + + if (!ret) + return NULL; + optr = grub_stpcpy (ret, "arc/"); + for (iptr = name; *iptr; iptr++) + { + if (state == 3) + { + *optr++ = '/'; + state = 0; + } + if (*iptr == '(') + { + state = 1; + continue; + } + if (*iptr == ')') + { + if (state == 1) + *optr++ = '0'; + state = 3; + continue; + } + *optr++ = *iptr; + if (state == 1) + state = 2; + } + *optr = '\0'; + return ret; +} + extern grub_uint32_t grub_total_modules_size __attribute__ ((section(".text"))); grub_addr_t grub_modbase; +extern char _end[]; +static char boot_location[256]; + void grub_machine_init (void) { struct grub_arc_memory_descriptor *cur = NULL; + grub_addr_t modend; - grub_modbase = GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size; + grub_memcpy (boot_location, + (char *) (GRUB_DECOMPRESSOR_LINK_ADDR - 256), 256); + + grub_modbase = ALIGN_UP ((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN); + modend = grub_modbase + grub_total_modules_size; grub_console_init_early (); /* FIXME: measure this. */ @@ -153,10 +244,10 @@ grub_machine_init (void) start = ((grub_uint64_t) cur->start_page) << 12; end = ((grub_uint64_t) cur->num_pages) << 12; end += start; - if ((grub_uint64_t) end > ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - - grub_total_modules_size) & 0x1fffffff)) - end = ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size) - & 0x1fffffff); + if ((grub_uint64_t) start < (modend & 0x1fffffff)) + start = (modend & 0x1fffffff); + if ((grub_uint64_t) end > 0x20000000) + end = 0x20000000; if (end > start) grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000), end - start); @@ -168,7 +259,7 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags __attribute__ ((unused))) { } @@ -196,3 +287,178 @@ grub_exit (void) while (1); } +static char * +get_part (char *dev) +{ + char *ptr; + if (!*dev) + return 0; + ptr = dev + grub_strlen (dev) - 1; + if (ptr == dev || *ptr != ')') + return 0; + ptr--; + while (grub_isdigit (*ptr) && ptr > dev) + ptr--; + if (*ptr != '(' || ptr == dev) + return 0; + ptr--; + if (ptr - dev < (int) sizeof ("partition") - 2) + return 0; + ptr -= sizeof ("partition") - 2; + if (grub_memcmp (ptr, "partition", sizeof ("partition") - 1) != 0) + return 0; + return ptr; +} + +static grub_disk_addr_t +get_partition_offset (char *part, grub_disk_addr_t *en) +{ + grub_arc_fileno_t handle; + grub_disk_addr_t ret = -1; + struct grub_arc_fileinfo info; + grub_arc_err_t r; + + if (GRUB_ARC_FIRMWARE_VECTOR->open (part, GRUB_ARC_FILE_ACCESS_OPEN_RO, + &handle)) + return -1; + + r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (handle, &info); + if (!r) + { + ret = (info.start >> 9); + *en = (info.end >> 9); + } + GRUB_ARC_FIRMWARE_VECTOR->close (handle); + return ret; +} + +struct get_device_name_ctx +{ + char *partition_name; + grub_disk_addr_t poff, pend; +}; + +static int +get_device_name_iter (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t part, void *data) +{ + struct get_device_name_ctx *ctx = data; + + if (grub_partition_get_start (part) == ctx->poff + && grub_partition_get_len (part) == ctx->pend) + { + ctx->partition_name = grub_partition_get_name (part); + return 1; + } + + return 0; +} + +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ + char *loaddev = boot_location; + char *pptr, *partptr; + char *dname; + grub_disk_addr_t poff = -1, pend; + struct get_device_name_ctx ctx; + grub_disk_t parent = 0; + unsigned i; + + for (i = 0; i < ARRAY_SIZE (type_names); i++) + if (type_names[i] + && grub_memcmp (loaddev, type_names[i], grub_strlen (type_names[i])) == 0 + && loaddev[grub_strlen (type_names[i])] == '(') + break; + if (i == ARRAY_SIZE (type_names)) + pptr = loaddev; + else + for (pptr = loaddev; *pptr && *pptr != '/' && *pptr != '\\'; pptr++); + if (*pptr) + { + char *iptr, *optr; + char sep = *pptr; + *path = grub_malloc (grub_strlen (pptr) + 1); + if (!*path) + return; + for (iptr = pptr, optr = *path; *iptr; iptr++, optr++) + if (*iptr == sep) + *optr = '/'; + else + *optr = *iptr; + *optr = '\0'; + *path = grub_strdup (pptr); + *pptr = '\0'; + } + + if (*loaddev == '\0') + { + const char *syspart = 0; + + if (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmware_vector_length + >= ((char *) (&GRUB_ARC_FIRMWARE_VECTOR->getenvironmentvariable + 1) + - (char *) GRUB_ARC_FIRMWARE_VECTOR) + && GRUB_ARC_FIRMWARE_VECTOR->getenvironmentvariable) + syspart = GRUB_ARC_FIRMWARE_VECTOR->getenvironmentvariable ("SystemPartition"); + if (!syspart) + return; + loaddev = grub_strdup (syspart); + } + + partptr = get_part (loaddev); + if (partptr) + { + poff = get_partition_offset (loaddev, &pend); + *partptr = '\0'; + } + dname = norm_name_to_alt (loaddev); + if (poff == (grub_addr_t) -1) + { + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + parent = grub_disk_open (dname); + if (!parent) + { + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + if (poff == 0 + && pend == grub_disk_get_size (parent)) + { + grub_disk_close (parent); + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + ctx.partition_name = NULL; + ctx.poff = poff; + ctx.pend = pend; + + grub_partition_iterate (parent, get_device_name_iter, &ctx); + grub_disk_close (parent); + + if (! ctx.partition_name) + { + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + *device = grub_xasprintf ("%s,%s", dname, + ctx.partition_name); + grub_free (ctx.partition_name); + grub_free (dname); + if (loaddev != boot_location) + grub_free (loaddev); +} diff --git a/grub-core/kern/mips/init.c b/grub-core/kern/mips/init.c index 353f679e6..14b8752ec 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -36,9 +36,3 @@ grub_get_rtc (void) return (((grub_uint64_t) high) << 32) | low; } - -void -grub_machine_get_bootlocation (char **device __attribute__ ((unused)), - char **path __attribute__ ((unused))) -{ -} diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 19f2d639b..d2f579588 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -40,54 +40,57 @@ #include grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); return GRUB_ERR_NONE; } +/* Helper for init_pci. */ +static int +set_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + /* We could use grub_pci_assign_addresses for this but we prefer to + have exactly same memory map as on pmon. */ + switch (pciid) + { + case GRUB_LOONGSON_OHCI_PCIID: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5025000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); + break; + case GRUB_LOONGSON_EHCI_PCIID: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5026000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) + | GRUB_PCI_STATUS_CAPABILITIES); + break; + } + return 0; +} + static void init_pci (void) { - auto int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - /* FIXME: autoscan for BARs and devices. */ - switch (pciid) - { - case GRUB_LOONGSON_OHCI_PCIID: - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0x5025000); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE - | GRUB_PCI_COMMAND_PARITY_ERROR - | GRUB_PCI_COMMAND_BUS_MASTER - | GRUB_PCI_COMMAND_MEM_ENABLED); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); - grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); - break; - case GRUB_LOONGSON_EHCI_PCIID: - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0x5026000); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE - | GRUB_PCI_COMMAND_PARITY_ERROR - | GRUB_PCI_COMMAND_BUS_MASTER - | GRUB_PCI_COMMAND_MEM_ENABLED); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); - grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) - | GRUB_PCI_STATUS_CAPABILITIES); - break; - } - return 0; - } - *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) = 0x8000000c; *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff; @@ -110,7 +113,7 @@ init_pci (void) *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_ADDRESS_REG1)) = 0; - grub_pci_iterate (set_card); + grub_pci_iterate (set_card, NULL); } void @@ -214,16 +217,49 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags __attribute__ ((unused))) { } +static int +halt_via (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_uint16_t pm; + grub_pci_address_t addr; + + if (pciid != 0x30571106) + return 0; + + addr = grub_pci_make_address (dev, 0x40); + pm = grub_pci_read (addr) & ~1; + + if (pm == 0) + { + grub_pci_write (addr, 0x1801); + pm = 0x1800; + } + + addr = grub_pci_make_address (dev, 0x80); + grub_pci_write_byte (addr, 0xff); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, grub_pci_read_word (addr) | GRUB_PCI_COMMAND_IO_ENABLED); + + /* FIXME: This one is derived from qemu. Check on real hardware. */ + grub_outw (0x2000, pm + 4 + GRUB_MACHINE_PCI_IO_BASE); + grub_millisleep (5000); + + return 0; +} + void grub_halt (void) { switch (grub_arch_machine) { case GRUB_ARCH_MACHINE_FULOONG2E: + grub_pci_iterate (halt_via, NULL); break; case GRUB_ARCH_MACHINE_FULOONG2F: { @@ -257,6 +293,12 @@ grub_exit (void) grub_halt (); } +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + extern char _end[]; grub_addr_t grub_modbase = (grub_addr_t) _end; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 782f17fbf..2ea2eb4fd 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -57,8 +57,6 @@ grub_machine_init (void) grub_install_get_time_ms (grub_rtc_get_time_ms); - grub_font_init (); - grub_keylayouts_init (); grub_at_keyboard_init (); @@ -69,12 +67,10 @@ grub_machine_init (void) grub_serial_init (); grub_boot_init (); - - grub_gfxterm_init (); } void -grub_machine_fini (void) +grub_machine_fini (int flags __attribute__ ((unused))) { } @@ -92,12 +88,18 @@ grub_halt (void) } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { - hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE); + hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE, hook_data); return GRUB_ERR_NONE; } +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + extern char _end[]; grub_addr_t grub_modbase = (grub_addr_t) _end; diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 2476038bc..35a11bcf8 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -73,7 +73,6 @@ cont: #endif /* Move the modules out of BSS. */ -#ifndef GRUB_MACHINE_ARC lui $t2, %hi(__bss_start) addiu $t2, %lo(__bss_start) @@ -103,7 +102,6 @@ modulesmovcont: b modulesmovcont addiu $t3, $t3, -1 modulesmovdone: -#endif /* Clean BSS. */ diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 95d46245e..194e7703a 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -71,12 +71,12 @@ void *memmove (void *dest, const void *src, grub_size_t n) void *memcpy (void *dest, const void *src, grub_size_t n) __attribute__ ((alias ("grub_memmove"))); #else -void * __attribute__ ((regparm(0))) +void * GRUB_BUILTIN_ATTR memcpy (void *dest, const void *src, grub_size_t n) { return grub_memmove (dest, src, n); } -void * __attribute__ ((regparm(0))) +void * GRUB_BUILTIN_ATTR memmove (void *dest, const void *src, grub_size_t n) { return grub_memmove (dest, src, n); @@ -94,17 +94,6 @@ grub_strcpy (char *dest, const char *src) return dest; } -char * -grub_strncpy (char *dest, const char *src, int c) -{ - char *p = dest; - - while ((*p++ = *src++) != '\0' && --c) - ; - - return dest; -} - int grub_printf (const char *fmt, ...) { @@ -236,7 +225,7 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n) int memcmp (const void *s1, const void *s2, grub_size_t n) __attribute__ ((alias ("grub_memcmp"))); #else -int __attribute__ ((regparm(0))) +int GRUB_BUILTIN_ATTR memcmp (const void *s1, const void *s2, grub_size_t n) { return grub_memcmp (s1, s2, n); @@ -347,13 +336,6 @@ grub_isspace (int c) return (c == '\n' || c == '\r' || c == ' ' || c == '\t'); } -int -grub_isprint (int c) -{ - return (c >= ' ' && c <= '~'); -} - - unsigned long grub_strtoul (const char *str, char **end, int base) { @@ -378,7 +360,8 @@ grub_strtoull (const char *str, char **end, int base) int found = 0; /* Skip white spaces. */ - while (*str && grub_isspace (*str)) + /* grub_isspace checks that *str != '\0'. */ + while (grub_isspace (*str)) str++; /* Guess the base, if not specified. The prefix `0x' means 16, and @@ -471,6 +454,15 @@ grub_strndup (const char *s, grub_size_t n) return p; } +/* clang detects that we're implementing here a memset so it decides to + optimise and calls memset resulting in infinite recursion. With volatile + we make it not optimise in this way. */ +#ifdef __clang__ +#define VOLATILE_CLANG volatile +#else +#define VOLATILE_CLANG +#endif + void * grub_memset (void *s, int c, grub_size_t len) { @@ -487,13 +479,13 @@ grub_memset (void *s, int c, grub_size_t len) while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1))) { - *(grub_uint8_t *) p = pattern8; + *(VOLATILE_CLANG grub_uint8_t *) p = pattern8; p = (grub_uint8_t *) p + 1; len--; } while (len >= sizeof (unsigned long)) { - *(unsigned long *) p = patternl; + *(VOLATILE_CLANG unsigned long *) p = patternl; p = (unsigned long *) p + 1; len -= sizeof (unsigned long); } @@ -501,7 +493,7 @@ grub_memset (void *s, int c, grub_size_t len) while (len > 0) { - *(grub_uint8_t *) p = pattern8; + *(VOLATILE_CLANG grub_uint8_t *) p = pattern8; p = (grub_uint8_t *) p + 1; len--; } @@ -512,11 +504,18 @@ grub_memset (void *s, int c, grub_size_t len) void *memset (void *s, int c, grub_size_t n) __attribute__ ((alias ("grub_memset"))); #else -void * __attribute__ ((regparm(0))) +void * GRUB_BUILTIN_ATTR memset (void *s, int c, grub_size_t n) { return grub_memset (s, c, n); } + +void GRUB_BUILTIN_ATTR +__bzero (void *s, grub_size_t n) +{ + grub_memset (s, 0, n); +} + #endif grub_size_t @@ -559,6 +558,11 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) grub_uint64_t q = 0; grub_uint64_t m = 0; + /* ARM and IA64 don't have a fast 32-bit division. + Using that code would just make us use libgcc routines, calling + them twice (once for modulo and once for quotient. + */ +#if !defined (__arm__) && !defined (__ia64__) /* Skip the slow computation if 32-bit arithmetic is possible. */ if (n < 0xffffffff && d < 0xffffffff) { @@ -567,6 +571,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) return ((grub_uint32_t) n) / (grub_uint32_t) d; } +#endif while (bits--) { @@ -591,6 +596,53 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) return q; } +#ifndef GRUB_UTIL + +#if defined (__arm__) + +grub_uint32_t +__udivsi3 (grub_uint32_t a, grub_uint32_t b) +{ + return grub_divmod64 (a, b, 0); +} + +grub_uint32_t +__umodsi3 (grub_uint32_t a, grub_uint32_t b) +{ + grub_uint64_t ret; + grub_divmod64 (a, b, &ret); + return ret; +} + + +#endif + +#ifdef __arm__ +grub_uint32_t +__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b) + __attribute__ ((alias ("__udivsi3"))); +#endif + +#if defined (__ia64__) + +grub_uint64_t +__udivdi3 (grub_uint64_t a, grub_uint64_t b) +{ + return grub_divmod64 (a, b, 0); +} + +grub_uint64_t +__umoddi3 (grub_uint64_t a, grub_uint64_t b) +{ + grub_uint64_t ret; + grub_divmod64 (a, b, &ret); + return ret; +} + +#endif + +#endif /* GRUB_UTIL */ + /* Convert a long long value to a string. This function avoids 64-bit modular arithmetic or divisions. */ static char * @@ -631,6 +683,31 @@ grub_lltoa (char *str, int c, unsigned long long n) return p; } +static inline void +write_char (char *str, grub_size_t *count, grub_size_t max_len, unsigned char ch) +{ + if (*count < max_len) + str[*count] = ch; + + (*count)++; +} + +static inline void +write_str (char *str, grub_size_t *count, grub_size_t max_len, const char *s) +{ + while (*s) + write_char (str, count, max_len, *s++); +} + +static inline void +write_fill (char *str, grub_size_t *count, grub_size_t max_len, const char ch, int count_fill) +{ + int i; + for (i = 0; i < count_fill; i++) + write_char (str, count, max_len, ch); +} + + static int grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list args_in) { @@ -639,30 +716,6 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a grub_size_t count = 0; grub_size_t count_args = 0; const char *fmt; - auto void write_char (unsigned char ch); - auto void write_str (const char *s); - auto void write_fill (const char ch, int n); - - void write_char (unsigned char ch) - { - if (count < max_len) - *str++ = ch; - - count++; - } - - void write_str (const char *s) - { - while (*s) - write_char (*s++); - } - - void write_fill (const char ch, int count_fill) - { - int i; - for (i = 0; i < count_fill; i++) - write_char (ch); - } fmt = fmt0; while ((c = *fmt++) != 0) @@ -670,34 +723,33 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a if (c != '%') continue; - if (*fmt && *fmt =='-') + if (*fmt =='-') fmt++; - while (*fmt && grub_isdigit (*fmt)) + while (grub_isdigit (*fmt)) fmt++; - if (*fmt && *fmt == '$') + if (*fmt == '$') fmt++; - if (*fmt && *fmt =='-') + if (*fmt =='-') fmt++; - while (*fmt && grub_isdigit (*fmt)) + while (grub_isdigit (*fmt)) fmt++; - if (*fmt && *fmt =='.') + if (*fmt =='.') fmt++; - while (*fmt && grub_isdigit (*fmt)) + while (grub_isdigit (*fmt)) fmt++; c = *fmt++; if (c == 'l') - { - c = *fmt++; - if (c == 'l') - c = *fmt++; - } + c = *fmt++; + if (c == 'l') + c = *fmt++; + switch (c) { case 'p': @@ -712,16 +764,17 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a } } - enum { INT, WCHAR, LONG, LONGLONG, POINTER } types[count_args]; + enum { INT, LONG, LONGLONG, POINTER } types[count_args]; union { int i; - grub_uint32_t w; long l; long long ll; void *p; } args[count_args]; + COMPILE_TIME_ASSERT (sizeof (int) == sizeof (grub_uint32_t)); + grub_memset (types, 0, sizeof (types)); fmt = fmt0; @@ -738,27 +791,30 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a curn = n++; - if (*fmt && *fmt =='-') - fmt++; - - while (*fmt && grub_isdigit (*fmt)) - fmt++; - - if (*fmt && *fmt =='.') - fmt++; - - while (*fmt && grub_isdigit (*fmt)) + if (*fmt =='-') fmt++; p = fmt; - if (*fmt && *fmt == '$') + while (grub_isdigit (*fmt)) + fmt++; + + if (*fmt == '$') { curn = grub_strtoull (p, 0, 10) - 1; fmt++; } - while (*fmt && grub_isdigit (*fmt)) + if (*fmt =='-') + fmt++; + + while (grub_isdigit (*fmt)) + fmt++; + + if (*fmt =='.') + fmt++; + + while (grub_isdigit (*fmt)) fmt++; c = *fmt++; @@ -790,21 +846,16 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a case 's': types[curn] = POINTER; break; + case 'C': case 'c': types[curn] = INT; break; - case 'C': - types[curn] = WCHAR; - break; } } for (n = 0; n < count_args; n++) switch (types[n]) { - case WCHAR: - args[n].w = va_arg (args_in, grub_uint32_t); - break; case POINTER: args[n].p = va_arg (args_in, void *); break; @@ -825,7 +876,6 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a while ((c = *fmt++) != 0) { char tmp[32]; - char *p; unsigned int format1 = 0; unsigned int format2 = ~ 0U; char zerofill = ' '; @@ -837,7 +887,7 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a if (c != '%') { - write_char (c); + write_char (str, &count, max_len,c); continue; } @@ -845,44 +895,26 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a rescan:; - if (*fmt && *fmt =='-') + if (*fmt =='-') { rightfill = 1; fmt++; } - p = (char *) fmt; /* Read formatting parameters. */ - while (*p && grub_isdigit (*p)) - p++; - - if (p > fmt) + if (grub_isdigit (*fmt)) { - char s[p - fmt + 1]; - grub_strncpy (s, fmt, p - fmt); - s[p - fmt] = 0; - if (s[0] == '0') + if (fmt[0] == '0') zerofill = '0'; - format1 = grub_strtoul (s, 0, 10); - fmt = p; + format1 = grub_strtoul (fmt, (char **) &fmt, 10); } - if (*p && *p == '.') - { - p++; - fmt++; - while (*p && grub_isdigit (*p)) - p++; + if (*fmt == '.') + fmt++; + + if (grub_isdigit (*fmt)) + format2 = grub_strtoul (fmt, (char **) &fmt, 10); - if (p > fmt) - { - char fstr[p - fmt + 1]; - grub_strncpy (fstr, fmt, p - fmt); - fstr[p - fmt] = 0; - format2 = grub_strtoul (fstr, 0, 10); - fmt = p; - } - } if (*fmt == '$') { curn = format1 - 1; @@ -907,13 +939,19 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a } } + if (c == '%') + { + write_char (str, &count, max_len,c); + continue; + } + if (curn >= count_args) continue; switch (c) { case 'p': - write_str ("0x"); + write_str (str, &count, max_len, "0x"); c = 'x'; longlongfmt |= (sizeof (void *) == sizeof (long long)); /* Fall through. */ @@ -933,19 +971,19 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a else grub_lltoa (tmp, c, args[curn].i); if (! rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); - write_str (tmp); + write_fill (str, &count, max_len, zerofill, format1 - grub_strlen (tmp)); + write_str (str, &count, max_len, tmp); if (rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); + write_fill (str, &count, max_len, zerofill, format1 - grub_strlen (tmp)); break; case 'c': - write_char (args[curn].i & 0xff); + write_char (str, &count, max_len,args[curn].i & 0xff); break; case 'C': { - grub_uint32_t code = args[curn].w; + grub_uint32_t code = args[curn].i; int shift; unsigned mask; @@ -964,21 +1002,11 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a shift = 12; mask = 0xe0; } - else if (code <= 0x1fffff) + else if (code <= 0x10ffff) { shift = 18; mask = 0xf0; } - else if (code <= 0x3ffffff) - { - shift = 24; - mask = 0xf8; - } - else if (code <= 0x7fffffff) - { - shift = 30; - mask = 0xfc; - } else { code = '?'; @@ -986,43 +1014,44 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a mask = 0; } - write_char (mask | (code >> shift)); + write_char (str, &count, max_len,mask | (code >> shift)); for (shift -= 6; shift >= 0; shift -= 6) - write_char (0x80 | (0x3f & (code >> shift))); + write_char (str, &count, max_len,0x80 | (0x3f & (code >> shift))); } break; case 's': - p = args[curn].p; - if (p) - { - grub_size_t len = 0; - while (len < format2 && p[len]) - len++; + { + grub_size_t len = 0; + const char *p = args[curn].p ? : "(null)"; - if (!rightfill && len < format1) - write_fill (zerofill, format1 - len); + while (len < format2 && p[len]) + len++; - grub_size_t i; - for (i = 0; i < len; i++) - write_char (*p++); + if (!rightfill && len < format1) + write_fill (str, &count, max_len, zerofill, format1 - len); - if (rightfill && len < format1) - write_fill (zerofill, format1 - len); - } - else - write_str ("(null)"); + grub_size_t i; + for (i = 0; i < len; i++) + write_char (str, &count, max_len,*p++); + + if (rightfill && len < format1) + write_fill (str, &count, max_len, zerofill, format1 - len); + } break; default: - write_char (c); + write_char (str, &count, max_len,c); break; } } - *str = '\0'; + if (count < max_len) + str[count] = '\0'; + else + str[max_len] = '\0'; return count; } @@ -1096,7 +1125,7 @@ grub_xasprintf (const char *fmt, ...) } /* Abort GRUB. This function does not return. */ -void +static void __attribute__ ((noreturn)) grub_abort (void) { grub_printf ("\nAborted."); @@ -1112,18 +1141,17 @@ grub_abort (void) grub_exit (); } -#if ! defined (__APPLE__) && !defined (GRUB_UTIL) -/* GCC emits references to abort(). */ -void abort (void) __attribute__ ((alias ("grub_abort"))); -#endif - -#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) && !defined(GRUB_MACHINE_EMU) -/* Some gcc versions generate a call to this function - in trampolines for nested functions. */ -void __enable_execute_stack (void *addr __attribute__ ((unused))) +void +grub_fatal (const char *fmt, ...) { + va_list ap; + + va_start (ap, fmt); + grub_vprintf (_(fmt), ap); + va_end (ap); + + grub_abort (); } -#endif #if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL) void __register_frame_info (void) @@ -1135,3 +1163,42 @@ void __deregister_frame_info (void) } #endif +#if BOOT_TIME_STATS + +#include + +struct grub_boot_time *grub_boot_time_head; +static struct grub_boot_time **boot_time_last = &grub_boot_time_head; + +void +grub_real_boot_time (const char *file, + const int line, + const char *fmt, ...) +{ + struct grub_boot_time *n; + va_list args; + + grub_error_push (); + n = grub_malloc (sizeof (*n)); + if (!n) + { + grub_errno = 0; + grub_error_pop (); + return; + } + n->file = file; + n->line = line; + n->tp = grub_get_time_ms (); + n->next = 0; + + va_start (args, fmt); + n->msg = grub_xvasprintf (fmt, args); + va_end (args); + + *boot_time_last = n; + boot_time_last = &n->next; + + grub_errno = 0; + grub_error_pop (); +} +#endif diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index 9f08e05bf..6111eef7e 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -117,14 +117,45 @@ grub_mm_init_region (void *addr, grub_size_t size) grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size); #endif + /* Exclude last 4K to avoid overflows. */ + /* If addr + 0x1000 overflows then whole region is in excluded zone. */ + if ((grub_addr_t) addr > ~((grub_addr_t) 0x1000)) + return; + + /* If addr + 0x1000 + size overflows then decrease size. */ + if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size) + size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr; + + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) + { + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); + *r = *q; + r->pre_size += size; + + if (r->pre_size >> GRUB_MM_ALIGN_LOG2) + { + h = (grub_mm_header_t) (r + 1); + h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); + h->magic = GRUB_MM_ALLOC_MAGIC; + r->size += h->size << GRUB_MM_ALIGN_LOG2; + r->pre_size &= (GRUB_MM_ALIGN - 1); + *p = r; + grub_free (h + 1); + } + *p = r; + return; + } + /* Allocate a region from the head. */ r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); - size -= (char *) r - (char *) addr + sizeof (*r); /* If this region is too small, ignore it. */ - if (size < GRUB_MM_ALIGN) + if (size < GRUB_MM_ALIGN + (char *) r - (char *) addr + sizeof (*r)) return; + size -= (char *) r - (char *) addr + sizeof (*r); + h = (grub_mm_header_t) (r + 1); h->next = h; h->magic = GRUB_MM_FREE_MAGIC; @@ -163,7 +194,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) { grub_off_t extra; - extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) % align; + extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); if (extra) extra = align - extra; @@ -452,7 +483,8 @@ grub_realloc (void *ptr, grub_size_t size) if (! q) return q; - grub_memcpy (q, ptr, size); + /* We've already checked that p->size < n. */ + grub_memcpy (q, ptr, p->size << GRUB_MM_ALIGN_LOG2); grub_free (ptr); return q; } diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c index 9213caa76..b9bd12352 100644 --- a/grub-core/kern/parser.c +++ b/grub-core/kern/parser.c @@ -96,8 +96,42 @@ grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result) } +/* Helper for grub_parser_split_cmdline. */ +static inline int +check_varstate (grub_parser_state_t s) +{ + return (s == GRUB_PARSER_STATE_VARNAME + || s == GRUB_PARSER_STATE_VARNAME2 + || s == GRUB_PARSER_STATE_QVARNAME + || s == GRUB_PARSER_STATE_QVARNAME2); +} + + +static void +add_var (char *varname, char **bp, char **vp, + grub_parser_state_t state, grub_parser_state_t newstate) +{ + const char *val; + + /* Check if a variable was being read in and the end of the name + was reached. */ + if (!(check_varstate (state) && !check_varstate (newstate))) + return; + + *((*vp)++) = '\0'; + val = grub_env_get (varname); + *vp = varname; + if (!val) + return; + + /* Insert the contents of the variable in the buffer. */ + for (; *val; val++) + *((*bp)++) = *val; +} + grub_err_t -grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, +grub_parser_split_cmdline (const char *cmdline, + grub_reader_getline_t getline, void *getline_data, int *argc, char ***argv) { grub_parser_state_t state = GRUB_PARSER_STATE_TEXT; @@ -111,45 +145,13 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, char *args; int i; - auto int check_varstate (grub_parser_state_t s); - - int check_varstate (grub_parser_state_t s) - { - return (s == GRUB_PARSER_STATE_VARNAME - || s == GRUB_PARSER_STATE_VARNAME2 - || s == GRUB_PARSER_STATE_QVARNAME - || s == GRUB_PARSER_STATE_QVARNAME2); - } - - auto void add_var (grub_parser_state_t newstate); - - void add_var (grub_parser_state_t newstate) - { - const char *val; - - /* Check if a variable was being read in and the end of the name - was reached. */ - if (!(check_varstate (state) && !check_varstate (newstate))) - return; - - *(vp++) = '\0'; - val = grub_env_get (varname); - vp = varname; - if (!val) - return; - - /* Insert the contents of the variable in the buffer. */ - for (; *val; val++) - *(bp++) = *val; - } - *argc = 0; do { if (!rd || !*rd) { if (getline) - getline (&rd, 1); + getline (&rd, 1, getline_data); else break; } @@ -167,7 +169,7 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, /* If a variable was being processed and this character does not describe the variable anymore, write the variable to the buffer. */ - add_var (newstate); + add_var (varname, &bp, &vp, state, newstate); if (check_varstate (newstate)) { @@ -197,7 +199,7 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, /* A special case for when the last character was part of a variable. */ - add_var (GRUB_PARSER_STATE_TEXT); + add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT); if (bp != buffer && *(bp - 1)) { @@ -232,36 +234,39 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, return 0; } +/* Helper for grub_parser_execute. */ +static grub_err_t +grub_parser_execute_getline (char **line, int cont __attribute__ ((unused)), + void *data) +{ + char **source = data; + char *p; + + if (!*source) + { + *line = 0; + return 0; + } + + p = grub_strchr (*source, '\n'); + + if (p) + *line = grub_strndup (*source, p - *source); + else + *line = grub_strdup (*source); + *source = p ? p + 1 : 0; + return 0; +} + grub_err_t grub_parser_execute (char *source) { - auto grub_err_t getline (char **line, int cont); - grub_err_t getline (char **line, int cont __attribute__ ((unused))) - { - char *p; - - if (!source) - { - *line = 0; - return 0; - } - - p = grub_strchr (source, '\n'); - - if (p) - *line = grub_strndup (source, p - source); - else - *line = grub_strdup (source); - source = p ? p + 1 : 0; - return 0; - } - while (source) { char *line; - getline (&line, 0); - grub_rescue_parse_line (line, getline); + grub_parser_execute_getline (&line, 0, &source); + grub_rescue_parse_line (line, grub_parser_execute_getline, &source); grub_free (line); } diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c index 82ae9c8c2..e499147cb 100644 --- a/grub-core/kern/partition.c +++ b/grub-core/kern/partition.c @@ -59,39 +59,50 @@ grub_partition_check_containment (const grub_disk_t disk, return 1; } +/* Context for grub_partition_map_probe. */ +struct grub_partition_map_probe_ctx +{ + int partnum; + grub_partition_t p; +}; + +/* Helper for grub_partition_map_probe. */ +static int +probe_iter (grub_disk_t dsk, const grub_partition_t partition, void *data) +{ + struct grub_partition_map_probe_ctx *ctx = data; + + if (ctx->partnum != partition->number) + return 0; + + if (!(grub_partition_check_containment (dsk, partition))) + return 0; + + ctx->p = (grub_partition_t) grub_malloc (sizeof (*ctx->p)); + if (! ctx->p) + return 1; + + grub_memcpy (ctx->p, partition, sizeof (*ctx->p)); + return 1; +} + static grub_partition_t grub_partition_map_probe (const grub_partition_map_t partmap, grub_disk_t disk, int partnum) { - grub_partition_t p = 0; + struct grub_partition_map_probe_ctx ctx = { + .partnum = partnum, + .p = 0 + }; - auto int find_func (grub_disk_t d, const grub_partition_t partition); - - int find_func (grub_disk_t dsk, - const grub_partition_t partition) - { - if (partnum != partition->number) - return 0; - - if (!(grub_partition_check_containment (dsk, partition))) - return 0; - - p = (grub_partition_t) grub_malloc (sizeof (*p)); - if (! p) - return 1; - - grub_memcpy (p, partition, sizeof (*p)); - return 1; - } - - partmap->iterate (disk, find_func); + partmap->iterate (disk, probe_iter, &ctx); if (grub_errno) goto fail; - return p; + return ctx.p; fail: - grub_free (p); + grub_free (ctx.p); return 0; } @@ -162,62 +173,71 @@ grub_partition_probe (struct grub_disk *disk, const char *str) return part; } +/* Context for grub_partition_iterate. */ +struct grub_partition_iterate_ctx +{ + int ret; + grub_partition_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_partition_iterate. */ +static int +part_iterate (grub_disk_t dsk, const grub_partition_t partition, void *data) +{ + struct grub_partition_iterate_ctx *ctx = data; + struct grub_partition p = *partition; + + if (!(grub_partition_check_containment (dsk, partition))) + return 0; + + p.parent = dsk->partition; + dsk->partition = 0; + if (ctx->hook (dsk, &p, ctx->hook_data)) + { + ctx->ret = 1; + return 1; + } + if (p.start != 0) + { + const struct grub_partition_map *partmap; + dsk->partition = &p; + FOR_PARTITION_MAPS(partmap) + { + grub_err_t err; + err = partmap->iterate (dsk, part_iterate, ctx); + if (err) + grub_errno = GRUB_ERR_NONE; + if (ctx->ret) + break; + } + } + dsk->partition = p.parent; + return ctx->ret; +} + int grub_partition_iterate (struct grub_disk *disk, - int (*hook) (grub_disk_t disk, - const grub_partition_t partition)) + grub_partition_iterate_hook_t hook, void *hook_data) { - int ret = 0; - - auto int part_iterate (grub_disk_t dsk, const grub_partition_t p); - - int part_iterate (grub_disk_t dsk, - const grub_partition_t partition) - { - struct grub_partition p = *partition; - - if (!(grub_partition_check_containment (dsk, partition))) - return 0; - - p.parent = dsk->partition; - dsk->partition = 0; - if (hook (dsk, &p)) - { - ret = 1; - return 1; - } - if (p.start != 0) - { - const struct grub_partition_map *partmap; - dsk->partition = &p; - FOR_PARTITION_MAPS(partmap) - { - grub_err_t err; - err = partmap->iterate (dsk, part_iterate); - if (err) - grub_errno = GRUB_ERR_NONE; - if (ret) - break; - } - } - dsk->partition = p.parent; - return ret; - } + struct grub_partition_iterate_ctx ctx = { + .ret = 0, + .hook = hook, + .hook_data = hook_data + }; + const struct grub_partition_map *partmap; + FOR_PARTITION_MAPS(partmap) { - const struct grub_partition_map *partmap; - FOR_PARTITION_MAPS(partmap) - { - grub_err_t err; - err = partmap->iterate (disk, part_iterate); - if (err) - grub_errno = GRUB_ERR_NONE; - if (ret) - break; - } + grub_err_t err; + err = partmap->iterate (disk, part_iterate, &ctx); + if (err) + grub_errno = GRUB_ERR_NONE; + if (ctx.ret) + break; } - return ret; + return ctx.ret; } char * diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c index 4057fee5a..8f77b6547 100644 --- a/grub-core/kern/powerpc/dl.c +++ b/grub-core/kern/powerpc/dl.c @@ -38,6 +38,8 @@ grub_arch_dl_check_header (void *ehdr) return GRUB_ERR_NONE; } +#pragma GCC diagnostic ignored "-Wcast-align" + void grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) diff --git a/grub-core/kern/powerpc/ieee1275/startup.S b/grub-core/kern/powerpc/ieee1275/startup.S index b26c47edb..21c884b43 100644 --- a/grub-core/kern/powerpc/ieee1275/startup.S +++ b/grub-core/kern/powerpc/ieee1275/startup.S @@ -34,14 +34,31 @@ _start: /* Stage1 won't zero BSS for us. In other cases, why not do it again? */ lis 6, (__bss_start - 4)@h ori 6, 6, (__bss_start - 4)@l + +2: stb 2, 4(6) + addi 6, 6, 1 + andi. 7, 6, 3 + cmpi 0, 1, 7, 0 + bne 2b + lis 7, (_end - 4)@h ori 7, 7, (_end - 4)@l subf 7, 6, 7 + subi 8, 7, 1 + andi. 8, 8, 3 + addi 8, 8, 1 + sub 7, 7, 8 + srwi 7, 7, 2 /* We store 4 bytes at a time. */ mtctr 7 2: stwu 2, 4(6) /* We know r2 is already 0 from above. */ bdnz 2b + mtctr 8 +2: stb 2, 4(6) /* We know r2 is already 0 from above. */ + addi 6, 6, 1 + bdnz 2b + /* Store r5 in grub_ieee1275_entry_fn. */ lis 9, grub_ieee1275_entry_fn@ha stw 5, grub_ieee1275_entry_fn@l(9) diff --git a/grub-core/kern/rescue_parser.c b/grub-core/kern/rescue_parser.c index 656342d27..ab3d04160 100644 --- a/grub-core/kern/rescue_parser.c +++ b/grub-core/kern/rescue_parser.c @@ -26,14 +26,16 @@ #include grub_err_t -grub_rescue_parse_line (char *line, grub_reader_getline_t getline) +grub_rescue_parse_line (char *line, + grub_reader_getline_t getline, void *getline_data) { char *name; int n; grub_command_t cmd; char **args; - if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0) + if (grub_parser_split_cmdline (line, getline, getline_data, &n, &args) + || n < 0) return grub_errno; if (n == 0) diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c index 78a757268..03826cf63 100644 --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -30,7 +30,8 @@ static char linebuf[GRUB_RESCUE_BUF_SIZE]; /* Prompt to input a command and read the line. */ static grub_err_t -grub_rescue_read_line (char **line, int cont) +grub_rescue_read_line (char **line, int cont, + void *data __attribute__ ((unused))) { int c; int pos = 0; @@ -89,11 +90,11 @@ grub_rescue_run (void) grub_print_error (); grub_errno = GRUB_ERR_NONE; - grub_rescue_read_line (&line, 0); + grub_rescue_read_line (&line, 0, NULL); if (! line || line[0] == '\0') continue; - grub_rescue_parse_line (line, grub_rescue_read_line); + grub_rescue_parse_line (line, grub_rescue_read_line, NULL); grub_free (line); } } diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 5014caf62..07720ee67 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -28,7 +28,11 @@ struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; -void (*grub_term_poll_usb) (void) = NULL; +/* Current color state. */ +grub_uint8_t grub_term_normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR; +grub_uint8_t grub_term_highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR; + +void (*grub_term_poll_usb) (int wait_for_completion) = NULL; void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ @@ -42,7 +46,6 @@ grub_putcode_dumb (grub_uint32_t code, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1 }; @@ -50,7 +53,7 @@ grub_putcode_dumb (grub_uint32_t code, { int n; - n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term) >> 8) + n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term).x) % GRUB_TERM_TAB_WIDTH); while (n--) grub_putcode_dumb (' ', term); @@ -86,7 +89,7 @@ grub_getkey_noblock (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); if (grub_net_poll_cards_idle) grub_net_poll_cards_idle (); diff --git a/grub-core/kern/uboot/hw.c b/grub-core/kern/uboot/hw.c new file mode 100644 index 000000000..272b83bd7 --- /dev/null +++ b/grub-core/kern/uboot/hw.c @@ -0,0 +1,112 @@ +/* hw.c - U-Boot hardware discovery */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_addr_t start_of_ram; + +/* + * grub_uboot_probe_memory(): + * Queries U-Boot for available memory regions. + * + * Sets up heap near the image in memory and sets up "start_of_ram". + */ +void +grub_uboot_mm_init (void) +{ + struct sys_info *si = grub_uboot_get_sys_info (); + + grub_mm_init_region ((void *) grub_modules_get_end (), + GRUB_KERNEL_MACHINE_HEAP_SIZE); + + if (si && (si->mr_no != 0)) + { + int i; + start_of_ram = GRUB_UINT_MAX; + + for (i = 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM) + if (si->mr[i].start < start_of_ram) + start_of_ram = si->mr[i].start; + } +} + +/* + * grub_uboot_probe_hardware(): + */ +grub_err_t +grub_uboot_probe_hardware (void) +{ + int devcount, i; + + devcount = grub_uboot_dev_enum (); + grub_dprintf ("init", "%d devices found\n", devcount); + + for (i = 0; i < devcount; i++) + { + struct device_info *devinfo = grub_uboot_dev_get (i); + + grub_dprintf ("init", "device handle: %d\n", i); + grub_dprintf ("init", " cookie\t= 0x%08x\n", + (grub_uint32_t) devinfo->cookie); + + if (devinfo->type & DEV_TYP_STOR) + { + grub_dprintf ("init", " type\t\t= DISK\n"); + grub_ubootdisk_register (devinfo); + } + else if (devinfo->type & DEV_TYP_NET) + { + /* Dealt with in ubootnet module. */ + grub_dprintf ("init", " type\t\t= NET (not supported yet)\n"); + } + else + { + grub_dprintf ("init", "%s: unknown device type", __FUNCTION__); + } + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +{ + int i; + struct sys_info *si = grub_uboot_get_sys_info (); + + if (!si || (si->mr_no < 1)) + return GRUB_ERR_BUG; + + /* Iterate and call `hook'. */ + for (i = 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM) + hook (si->mr[i].start, si->mr[i].size, GRUB_MEMORY_AVAILABLE, + hook_data); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c new file mode 100644 index 000000000..9d7924c04 --- /dev/null +++ b/grub-core/kern/uboot/init.c @@ -0,0 +1,154 @@ +/* init.c - generic U-Boot initialization and finalization */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char __bss_start[]; +extern char _end[]; +extern grub_size_t grub_total_module_size; +extern int (*grub_uboot_syscall_ptr) (int, int *, ...); +static unsigned long timer_start; + +extern grub_uint32_t grub_uboot_machine_type; +extern grub_addr_t grub_uboot_boot_data; + +void +grub_exit (void) +{ + grub_uboot_return (0); +} + +grub_uint32_t +grub_uboot_get_machine_type (void) +{ + return grub_uboot_machine_type; +} + +grub_addr_t +grub_uboot_get_boot_data (void) +{ + return grub_uboot_boot_data; +} + +static grub_uint64_t +uboot_timer_ms (void) +{ + return (grub_uint64_t) grub_uboot_get_timer (timer_start) / 1000; +} + +void +grub_machine_init (void) +{ + int ver; + + /* First of all - establish connection with U-Boot */ + ver = grub_uboot_api_init (); + if (!ver) + { + /* Don't even have a console to log errors to... */ + grub_exit (); + } + else if (ver > API_SIG_VERSION) + { + /* Try to print an error message */ + grub_uboot_puts ("invalid U-Boot API version\n"); + } + + /* Initialize the console so that GRUB can display messages. */ + grub_console_init_early (); + + /* Enumerate memory and initialize the memory management system. */ + grub_uboot_mm_init (); + + grub_dprintf ("init", "__bss_start: %p\n", __bss_start); + grub_dprintf ("init", "_end: %p\n", _end); + grub_dprintf ("init", "grub_modbase: %p\n", (void *) grub_modbase); + grub_dprintf ("init", "grub_modules_get_end(): %p\n", + (void *) grub_modules_get_end ()); + + /* Initialise full terminfo support */ + grub_console_init_lately (); + + /* Enumerate uboot devices */ + grub_uboot_probe_hardware (); + + /* Initialise timer */ + timer_start = grub_uboot_get_timer (0); + grub_install_get_time_ms (uboot_timer_ms); + + /* Initialize */ + grub_ubootdisk_init (); +} + + +void +grub_machine_fini (int flags __attribute__ ((unused))) +{ +} + +/* + * grub_machine_get_bootlocation(): + * Called from kern/main.c, which expects a device name (minus parentheses) + * and a filesystem path back, if any are known. + * Any returned values must be pointers to dynamically allocated strings. + */ +void +grub_machine_get_bootlocation (char **device, char **path) +{ + char *tmp; + + tmp = grub_uboot_env_get ("grub_bootdev"); + if (tmp) + { + *device = grub_strdup (tmp); + if (*device == NULL) + return; + } + else + *device = NULL; + + tmp = grub_uboot_env_get ("grub_bootpath"); + if (tmp) + { + *path = grub_strdup (tmp); + if (*path == NULL) + return; + } + else + *path = NULL; +} + +void +grub_uboot_fini (void) +{ + grub_ubootdisk_fini (); + grub_console_fini (); +} diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c new file mode 100644 index 000000000..6800a4beb --- /dev/null +++ b/grub-core/kern/uboot/uboot.c @@ -0,0 +1,326 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +/* + * The main syscall entry point is not reentrant, only one call is + * serviced until finished. + * + * int syscall(int call, int *retval, ...) + * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); + * + * call: syscall number + * + * retval: points to the return value placeholder, this is the place the + * syscall puts its return value, if NULL the caller does not + * expect a return value + * + * ... syscall arguments (variable number) + * + * returns: 0 if the call not found, 1 if serviced + */ + +extern int (*grub_uboot_syscall_ptr) (int, int *, ...); +extern int grub_uboot_syscall (int, int *, ...); +extern grub_addr_t grub_uboot_search_hint; + +static struct sys_info uboot_sys_info; +static struct mem_region uboot_mem_info[5]; +static struct device_info * devices; +static int num_devices; + +int +grub_uboot_api_init (void) +{ + struct api_signature *start, *end; + struct api_signature *p; + + if (grub_uboot_search_hint) + { + /* Extended search range to work around Trim Slice U-Boot issue */ + start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff) + - 0x00500000); + end = + (struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN - + API_SIG_MAGLEN + 0x00500000); + } + else + { + start = 0; + end = (struct api_signature *) (256 * 1024 * 1024); + } + + /* Structure alignment is (at least) 8 bytes */ + for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8)) + { + if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0) + { + grub_uboot_syscall_ptr = p->syscall; + return p->version; + } + } + + return 0; +} + +/* + * All functions below are wrappers around the grub_uboot_syscall() function + */ + +int +grub_uboot_getc (void) +{ + int c; + if (!grub_uboot_syscall (API_GETC, NULL, &c)) + return -1; + + return c; +} + +int +grub_uboot_tstc (void) +{ + int c; + if (!grub_uboot_syscall (API_TSTC, NULL, &c)) + return -1; + + return c; +} + +void +grub_uboot_putc (int c) +{ + grub_uboot_syscall (API_PUTC, NULL, &c); +} + +void +grub_uboot_puts (const char *s) +{ + grub_uboot_syscall (API_PUTS, NULL, s); +} + +void +grub_uboot_reset (void) +{ + grub_uboot_syscall (API_RESET, NULL, 0); +} + +struct sys_info * +grub_uboot_get_sys_info (void) +{ + int retval; + + grub_memset (&uboot_sys_info, 0, sizeof (uboot_sys_info)); + grub_memset (&uboot_mem_info, 0, sizeof (uboot_mem_info)); + uboot_sys_info.mr = uboot_mem_info; + uboot_sys_info.mr_no = sizeof (uboot_mem_info) / sizeof (struct mem_region); + + if (grub_uboot_syscall (API_GET_SYS_INFO, &retval, &uboot_sys_info)) + if (retval == 0) + return &uboot_sys_info; + + return NULL; +} + +void +grub_uboot_udelay (grub_uint32_t usec) +{ + grub_uboot_syscall (API_UDELAY, NULL, &usec); +} + +grub_uint32_t +grub_uboot_get_timer (grub_uint32_t base) +{ + grub_uint32_t current; + + if (!grub_uboot_syscall (API_GET_TIMER, NULL, ¤t, &base)) + return 0; + + return current; +} + +int +grub_uboot_dev_enum (void) +{ + struct device_info * enum_devices; + int num_enum_devices, max_devices; + + if (num_devices) + return num_devices; + + max_devices = 2; + enum_devices = grub_malloc (sizeof(struct device_info) * max_devices); + if (!enum_devices) + return 0; + + /* + * The API_DEV_ENUM call starts a fresh enumeration when passed a + * struct device_info with a NULL cookie, and then depends on having + * the previously enumerated device cookie "seeded" into the target + * structure. + */ + + enum_devices[0].cookie = NULL; + num_enum_devices = 0; + + if (grub_uboot_syscall (API_DEV_ENUM, NULL, + &enum_devices[num_enum_devices]) == 0) + goto error; + + num_enum_devices++; + + while (enum_devices[num_enum_devices - 1].cookie != NULL) + { + if (num_enum_devices == max_devices) + { + struct device_info *tmp; + int new_max; + new_max = max_devices * 2; + tmp = grub_realloc (enum_devices, + sizeof (struct device_info) * new_max); + if (!tmp) + { + /* Failed to realloc, so return what we have */ + break; + } + enum_devices = tmp; + max_devices = new_max; + } + + enum_devices[num_enum_devices].cookie = + enum_devices[num_enum_devices - 1].cookie; + if (grub_uboot_syscall (API_DEV_ENUM, NULL, + &enum_devices[num_enum_devices]) == 0) + goto error; + + if (enum_devices[num_enum_devices].cookie == NULL) + break; + + num_enum_devices++; + } + + devices = enum_devices; + return num_devices = num_enum_devices; + + error: + grub_free (enum_devices); + return 0; +} + +#define VALID_DEV(x) (((x) < num_devices) && ((x) >= 0)) +#define OPEN_DEV(x) ((x->state == DEV_STA_OPEN)) + +struct device_info * +grub_uboot_dev_get (int index) +{ + if (VALID_DEV (index)) + return &devices[index]; + + return NULL; +} + + +int +grub_uboot_dev_open (struct device_info *dev) +{ + int retval; + + if (!grub_uboot_syscall (API_DEV_OPEN, &retval, dev)) + return -1; + + return retval; +} + +int +grub_uboot_dev_close (struct device_info *dev) +{ + int retval; + + if (!grub_uboot_syscall (API_DEV_CLOSE, &retval, dev)) + return -1; + + return retval; +} + + +int +grub_uboot_dev_read (struct device_info *dev, void *buf, grub_size_t blocks, + grub_uint32_t start, grub_size_t * real_blocks) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_READ, &retval, dev, buf, + &blocks, &start, real_blocks)) + return -1; + + return retval; +} + +int +grub_uboot_dev_recv (struct device_info *dev, void *buf, + int size, int *real_size) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_READ, &retval, dev, buf, &size, real_size)) + return -1; + + return retval; + +} + +int +grub_uboot_dev_send (struct device_info *dev, void *buf, int size) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_WRITE, &retval, dev, buf, &size)) + return -1; + + return retval; +} + +char * +grub_uboot_env_get (const char *name) +{ + char *value; + + if (!grub_uboot_syscall (API_ENV_GET, NULL, name, &value)) + return NULL; + + return value; +} + +void +grub_uboot_env_set (const char *name, const char *value) +{ + grub_uboot_syscall (API_ENV_SET, NULL, name, value); +} diff --git a/grub-core/kern/vga_init.c b/grub-core/kern/vga_init.c index 889d0128e..3fe2f16de 100644 --- a/grub-core/kern/vga_init.c +++ b/grub-core/kern/vga_init.c @@ -18,6 +18,7 @@ #ifndef __mips__ #include +#include #endif #include #include @@ -45,11 +46,7 @@ static struct {grub_uint8_t r, g, b, a; } colors[] = {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white }; -#ifdef __mips__ -extern unsigned char ascii_bitmaps[]; -#else #include -#endif #ifdef __mips__ #define VGA_ADDR 0xb00a0000 @@ -90,37 +87,6 @@ load_palette (void) void grub_qemu_init_cirrus (void) { -#ifndef __mips__ - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA) - return 0; - - /* FIXME: chooose addresses dynamically. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH - | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); - grub_pci_write (addr, 0xf2000000 - | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED - | GRUB_PCI_COMMAND_IO_ENABLED); - - return 1; - } - - grub_pci_iterate (find_card); -#endif - grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_MISC_WRITE); diff --git a/grub-core/kern/x86_64/xen/hypercall.S b/grub-core/kern/x86_64/xen/hypercall.S new file mode 100644 index 000000000..9b04db6a0 --- /dev/null +++ b/grub-core/kern/x86_64/xen/hypercall.S @@ -0,0 +1,53 @@ +/* hypercall.S - wrappers for Xen hypercalls */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +FUNCTION(grub_xen_sched_op) + movq $__HYPERVISOR_sched_op, %rax + syscall + ret + +FUNCTION(grub_xen_event_channel_op) + movq $__HYPERVISOR_event_channel_op, %rax + syscall + ret + +FUNCTION(grub_xen_update_va_mapping) + movq $__HYPERVISOR_update_va_mapping, %rax + syscall + ret + +FUNCTION(grub_xen_mmuext_op) + movq %rcx, %r10 + movq $__HYPERVISOR_mmuext_op, %rax + syscall + ret + +FUNCTION(grub_xen_grant_table_op) + movq $__HYPERVISOR_grant_table_op, %rax + syscall + ret + +FUNCTION(grub_xen_mmu_update) + movq %rcx, %r10 + movq $__HYPERVISOR_mmu_update, %rax + syscall + ret diff --git a/grub-core/kern/x86_64/xen/startup.S b/grub-core/kern/x86_64/xen/startup.S new file mode 100644 index 000000000..7217ee57b --- /dev/null +++ b/grub-core/kern/x86_64/xen/startup.S @@ -0,0 +1,38 @@ +/* startup.S - bootstrap GRUB itself */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + + .file "startup.S" + .text + .globl start, _start + .code64 + +start: +_start: + leaq LOCAL(stack_end), %rsp + movq %rsi, EXT_C(grub_xen_start_page_addr)(%rip) + + call EXT_C(grub_main) + /* Doesn't return. */ + + .bss + .space (1 << 22) +LOCAL(stack_end): diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c new file mode 100644 index 000000000..3bfd99fc9 --- /dev/null +++ b/grub-core/kern/xen/init.c @@ -0,0 +1,571 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_addr_t grub_modbase; +struct start_info *grub_xen_start_page_addr; +volatile struct xencons_interface *grub_xen_xcons; +volatile struct shared_info *grub_xen_shared_info; +volatile struct xenstore_domain_interface *grub_xen_xenstore; +volatile grant_entry_v2_t *grub_xen_grant_table; +static const grub_size_t total_grants = + GRUB_XEN_PAGE_SIZE / sizeof (grub_xen_grant_table[0]); +grub_size_t grub_xen_n_allocated_shared_pages; + +static grub_xen_mfn_t +grub_xen_ptr2mfn (void *ptr) +{ + grub_xen_mfn_t *mfn_list = + (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; + return mfn_list[(grub_addr_t) ptr >> GRUB_XEN_LOG_PAGE_SIZE]; +} + +void * +grub_xen_alloc_shared_page (domid_t dom, grub_xen_grant_t * grnum) +{ + void *ret; + grub_xen_mfn_t mfn; + volatile grant_entry_v2_t *entry; + + /* Avoid 0. */ + for (entry = grub_xen_grant_table; + entry < grub_xen_grant_table + total_grants; entry++) + if (!entry->hdr.flags) + break; + + if (entry == grub_xen_grant_table + total_grants) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of grant entries"); + return NULL; + } + ret = grub_memalign (GRUB_XEN_PAGE_SIZE, GRUB_XEN_PAGE_SIZE); + if (!ret) + return NULL; + mfn = grub_xen_ptr2mfn (ret); + entry->full_page.pad0 = 0; + entry->full_page.frame = mfn; + entry->full_page.hdr.domid = dom; + mb (); + entry->full_page.hdr.flags = GTF_permit_access; + mb (); + *grnum = entry - grub_xen_grant_table; + grub_xen_n_allocated_shared_pages++; + return ret; +} + +void +grub_xen_free_shared_page (void *ptr) +{ + grub_xen_mfn_t mfn; + volatile grant_entry_v2_t *entry; + + mfn = grub_xen_ptr2mfn (ptr); + for (entry = grub_xen_grant_table + 1; + entry < grub_xen_grant_table + total_grants; entry++) + if (entry->hdr.flags && entry->full_page.frame == mfn) + { + mb (); + entry->hdr.flags = 0; + mb (); + entry->full_page.frame = 0; + mb (); + } + grub_xen_n_allocated_shared_pages--; +} + +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + +static grub_uint8_t window[GRUB_XEN_PAGE_SIZE] + __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE))); + +#ifdef __x86_64__ +#define NUMBER_OF_LEVELS 4 +#else +#define NUMBER_OF_LEVELS 3 +#endif + +#define LOG_POINTERS_PER_PAGE 9 +#define POINTERS_PER_PAGE (1 << LOG_POINTERS_PER_PAGE) + +void +grub_xen_store_send (const void *buf_, grub_size_t len) +{ + const grub_uint8_t *buf = buf_; + struct evtchn_send send; + int event_sent = 0; + while (len) + { + grub_size_t avail, inbuf; + grub_size_t prod, cons; + mb (); + prod = grub_xen_xenstore->req_prod; + cons = grub_xen_xenstore->req_cons; + if (prod >= cons + sizeof (grub_xen_xenstore->req)) + { + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op (SCHEDOP_yield, 0); + continue; + } + event_sent = 0; + avail = cons + sizeof (grub_xen_xenstore->req) - prod; + inbuf = (~prod & (sizeof (grub_xen_xenstore->req) - 1)) + 1; + if (avail > inbuf) + avail = inbuf; + if (avail > len) + avail = len; + grub_memcpy ((void *) &grub_xen_xenstore->req[prod & (sizeof (grub_xen_xenstore->req) - 1)], + buf, avail); + buf += avail; + len -= avail; + mb (); + grub_xen_xenstore->req_prod += avail; + mb (); + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op (SCHEDOP_yield, 0); + } +} + +void +grub_xen_store_recv (void *buf_, grub_size_t len) +{ + grub_uint8_t *buf = buf_; + struct evtchn_send send; + int event_sent = 0; + while (len) + { + grub_size_t avail, inbuf; + grub_size_t prod, cons; + mb (); + prod = grub_xen_xenstore->rsp_prod; + cons = grub_xen_xenstore->rsp_cons; + if (prod <= cons) + { + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op (SCHEDOP_yield, 0); + continue; + } + event_sent = 0; + avail = prod - cons; + inbuf = (~cons & (sizeof (grub_xen_xenstore->req) - 1)) + 1; + if (avail > inbuf) + avail = inbuf; + if (avail > len) + avail = len; + grub_memcpy (buf, + (void *) &grub_xen_xenstore->rsp[cons & (sizeof (grub_xen_xenstore->rsp) - 1)], + avail); + buf += avail; + len -= avail; + mb (); + grub_xen_xenstore->rsp_cons += avail; + mb (); + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op(EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op(SCHEDOP_yield, 0); + } +} + +void * +grub_xenstore_get_file (const char *dir, grub_size_t *len) +{ + struct xsd_sockmsg msg; + char *buf; + grub_size_t dirlen = grub_strlen (dir) + 1; + + if (len) + *len = 0; + + grub_memset (&msg, 0, sizeof (msg)); + msg.type = XS_READ; + msg.len = dirlen; + grub_xen_store_send (&msg, sizeof (msg)); + grub_xen_store_send (dir, dirlen); + grub_xen_store_recv (&msg, sizeof (msg)); + buf = grub_malloc (msg.len + 1); + if (!buf) + return NULL; + grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len); + grub_xen_store_recv (buf, msg.len); + buf[msg.len] = '\0'; + if (msg.type == XS_ERROR) + { + grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", dir, buf); + grub_free (buf); + return NULL; + } + if (len) + *len = msg.len; + return buf; +} + +grub_err_t +grub_xenstore_write_file (const char *dir, const void *buf, grub_size_t len) +{ + struct xsd_sockmsg msg; + grub_size_t dirlen = grub_strlen (dir) + 1; + char *resp; + + grub_memset (&msg, 0, sizeof (msg)); + msg.type = XS_WRITE; + msg.len = dirlen + len + 1; + grub_xen_store_send (&msg, sizeof (msg)); + grub_xen_store_send (dir, dirlen); + grub_xen_store_send (buf, len); + grub_xen_store_send ("", 1); + grub_xen_store_recv (&msg, sizeof (msg)); + resp = grub_malloc (msg.len + 1); + if (!resp) + return grub_errno; + grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len); + grub_xen_store_recv (resp, msg.len); + resp[msg.len] = '\0'; + if (msg.type == XS_ERROR) + { + grub_dprintf ("xen", "error = %s\n", resp); + grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", + dir, resp); + grub_free (resp); + return grub_errno; + } + grub_free (resp); + return GRUB_ERR_NONE; +} + +/* FIXME: error handling. */ +grub_err_t +grub_xenstore_dir (const char *dir, + int (*hook) (const char *dir, void *hook_data), + void *hook_data) +{ + struct xsd_sockmsg msg; + char *buf; + char *ptr; + grub_size_t dirlen = grub_strlen (dir) + 1; + + grub_memset (&msg, 0, sizeof (msg)); + msg.type = XS_DIRECTORY; + msg.len = dirlen; + grub_xen_store_send (&msg, sizeof (msg)); + grub_xen_store_send (dir, dirlen); + grub_xen_store_recv (&msg, sizeof (msg)); + buf = grub_malloc (msg.len + 1); + if (!buf) + return grub_errno; + grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len); + grub_xen_store_recv (buf, msg.len); + buf[msg.len] = '\0'; + if (msg.type == XS_ERROR) + { + grub_err_t err; + err = grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", + dir, buf); + grub_free (buf); + return err; + } + for (ptr = buf; ptr < buf + msg.len; ptr += grub_strlen (ptr) + 1) + if (hook (ptr, hook_data)) + break; + grub_free (buf); + return grub_errno; +} + +unsigned long gntframe = 0; + +#define MAX_N_UNUSABLE_PAGES 4 + +static int +grub_xen_is_page_usable (grub_xen_mfn_t mfn) +{ + if (mfn == grub_xen_start_page_addr->console.domU.mfn) + return 0; + if (mfn == grub_xen_start_page_addr->shared_info) + return 0; + if (mfn == grub_xen_start_page_addr->store_mfn) + return 0; + if (mfn == gntframe) + return 0; + return 1; +} + +static grub_uint64_t +page2offset (grub_uint64_t page) +{ + return page << 12; +} + +static void +map_all_pages (void) +{ + grub_uint64_t total_pages = grub_xen_start_page_addr->nr_pages; + grub_uint64_t i, j; + grub_xen_mfn_t *mfn_list = + (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; + grub_uint64_t *pg = (grub_uint64_t *) window; + grub_uint64_t oldpgstart, oldpgend; + struct gnttab_setup_table gnttab_setup; + struct gnttab_set_version gnttab_setver; + grub_size_t n_unusable_pages = 0; + struct mmu_update m2p_updates[2 * MAX_N_UNUSABLE_PAGES]; + + grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver)); + + gnttab_setver.version = 2; + grub_xen_grant_table_op (GNTTABOP_set_version, &gnttab_setver, 1); + + grub_memset (&gnttab_setup, 0, sizeof (gnttab_setup)); + gnttab_setup.dom = DOMID_SELF; + gnttab_setup.nr_frames = 1; + gnttab_setup.frame_list.p = &gntframe; + + grub_xen_grant_table_op (GNTTABOP_setup_table, &gnttab_setup, 1); + + for (j = 0; j < total_pages - n_unusable_pages; j++) + while (!grub_xen_is_page_usable (mfn_list[j])) + { + grub_xen_mfn_t t; + if (n_unusable_pages >= MAX_N_UNUSABLE_PAGES) + { + struct sched_shutdown arg; + arg.reason = SHUTDOWN_crash; + grub_xen_sched_op (SCHEDOP_shutdown, &arg); + while (1); + } + t = mfn_list[j]; + mfn_list[j] = mfn_list[total_pages - n_unusable_pages - 1]; + mfn_list[total_pages - n_unusable_pages - 1] = t; + + m2p_updates[2 * n_unusable_pages].ptr + = page2offset (mfn_list[j]) | MMU_MACHPHYS_UPDATE; + m2p_updates[2 * n_unusable_pages].val = j; + m2p_updates[2 * n_unusable_pages + 1].ptr + = page2offset (mfn_list[total_pages - n_unusable_pages - 1]) + | MMU_MACHPHYS_UPDATE; + m2p_updates[2 * n_unusable_pages + 1].val = total_pages + - n_unusable_pages - 1; + + n_unusable_pages++; + } + + grub_xen_mmu_update (m2p_updates, 2 * n_unusable_pages, NULL, DOMID_SELF); + + total_pages += 4; + + grub_uint64_t lx[NUMBER_OF_LEVELS], nlx; + grub_uint64_t paging_start = total_pages - 4 - n_unusable_pages, curpage; + + for (nlx = total_pages, i = 0; i < (unsigned) NUMBER_OF_LEVELS; i++) + { + nlx = (nlx + POINTERS_PER_PAGE - 1) >> LOG_POINTERS_PER_PAGE; + /* PAE wants all 4 root directories present. */ +#ifdef __i386__ + if (i == 1) + nlx = 4; +#endif + lx[i] = nlx; + paging_start -= nlx; + } + + oldpgstart = grub_xen_start_page_addr->pt_base >> 12; + oldpgend = oldpgstart + grub_xen_start_page_addr->nr_pt_frames; + + curpage = paging_start; + + int l; + + for (l = NUMBER_OF_LEVELS - 1; l >= 1; l--) + { + for (i = 0; i < lx[l]; i++) + { + grub_xen_update_va_mapping (&window, + page2offset (mfn_list[curpage + i]) | 7, + UVMF_INVLPG); + grub_memset (&window, 0, sizeof (window)); + + for (j = i * POINTERS_PER_PAGE; + j < (i + 1) * POINTERS_PER_PAGE && j < lx[l - 1]; j++) + pg[j - i * POINTERS_PER_PAGE] = + page2offset (mfn_list[curpage + lx[l] + j]) +#ifdef __x86_64__ + | 4 +#endif + | 3; + } + curpage += lx[l]; + } + + for (i = 0; i < lx[0]; i++) + { + grub_xen_update_va_mapping (&window, + page2offset (mfn_list[curpage + i]) | 7, + UVMF_INVLPG); + grub_memset (&window, 0, sizeof (window)); + + for (j = i * POINTERS_PER_PAGE; + j < (i + 1) * POINTERS_PER_PAGE && j < total_pages; j++) + if (j < paging_start && !(j >= oldpgstart && j < oldpgend)) + pg[j - i * POINTERS_PER_PAGE] = page2offset (mfn_list[j]) | 0x7; + else if (j < grub_xen_start_page_addr->nr_pages) + pg[j - i * POINTERS_PER_PAGE] = page2offset (mfn_list[j]) | 5; + else if (j == grub_xen_start_page_addr->nr_pages) + { + pg[j - i * POINTERS_PER_PAGE] = + page2offset (grub_xen_start_page_addr->console.domU.mfn) | 7; + grub_xen_xcons = (void *) (grub_addr_t) page2offset (j); + } + else if (j == grub_xen_start_page_addr->nr_pages + 1) + { + pg[j - i * POINTERS_PER_PAGE] = + grub_xen_start_page_addr->shared_info | 7; + grub_xen_shared_info = (void *) (grub_addr_t) page2offset (j); + } + else if (j == grub_xen_start_page_addr->nr_pages + 2) + { + pg[j - i * POINTERS_PER_PAGE] = + page2offset (grub_xen_start_page_addr->store_mfn) | 7; + grub_xen_xenstore = (void *) (grub_addr_t) page2offset (j); + } + else if (j == grub_xen_start_page_addr->nr_pages + 3) + { + pg[j - i * POINTERS_PER_PAGE] = page2offset (gntframe) | 7; + grub_xen_grant_table = (void *) (grub_addr_t) page2offset (j); + } + } + + grub_xen_update_va_mapping (&window, 0, UVMF_INVLPG); + + mmuext_op_t op[3]; + + op[0].cmd = MMUEXT_PIN_L1_TABLE + (NUMBER_OF_LEVELS - 1); + op[0].arg1.mfn = mfn_list[paging_start]; + op[1].cmd = MMUEXT_NEW_BASEPTR; + op[1].arg1.mfn = mfn_list[paging_start]; + op[2].cmd = MMUEXT_UNPIN_TABLE; + op[2].arg1.mfn = mfn_list[oldpgstart]; + + grub_xen_mmuext_op (op, 3, NULL, DOMID_SELF); + + for (i = oldpgstart; i < oldpgend; i++) + grub_xen_update_va_mapping ((void *) (grub_addr_t) page2offset (i), + page2offset (mfn_list[i]) | 7, UVMF_INVLPG); + void *new_start_page, *new_mfn_list; + new_start_page = (void *) (grub_addr_t) page2offset (paging_start - 1); + grub_memcpy (new_start_page, grub_xen_start_page_addr, 4096); + grub_xen_start_page_addr = new_start_page; + new_mfn_list = (void *) (grub_addr_t) + page2offset (paging_start - 1 + - ((grub_xen_start_page_addr->nr_pages + * sizeof (grub_uint64_t) + 4095) / 4096)); + grub_memcpy (new_mfn_list, mfn_list, grub_xen_start_page_addr->nr_pages + * sizeof (grub_uint64_t)); + grub_xen_start_page_addr->pt_base = page2offset (paging_start); + grub_xen_start_page_addr->mfn_list = (grub_addr_t) new_mfn_list; + + grub_addr_t heap_start = grub_modules_get_end (); + grub_addr_t heap_end = (grub_addr_t) new_mfn_list; + + grub_mm_init_region ((void *) heap_start, heap_end - heap_start); +} + +extern char _end[]; + +void +grub_machine_init (void) +{ +#ifdef __i386__ + grub_xen_vm_assist (VMASST_CMD_enable, VMASST_TYPE_pae_extended_cr3); +#endif + + grub_modbase = ALIGN_UP ((grub_addr_t) _end + + GRUB_KERNEL_MACHINE_MOD_GAP, + GRUB_KERNEL_MACHINE_MOD_ALIGN); + + map_all_pages (); + + grub_console_init (); + + grub_tsc_init (); + + grub_xendisk_init (); + + grub_boot_init (); +} + +void +grub_exit (void) +{ + struct sched_shutdown arg; + + arg.reason = SHUTDOWN_poweroff; + grub_xen_sched_op (SCHEDOP_shutdown, &arg); + while (1); +} + +void +grub_machine_fini (int flags __attribute__ ((unused))) +{ + grub_xendisk_fini (); + grub_boot_fini (); +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +{ + grub_uint64_t total_pages = grub_xen_start_page_addr->nr_pages; + grub_uint64_t usable_pages = grub_xen_start_page_addr->pt_base >> 12; + if (hook (0, page2offset (usable_pages), GRUB_MEMORY_AVAILABLE, hook_data)) + return GRUB_ERR_NONE; + + hook (page2offset (usable_pages), page2offset (total_pages - usable_pages), + GRUB_MEMORY_RESERVED, hook_data); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/LzmaDec.c b/grub-core/lib/LzmaDec.c index 62ebee686..952edb346 100644 --- a/grub-core/lib/LzmaDec.c +++ b/grub-core/lib/LzmaDec.c @@ -26,7 +26,9 @@ #include -#include +#pragma GCC diagnostic ignored "-Wshadow" +#include +#define memcpy grub_memcpy #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) @@ -718,7 +720,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) p->needFlush = 0; } -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index b34188528..8684de400 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -34,25 +34,26 @@ static const struct grub_arg_option help_options[] = {0, 0, 0, 0, 0, 0} }; +/* Helper for find_short. */ +static struct grub_arg_option * +fnd_short (const struct grub_arg_option *opt, char c) +{ + while (opt->doc) + { + if (opt->shortarg == c) + return (struct grub_arg_option *) opt; + opt++; + } + return 0; +} + static struct grub_arg_option * find_short (const struct grub_arg_option *options, char c) { struct grub_arg_option *found = 0; - auto struct grub_arg_option *fnd_short (const struct grub_arg_option *opt); - - struct grub_arg_option *fnd_short (const struct grub_arg_option *opt) - { - while (opt->doc) - { - if (opt->shortarg == c) - return (struct grub_arg_option *) opt; - opt++; - } - return 0; - } if (options) - found = fnd_short (options); + found = fnd_short (options, c); if (! found) { @@ -74,29 +75,30 @@ find_short (const struct grub_arg_option *options, char c) return found; } +/* Helper for find_long. */ +static struct grub_arg_option * +fnd_long (const struct grub_arg_option *opt, const char *s, int len) +{ + while (opt->doc) + { + if (opt->longarg && ! grub_strncmp (opt->longarg, s, len) && + opt->longarg[len] == '\0') + return (struct grub_arg_option *) opt; + opt++; + } + return 0; +} + static struct grub_arg_option * find_long (const struct grub_arg_option *options, const char *s, int len) { struct grub_arg_option *found = 0; - auto struct grub_arg_option *fnd_long (const struct grub_arg_option *opt); - - struct grub_arg_option *fnd_long (const struct grub_arg_option *opt) - { - while (opt->doc) - { - if (opt->longarg && ! grub_strncmp (opt->longarg, s, len) && - opt->longarg[len] == '\0') - return (struct grub_arg_option *) opt; - opt++; - } - return 0; - } if (options) - found = fnd_long (options); + found = fnd_long (options, s, len); if (! found) - found = fnd_long (help_options); + found = fnd_long (help_options, s, len); return found; } @@ -107,69 +109,70 @@ show_usage (grub_extcmd_t cmd) grub_printf ("%s %s %s\n", _("Usage:"), cmd->cmd->name, _(cmd->cmd->summary)); } +static void +showargs (const struct grub_arg_option *opt, + int h_is_used, int u_is_used) +{ + for (; opt->doc; opt++) + { + int spacing = 20; + + if (opt->shortarg && grub_isgraph (opt->shortarg)) + grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); + else if (opt == help_options && ! h_is_used) + grub_printf ("-h, "); + else if (opt == help_options + 1 && ! u_is_used) + grub_printf ("-u, "); + else + grub_printf (" "); + + if (opt->longarg) + { + grub_printf ("--%s", opt->longarg); + spacing -= grub_strlen (opt->longarg) + 2; + + if (opt->arg) + { + grub_printf ("=%s", opt->arg); + spacing -= grub_strlen (opt->arg) + 1; + } + } + + if (spacing < 0) + spacing = 3; + + while (spacing--) + grub_xputs (" "); + + grub_printf ("%s\n", _(opt->doc)); + } +} + void grub_arg_show_help (grub_extcmd_t cmd) { - auto void showargs (const struct grub_arg_option *opt); int h_is_used = 0; int u_is_used = 0; - - auto void showargs (const struct grub_arg_option *opt) - { - for (; opt->doc; opt++) - { - int spacing = 20; - - if (opt->shortarg && grub_isgraph (opt->shortarg)) - grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); - else if (opt == help_options && ! h_is_used) - grub_printf ("-h, "); - else if (opt == help_options + 1 && ! u_is_used) - grub_printf ("-u, "); - else - grub_printf (" "); - - if (opt->longarg) - { - grub_printf ("--%s", opt->longarg); - spacing -= grub_strlen (opt->longarg) + 2; - - if (opt->arg) - { - grub_printf ("=%s", opt->arg); - spacing -= grub_strlen (opt->arg) + 1; - } - } - - if (spacing < 0) - spacing = 3; - - while (spacing--) - grub_xputs (" "); - - grub_printf ("%s\n", _(opt->doc)); - - switch (opt->shortarg) - { - case 'h': - h_is_used = 1; - break; - - case 'u': - u_is_used = 1; - break; - - default: - break; - } - } - } + const struct grub_arg_option *opt; show_usage (cmd); grub_printf ("%s\n\n", _(cmd->cmd->description)); + + for (opt = cmd->options; opt && opt->doc; opt++) + switch (opt->shortarg) + { + case 'h': + h_is_used = 1; + break; + + case 'u': + u_is_used = 1; + break; + } + if (cmd->options) - showargs (cmd->options); - showargs (help_options); + showargs (cmd->options, h_is_used, u_is_used); + showargs (help_options, h_is_used, u_is_used); #if 0 grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT); #endif @@ -209,6 +212,22 @@ parse_option (grub_extcmd_t cmd, const struct grub_arg_option *opt, return 0; } +static inline grub_err_t +add_arg (char ***argl, int *num, char *s) +{ + char **p = *argl; + *argl = grub_realloc (*argl, (++(*num) + 1) * sizeof (char *)); + if (! *argl) + { + grub_free (p); + return grub_errno; + } + (*argl)[(*num) - 1] = s; + (*argl)[(*num)] = NULL; + return 0; +} + + int grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, struct grub_arg_list *usr, char ***args, int *argnum) @@ -217,22 +236,6 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, int arglen; char **argl = 0; int num = 0; - auto grub_err_t add_arg (char *s); - - grub_err_t add_arg (char *s) - { - char **p = argl; - argl = grub_realloc (argl, (++num + 1) * sizeof (char *)); - if (! argl) - { - grub_free (p); - return grub_errno; - } - argl[num - 1] = s; - argl[num] = NULL; - return 0; - } - for (curarg = 0; curarg < argc; curarg++) { @@ -244,7 +247,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if ((num && (cmd->cmd->flags & GRUB_COMMAND_OPTIONS_AT_START)) || arg[0] != '-' || grub_strlen (arg) == 1) { - if (add_arg (arg) != 0) + if (add_arg (&argl, &num, arg) != 0) goto fail; continue; @@ -263,7 +266,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (*curshort) { - if (add_arg (arg) != 0) + if (add_arg (&argl, &num, arg) != 0) goto fail; continue; } @@ -316,7 +319,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (grub_strlen (arg) == 2) { for (curarg++; curarg < argc; curarg++) - if (add_arg (argv[curarg]) != 0) + if (add_arg (&argl, &num, argv[curarg]) != 0) goto fail; break; } @@ -338,7 +341,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) { - if (add_arg (arg) != 0) + if (add_arg (&argl, &num, arg) != 0) goto fail; continue; } @@ -425,7 +428,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, { int i; char **args; - unsigned argcnt; + grub_size_t argcnt; struct grub_arg_list *list; const struct grub_arg_option *options; @@ -437,7 +440,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, for (i = 0; options[i].doc; i++) { if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) - argcnt += (argc + 1) / 2 + 1; /* max possible for any option */ + argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ } list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); @@ -453,7 +456,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) { list[i].args = args; - args += argc / 2 + 1; + args += (grub_size_t) argc / 2 + 1; } } return list; diff --git a/grub-core/lib/arm/setjmp.S b/grub-core/lib/arm/setjmp.S new file mode 100644 index 000000000..4f1567946 --- /dev/null +++ b/grub-core/lib/arm/setjmp.S @@ -0,0 +1,46 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .syntax unified + .arm + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + stm r0, { r4-r11, sp, lr } + mov r0, #0 + bx lr + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldm r0, { r4-r11, sp, lr } + movs r0, r1 + moveq r0, #1 + bx lr diff --git a/grub-core/lib/backtrace.c b/grub-core/lib/backtrace.c index 32945d9f8..825a8800e 100644 --- a/grub-core/lib/backtrace.c +++ b/grub-core/lib/backtrace.c @@ -39,7 +39,7 @@ grub_backtrace_print_address (void *addr) + segment->size > (grub_uint8_t *) addr) { grub_printf ("%s.%x+%" PRIxGRUB_SIZE, mod->name, segment->section, - (grub_uint8_t *) addr - (grub_uint8_t *) segment->addr); + (grub_size_t) ((grub_uint8_t *) addr - (grub_uint8_t *) segment->addr)); return; } } diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c index a702e6487..d5e10ee87 100644 --- a/grub-core/lib/cmdline.c +++ b/grub-core/lib/cmdline.c @@ -56,6 +56,9 @@ unsigned int grub_loader_cmdline_size (int argc, char *argv[]) size++; /* Separator space or NULL. */ } + if (size == 0) + size = 1; + return size; } diff --git a/grub-core/lib/crc.c b/grub-core/lib/crc.c index ffc3ef3b5..bf97cc63a 100644 --- a/grub-core/lib/crc.c +++ b/grub-core/lib/crc.c @@ -22,25 +22,26 @@ static grub_uint32_t crc32c_table [256]; +/* Helper for init_crc32c_table. */ +static grub_uint32_t +reflect (grub_uint32_t ref, int len) +{ + grub_uint32_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1 << (len - i); + ref >>= 1; + } + + return result; +} + static void init_crc32c_table (void) { - auto grub_uint32_t reflect (grub_uint32_t ref, int len); - grub_uint32_t reflect (grub_uint32_t ref, int len) - { - grub_uint32_t result = 0; - int i; - - for (i = 1; i <= len; i++) - { - if (ref & 1) - result |= 1 << (len - i); - ref >>= 1; - } - - return result; - } - grub_uint32_t polynomial = 0x1edc6f41; int i, j; diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c index 4b1c92cf0..4960f3f89 100644 --- a/grub-core/lib/crc64.c +++ b/grub-core/lib/crc64.c @@ -25,25 +25,26 @@ GRUB_MOD_LICENSE ("GPLv3+"); static grub_uint64_t crc64_table [256]; +/* Helper for init_crc64_table. */ +static grub_uint64_t +reflect (grub_uint64_t ref, int len) +{ + grub_uint64_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1ULL << (len - i); + ref >>= 1; + } + + return result; +} + static void init_crc64_table (void) { - auto grub_uint64_t reflect (grub_uint64_t ref, int len); - grub_uint64_t reflect (grub_uint64_t ref, int len) - { - grub_uint64_t result = 0; - int i; - - for (i = 1; i <= len; i++) - { - if (ref & 1) - result |= 1ULL << (len - i); - ref >>= 1; - } - - return result; - } - grub_uint64_t polynomial = 0x42f0e1eba9ea3693ULL; int i, j; diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index f4b13ed3d..e31afb745 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -23,13 +23,7 @@ #include #include #include - -#ifdef GRUB_UTIL -#include -#include -#include -#include -#endif +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -56,6 +50,38 @@ grub_burn_stack (grub_size_t size) grub_burn_stack (size - sizeof (buf)); } +void +_gcry_burn_stack (int size) +{ + grub_burn_stack (size); +} + +void __attribute__ ((noreturn)) +_gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) + +{ + grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func); +} + + +void _gcry_log_error (const char *fmt, ...) +{ + va_list args; + const char *debug = grub_env_get ("debug"); + + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt")) + { + grub_printf ("gcrypt error: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + } +} void grub_cipher_register (gcry_cipher_spec_t *cipher) @@ -235,11 +261,13 @@ grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher, { const grub_uint8_t *inptr; grub_uint8_t *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; if (size % cipher->cipher->blocksize != 0) return GPG_ERR_INV_ARG; + if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) @@ -404,43 +432,11 @@ grub_crypto_memcmp (const void *a, const void *b, grub_size_t n) return !!counter; } +#ifndef GRUB_UTIL + int grub_password_get (char buf[], unsigned buf_size) { -#ifdef GRUB_UTIL - FILE *in; - struct termios s, t; - int tty_changed = 0; - char *ptr; - - /* Disable echoing. Based on glibc. */ - in = fopen ("/dev/tty", "w+c"); - if (in == NULL) - in = stdin; - - if (tcgetattr (fileno (in), &t) == 0) - { - /* Save the old one. */ - s = t; - /* Tricky, tricky. */ - t.c_lflag &= ~(ECHO|ISIG); - tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0); - } - else - tty_changed = 0; - fgets (buf, buf_size, stdin); - ptr = buf + strlen (buf) - 1; - while (buf <= ptr && (*ptr == '\n' || *ptr == '\r')) - *ptr-- = 0; - /* Restore the original setting. */ - if (tty_changed) - (void) tcsetattr (fileno (in), TCSAFLUSH, &s); - - grub_xputs ("\n"); - grub_refresh (); - - return 1; -#else unsigned cur_len = 0; int key; @@ -475,5 +471,6 @@ grub_password_get (char buf[], unsigned buf_size) grub_refresh (); return (key != '\e'); -#endif } +#endif + diff --git a/grub-core/lib/disk.c b/grub-core/lib/disk.c new file mode 100644 index 000000000..c7ba68007 --- /dev/null +++ b/grub-core/lib/disk.c @@ -0,0 +1,161 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#include "../kern/disk_common.c" + +static void +grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, + grub_disk_addr_t sector) +{ + unsigned cache_index; + struct grub_disk_cache *cache; + + sector &= ~(GRUB_DISK_CACHE_SIZE - 1); + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; + + if (cache->dev_id == dev_id && cache->disk_id == disk_id + && cache->sector == sector && cache->data) + { + cache->lock = 1; + grub_free (cache->data); + cache->data = 0; + cache->lock = 0; + } +} + +grub_err_t +grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, const void *buf) +{ + unsigned real_offset; + grub_disk_addr_t aligned_sector; + + grub_dprintf ("disk", "Writing `%s'...\n", disk->name); + + if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) + return -1; + + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); + real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + sector = aligned_sector; + + while (size) + { + if (real_offset != 0 || (size < (1U << disk->log_sector_size) + && size != 0)) + { + char *tmp_buf; + grub_size_t len; + grub_partition_t part; + + tmp_buf = grub_malloc (1 << disk->log_sector_size); + if (!tmp_buf) + return grub_errno; + + part = disk->partition; + disk->partition = 0; + if (grub_disk_read (disk, sector, + 0, (1 << disk->log_sector_size), tmp_buf) + != GRUB_ERR_NONE) + { + disk->partition = part; + grub_free (tmp_buf); + goto finish; + } + disk->partition = part; + + len = (1 << disk->log_sector_size) - real_offset; + if (len > size) + len = size; + + grub_memcpy (tmp_buf + real_offset, buf, len); + + grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); + + if ((disk->dev->write) (disk, transform_sector (disk, sector), + 1, tmp_buf) != GRUB_ERR_NONE) + { + grub_free (tmp_buf); + goto finish; + } + + grub_free (tmp_buf); + + sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); + buf = (const char *) buf + len; + size -= len; + real_offset = 0; + } + else + { + grub_size_t len; + grub_size_t n; + + len = size & ~((1 << disk->log_sector_size) - 1); + n = size >> disk->log_sector_size; + + if (n > (disk->max_agglomerate + << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size))) + n = (disk->max_agglomerate + << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size)); + + if ((disk->dev->write) (disk, transform_sector (disk, sector), + n, buf) != GRUB_ERR_NONE) + goto finish; + + while (n--) + { + grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); + sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); + } + + buf = (const char *) buf + len; + size -= len; + } + } + + finish: + + return grub_errno; +} + +GRUB_MOD_INIT(disk) +{ + grub_disk_write_weak = grub_disk_write; +} + +GRUB_MOD_FINI(disk) +{ + grub_disk_write_weak = NULL; +} diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c index 5ebf2cd1d..ce93db39f 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -23,12 +23,13 @@ #include #include #include +#include void grub_halt (void) { - grub_machine_fini (); -#ifndef __ia64__ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); +#if !defined(__ia64__) && !defined(__arm__) grub_acpi_halt (); #endif efi_call_4 (grub_efi_system_table->runtime_services->reset_system, diff --git a/grub-core/lib/efi/reboot.c b/grub-core/lib/efi/reboot.c index 9382370f7..7de8bcb5d 100644 --- a/grub-core/lib/efi/reboot.c +++ b/grub-core/lib/efi/reboot.c @@ -21,11 +21,12 @@ #include #include #include +#include void grub_reboot (void) { - grub_machine_fini (); + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); for (;;) ; diff --git a/grub-core/lib/efi/relocator.c b/grub-core/lib/efi/relocator.c index 0d346bea3..319b69eeb 100644 --- a/grub-core/lib/efi/relocator.c +++ b/grub-core/lib/efi/relocator.c @@ -96,10 +96,10 @@ grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) if (grub_efi_is_finished) return 1; - +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF grub_dprintf ("relocator", "EFI alloc: %llx, %llx\n", (unsigned long long) start, (unsigned long long) size); - +#endif b = grub_efi_system_table->boot_services; status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS, GRUB_EFI_LOADER_DATA, size >> 12, &address); diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c index 311927bd8..230e0e9d9 100644 --- a/grub-core/lib/envblk.c +++ b/grub-core/lib/envblk.c @@ -225,7 +225,8 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name) void grub_envblk_iterate (grub_envblk_t envblk, - int hook (const char *name, const char *value)) + void *hook_data, + int hook (const char *name, const char *value, void *hook_data)) { char *p, *pend; @@ -285,7 +286,7 @@ grub_envblk_iterate (grub_envblk_t envblk, } *q = '\0'; - ret = hook (name, value); + ret = hook (name, value, hook_data); grub_free (name); if (ret) return; diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c new file mode 100644 index 000000000..9b77e1c67 --- /dev/null +++ b/grub-core/lib/fdt.c @@ -0,0 +1,423 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +#define FDT_SUPPORTED_VERSION 17 + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +#define struct_end(fdt) \ + ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) \ + + grub_fdt_get_size_dt_struct(fdt)) + +/* Size needed by a node entry: 2 tokens (FDT_BEGIN_NODE and FDT_END_NODE), plus + the NULL-terminated string containing the name, plus padding if needed. */ +#define node_entry_size(node_name) \ + (2 * sizeof(grub_uint32_t) \ + + ALIGN_UP (grub_strlen (name) + 1, sizeof(grub_uint32_t))) + +/* Size needed by a property entry: 1 token (FDT_PROPERTY), plus len and nameoff + fields, plus the property value, plus padding if needed. */ +#define prop_entry_size(prop_len) \ + (3 * sizeof(grub_uint32_t) + ALIGN_UP(prop_len, sizeof(grub_uint32_t))) + +#define SKIP_NODE_NAME(name, token, end) \ + name = (char *) ((token) + 1); \ + while (name < (char *) end) \ + { \ + if (!*name++) \ + break; \ + } \ + token = (grub_uint32_t *) ALIGN_UP((grub_addr_t) (name), sizeof(*token)) + + +static grub_uint32_t *get_next_node (const void *fdt, char *node_name) +{ + grub_uint32_t *end = (void *) struct_end (fdt); + grub_uint32_t *token; + + if (node_name >= (char *) end) + return NULL; + while (*node_name++) + { + if (node_name >= (char *) end) + return NULL; + } + token = (grub_uint32_t *) ALIGN_UP ((grub_addr_t) node_name, 4); + while (token < end) + { + switch (grub_be_to_cpu32(*token)) + { + case FDT_BEGIN_NODE: + token = get_next_node (fdt, (char *) (token + 1)); + if (!token) + return NULL; + break; + case FDT_END_NODE: + token++; + if (token >= end) + return NULL; + return token; + case FDT_PROP: + /* Skip property token and following data (len, nameoff and property + value). */ + token += prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_NOP: + token++; + break; + default: + return NULL; + } + } + return NULL; +} + +static int get_mem_rsvmap_size (const void *fdt) +{ + int size = 0; + grub_uint64_t *ptr = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_mem_rsvmap (fdt)); + + do + { + size += 2 * sizeof(*ptr); + if (!*ptr && !*(ptr + 1)) + return size; + ptr += 2; + } while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt) + - 2 * sizeof(grub_uint64_t)); + return -1; +} + +static grub_uint32_t get_free_space (void *fdt) +{ + int mem_rsvmap_size = get_mem_rsvmap_size (fdt); + + if (mem_rsvmap_size < 0) + /* invalid memory reservation block */ + return 0; + return (grub_fdt_get_totalsize (fdt) - sizeof(grub_fdt_header_t) + - mem_rsvmap_size - grub_fdt_get_size_dt_strings (fdt) + - grub_fdt_get_size_dt_struct (fdt)); +} + +static int add_subnode (void *fdt, int parentoffset, const char *name) +{ + grub_uint32_t *token = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + grub_uint32_t *end = (void *) struct_end (fdt); + unsigned int entry_size = node_entry_size (name); + char *node_name; + + SKIP_NODE_NAME(node_name, token, end); + + /* Insert the new subnode just after the properties of the parent node (if + any).*/ + while (1) + { + if (token >= end) + return -1; + switch (grub_be_to_cpu32(*token)) + { + case FDT_PROP: + /* Skip len, nameoff and property value. */ + token += prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_BEGIN_NODE: + case FDT_END_NODE: + goto insert; + case FDT_NOP: + token++; + break; + default: + /* invalid token */ + return -1; + } + } +insert: + grub_memmove (token + entry_size / sizeof(*token), token, + (grub_addr_t) end - (grub_addr_t) token); + *token = grub_cpu_to_be32(FDT_BEGIN_NODE); + token[entry_size / sizeof(*token) - 2] = 0; /* padding bytes */ + grub_strcpy((char *) (token + 1), name); + token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32(FDT_END_NODE); + return ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct(fdt)); +} + +/* Rearrange FDT blocks in the canonical order: first the memory reservation + block (just after the FDT header), then the structure block and finally the + strings block. No free space is left between the first and the second block, + while the space between the second and the third block is given by the + clearance argument. */ +static int rearrange_blocks (void *fdt, unsigned int clearance) +{ + grub_uint32_t off_mem_rsvmap = ALIGN_UP(sizeof(grub_fdt_header_t), 8); + grub_uint32_t off_dt_struct = off_mem_rsvmap + get_mem_rsvmap_size (fdt); + grub_uint32_t off_dt_strings = off_dt_struct + + grub_fdt_get_size_dt_struct (fdt) + + clearance; + grub_uint8_t *fdt_ptr = fdt; + grub_uint8_t *tmp_fdt; + + if ((grub_fdt_get_off_mem_rsvmap (fdt) == off_mem_rsvmap) + && (grub_fdt_get_off_dt_struct (fdt) == off_dt_struct)) + { + /* No need to allocate memory for a temporary FDT, just move the strings + block if needed. */ + if (grub_fdt_get_off_dt_strings (fdt) != off_dt_strings) + { + grub_memmove(fdt_ptr + off_dt_strings, + fdt_ptr + grub_fdt_get_off_dt_strings (fdt), + grub_fdt_get_size_dt_strings (fdt)); + grub_fdt_set_off_dt_strings (fdt, off_dt_strings); + } + return 0; + } + tmp_fdt = grub_malloc (grub_fdt_get_totalsize (fdt)); + if (!tmp_fdt) + return -1; + grub_memcpy (tmp_fdt + off_mem_rsvmap, + fdt_ptr + grub_fdt_get_off_mem_rsvmap (fdt), + get_mem_rsvmap_size (fdt)); + grub_fdt_set_off_mem_rsvmap (fdt, off_mem_rsvmap); + grub_memcpy (tmp_fdt + off_dt_struct, + fdt_ptr + grub_fdt_get_off_dt_struct (fdt), + grub_fdt_get_size_dt_struct (fdt)); + grub_fdt_set_off_dt_struct (fdt, off_dt_struct); + grub_memcpy (tmp_fdt + off_dt_strings, + fdt_ptr + grub_fdt_get_off_dt_strings (fdt), + grub_fdt_get_size_dt_strings (fdt)); + grub_fdt_set_off_dt_strings (fdt, off_dt_strings); + + /* Copy reordered blocks back to fdt. */ + memcpy (fdt_ptr + off_mem_rsvmap, tmp_fdt + off_mem_rsvmap, + grub_fdt_get_totalsize (fdt) - off_mem_rsvmap); + + grub_free(tmp_fdt); + return 0; +} + +static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset, + const char *name) +{ + grub_uint32_t *prop = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + + nodeoffset); + grub_uint32_t *end = (void *) struct_end(fdt); + grub_uint32_t nameoff; + char *node_name; + + SKIP_NODE_NAME(node_name, prop, end); + while (prop < end - 2) + { + if (grub_be_to_cpu32(*prop) == FDT_PROP) + { + nameoff = grub_be_to_cpu32(*(prop + 2)); + if ((nameoff + grub_strlen (name) < grub_fdt_get_size_dt_strings (fdt)) + && !grub_strcmp (name, (char *) fdt + + grub_fdt_get_off_dt_strings (fdt) + nameoff)) + { + if (prop + prop_entry_size(grub_be_to_cpu32(*(prop + 1))) + / sizeof (*prop) >= end) + return NULL; + return prop; + } + prop += prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop); + } + else if (grub_be_to_cpu32(*prop) == FDT_NOP) + prop++; + else + return NULL; + } + return NULL; +} + +/* Check the FDT header for consistency and adjust the totalsize field to match + the size allocated for the FDT; if this function is called before the other + functions in this file and returns success, the other functions are + guaranteed not to access memory locations outside the allocated memory. */ +int grub_fdt_check_header (void *fdt, unsigned int size) +{ + if (((grub_addr_t) fdt & 0x7) || (grub_fdt_get_magic (fdt) != FDT_MAGIC) + || (grub_fdt_get_totalsize (fdt) > size) + || (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION) + || (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION) + || (grub_fdt_get_off_dt_struct (fdt) & 0x00000003) + || (grub_fdt_get_size_dt_struct (fdt) & 0x00000003) + || (grub_fdt_get_off_dt_struct (fdt) + grub_fdt_get_size_dt_struct (fdt) + > grub_fdt_get_totalsize (fdt)) + || (grub_fdt_get_off_dt_strings (fdt) + grub_fdt_get_size_dt_strings (fdt) + > grub_fdt_get_totalsize (fdt)) + || (grub_fdt_get_off_mem_rsvmap (fdt) & 0x00000007) + || (grub_fdt_get_off_mem_rsvmap (fdt) + > grub_fdt_get_totalsize (fdt) - 2 * sizeof(grub_uint64_t))) + return -1; + return 0; +} + +/* Find a direct sub-node of a given parent node. */ +int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset, + const char *name) +{ + grub_uint32_t *token, *end; + char *node_name; + + if (parentoffset & 0x3) + return -1; + token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + end = (void *) struct_end (fdt); + if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE)) + return -1; + SKIP_NODE_NAME(node_name, token, end); + while (token < end) + { + switch (grub_be_to_cpu32(*token)) + { + case FDT_BEGIN_NODE: + node_name = (char *) (token + 1); + if (node_name + grub_strlen (name) >= (char *) end) + return -1; + if (!grub_strcmp (node_name, name)) + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); + token = get_next_node (fdt, node_name); + if (!token) + return -1; + break; + case FDT_PROP: + /* Skip property token and following data (len, nameoff and property + value). */ + if (token >= end - 1) + return -1; + token += prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_NOP: + token++; + break; + default: + return -1; + } + } + return -1; +} + +int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset, + const char *name) +{ + unsigned int entry_size = node_entry_size(name); + + if ((parentoffset & 0x3) || (get_free_space (fdt) < entry_size)) + return -1; + + /* The new node entry will increase the size of the structure block: rearrange + blocks such that there is sufficient free space between the structure and + the strings block, then add the new node entry. */ + if (rearrange_blocks (fdt, entry_size) < 0) + return -1; + return add_subnode (fdt, parentoffset, name); +} + +int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, + const void *val, grub_uint32_t len) +{ + grub_uint32_t *prop; + int prop_name_present = 0; + grub_uint32_t nameoff = 0; + + if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) + || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) + != FDT_BEGIN_NODE)) + return -1; + prop = find_prop (fdt, nodeoffset, name); + if (prop) + { + grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)), + sizeof(grub_uint32_t)); + grub_uint32_t i; + + prop_name_present = 1; + for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++) + *(prop + 3 + i) = grub_cpu_to_be32 (FDT_NOP); + if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t))) + { + /* Length of new property value is greater than the space allocated + for the current value: a new entry needs to be created, so save the + nameoff field of the current entry and replace the current entry + with NOP tokens. */ + nameoff = grub_be_to_cpu32 (*(prop + 2)); + *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32 (FDT_NOP); + prop = NULL; + } + } + if (!prop || !prop_name_present) { + unsigned int needed_space = 0; + + if (!prop) + needed_space = prop_entry_size(len); + if (!prop_name_present) + needed_space += grub_strlen (name) + 1; + if (needed_space > get_free_space (fdt)) + return -1; + if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0) + return -1; + } + if (!prop_name_present) { + /* Append the property name at the end of the strings block. */ + nameoff = grub_fdt_get_size_dt_strings (fdt); + grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff, + name); + grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt) + + grub_strlen (name) + 1); + } + if (!prop) { + char *node_name = (char *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset + + sizeof(grub_uint32_t)); + + prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4)); + grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop, + struct_end(fdt) - (grub_addr_t) prop); + grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt) + + prop_entry_size(len)); + *prop = grub_cpu_to_be32 (FDT_PROP); + *(prop + 2) = grub_cpu_to_be32 (nameoff); + } + *(prop + 1) = grub_cpu_to_be32 (len); + + /* Insert padding bytes at the end of the value; if they are not needed, they + will be overwritten by the following memcpy. */ + *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0; + + grub_memcpy (prop + 3, val, len); + return 0; +} diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c index bd878c9bf..9f8405494 100644 --- a/grub-core/lib/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include const char bochs_shutdown[] = "Shutdown"; @@ -37,6 +39,23 @@ stop (void) } } +static int +grub_shutdown_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + /* QEMU. */ + if (pciid == 0x71138086) + { + grub_pci_address_t addr; + addr = grub_pci_make_address (dev, 0x40); + grub_pci_write (addr, 0x7001); + addr = grub_pci_make_address (dev, 0x80); + grub_pci_write (addr, grub_pci_read (addr) | 1); + grub_outw (0x2000, 0x7004); + } + return 0; +} + void grub_halt (void) { @@ -49,10 +68,12 @@ grub_halt (void) /* Disable interrupts. */ __asm__ __volatile__ ("cli"); - /* Bochs, QEMU, etc. */ + /* Bochs, QEMU, etc. Removed in newer QEMU releases. */ for (i = 0; i < sizeof (bochs_shutdown) - 1; i++) grub_outb (bochs_shutdown[i], 0x8900); + grub_pci_iterate (grub_shutdown_pci_iter, NULL); + grub_puts_ (N_("GRUB doesn't know how to halt this machine yet!")); /* In order to return we'd have to check what the previous status of IF diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c index 0587f1477..a234244dc 100644 --- a/grub-core/lib/i386/reboot.c +++ b/grub-core/lib/i386/reboot.c @@ -58,4 +58,3 @@ grub_reboot (void) while (1); } - diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index df25b30fa..d2a1b27ae 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -28,19 +28,6 @@ #include #include -extern grub_uint8_t grub_relocator_forward_start; -extern grub_uint8_t grub_relocator_forward_end; -extern grub_uint8_t grub_relocator_backward_start; -extern grub_uint8_t grub_relocator_backward_end; - -extern void *grub_relocator_backward_dest; -extern void *grub_relocator_backward_src; -extern grub_size_t grub_relocator_backward_chunk_size; - -extern void *grub_relocator_forward_dest; -extern void *grub_relocator_forward_src; -extern grub_size_t grub_relocator_forward_chunk_size; - extern grub_uint8_t grub_relocator16_start; extern grub_uint8_t grub_relocator16_end; extern grub_uint16_t grub_relocator16_cs; @@ -54,6 +41,7 @@ extern grub_uint16_t grub_relocator16_sp; extern grub_uint32_t grub_relocator16_edx; extern grub_uint32_t grub_relocator16_ebx; extern grub_uint32_t grub_relocator16_esi; +extern grub_uint32_t grub_relocator16_ebp; extern grub_uint16_t grub_relocator16_keep_a20_enabled; @@ -84,75 +72,6 @@ extern struct grub_i386_idt grub_relocator16_idt; #define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) -grub_size_t grub_relocator_align = 1; -grub_size_t grub_relocator_forward_size; -grub_size_t grub_relocator_backward_size; -#ifdef __x86_64__ -grub_size_t grub_relocator_jumper_size = 12; -#else -grub_size_t grub_relocator_jumper_size = 7; -#endif - -void -grub_cpu_relocator_init (void) -{ - grub_relocator_forward_size = RELOCATOR_SIZEOF(_forward); - grub_relocator_backward_size = RELOCATOR_SIZEOF(_backward); -} - -void -grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) -{ - grub_uint8_t *ptr; - ptr = rels; -#ifdef __x86_64__ - /* movq imm64, %rax (for relocator) */ - *(grub_uint8_t *) ptr = 0x48; - ptr++; - *(grub_uint8_t *) ptr = 0xb8; - ptr++; - *(grub_uint64_t *) ptr = addr; - ptr += sizeof (grub_uint64_t); -#else - /* movl imm32, %eax (for relocator) */ - *(grub_uint8_t *) ptr = 0xb8; - ptr++; - *(grub_uint32_t *) ptr = addr; - ptr += sizeof (grub_uint32_t); -#endif - /* jmp $eax/$rax */ - *(grub_uint8_t *) ptr = 0xff; - ptr++; - *(grub_uint8_t *) ptr = 0xe0; - ptr++; -} - -void -grub_cpu_relocator_backward (void *ptr, void *src, void *dest, - grub_size_t size) -{ - grub_relocator_backward_dest = dest; - grub_relocator_backward_src = src; - grub_relocator_backward_chunk_size = size; - - grub_memmove (ptr, - &grub_relocator_backward_start, - RELOCATOR_SIZEOF (_backward)); -} - -void -grub_cpu_relocator_forward (void *ptr, void *src, void *dest, - grub_size_t size) -{ - grub_relocator_forward_dest = dest; - grub_relocator_forward_src = src; - grub_relocator_forward_chunk_size = size; - - grub_memmove (ptr, - &grub_relocator_forward_start, - RELOCATOR_SIZEOF (_forward)); -} - grub_err_t grub_relocator32_boot (struct grub_relocator *rel, struct grub_relocator32_state state, @@ -225,6 +144,7 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator16_ss = state.ss; grub_relocator16_sp = state.sp; + grub_relocator16_ebp = state.ebp; grub_relocator16_ebx = state.ebx; grub_relocator16_edx = state.edx; grub_relocator16_esi = state.esi; diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index e79d87551..c8d6f86d8 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -259,6 +259,11 @@ VARIABLE(grub_relocator16_edx) VARIABLE(grub_relocator16_ebx) .long 0 + /* movl imm32, %ebp. */ + .byte 0x66, 0xbd +VARIABLE(grub_relocator16_ebp) + .long 0 + /* Cleared direction flag is of no problem with any current payload and makes this implementation easier. */ cld diff --git a/grub-core/lib/i386/relocator_common.S b/grub-core/lib/i386/relocator_common.S index b9d99e10e..03f427a03 100644 --- a/grub-core/lib/i386/relocator_common.S +++ b/grub-core/lib/i386/relocator_common.S @@ -42,7 +42,9 @@ LOCAL(base): /* %rax contains now our new 'base'. */ mov RAX, RSI -#ifdef __APPLE__ +#if defined (__APPLE__) && defined (__x86_64__) + leaq LOCAL(cont0) (%rip), RAX +#elif defined (__APPLE__) LOCAL(cont0_offset) = LOCAL(cont0) - LOCAL(base) add $LOCAL(cont0_offset), RAX #else diff --git a/grub-core/lib/i386/relocator_common_c.c b/grub-core/lib/i386/relocator_common_c.c new file mode 100644 index 000000000..7be609b73 --- /dev/null +++ b/grub-core/lib/i386/relocator_common_c.c @@ -0,0 +1,109 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009-2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +#include +#include +#include + +#include +#include + +extern grub_uint8_t grub_relocator_forward_start; +extern grub_uint8_t grub_relocator_forward_end; +extern grub_uint8_t grub_relocator_backward_start; +extern grub_uint8_t grub_relocator_backward_end; + +extern void *grub_relocator_backward_dest; +extern void *grub_relocator_backward_src; +extern grub_size_t grub_relocator_backward_chunk_size; + +extern void *grub_relocator_forward_dest; +extern void *grub_relocator_forward_src; +extern grub_size_t grub_relocator_forward_chunk_size; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_size_t grub_relocator_align = 1; +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +#ifdef __x86_64__ +grub_size_t grub_relocator_jumper_size = 12; +#else +grub_size_t grub_relocator_jumper_size = 7; +#endif + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF (_forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF (_backward); +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + grub_uint8_t *ptr; + ptr = rels; +#ifdef __x86_64__ + /* movq imm64, %rax (for relocator) */ + *(grub_uint8_t *) ptr = 0x48; + ptr++; + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint64_t *) ptr = addr; + ptr += sizeof (grub_uint64_t); +#else + /* movl imm32, %eax (for relocator) */ + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint32_t *) ptr = addr; + ptr += sizeof (grub_uint32_t); +#endif + /* jmp $eax/$rax */ + *(grub_uint8_t *) ptr = 0xff; + ptr++; + *(grub_uint8_t *) ptr = 0xe0; + ptr++; +} + +void +grub_cpu_relocator_backward (void *ptr, void *src, void *dest, + grub_size_t size) +{ + grub_relocator_backward_dest = dest; + grub_relocator_backward_src = src; + grub_relocator_backward_chunk_size = size; + + grub_memmove (ptr, + &grub_relocator_backward_start, RELOCATOR_SIZEOF (_backward)); +} + +void +grub_cpu_relocator_forward (void *ptr, void *src, void *dest, + grub_size_t size) +{ + grub_relocator_forward_dest = dest; + grub_relocator_forward_src = src; + grub_relocator_forward_chunk_size = size; + + grub_memmove (ptr, + &grub_relocator_forward_start, RELOCATOR_SIZEOF (_forward)); +} diff --git a/grub-core/lib/i386/xen/relocator.S b/grub-core/lib/i386/xen/relocator.S new file mode 100644 index 000000000..a1677db9f --- /dev/null +++ b/grub-core/lib/i386/xen/relocator.S @@ -0,0 +1,146 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator_xen_remap_start) +LOCAL(base): + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator_xen_remapper_virt) + .long 0 + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator_xen_remapper_map) + .long 0 + + /* mov imm32, %edx */ + .byte 0xba +VARIABLE(grub_relocator_xen_remapper_map_high) + .long 0 + + movl $2, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + addl $(LOCAL(cont) - LOCAL(base)), %ebx + + jmp *%ebx + +LOCAL(cont): + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator_xen_paging_size) + .long 0 + + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator_xen_paging_start) + .long 0 + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_mfn_list) + .long 0 + + movl %eax, %edi +1: + movl %ecx, %ebp + movl 0(%edi), %ecx + movl %ecx, %edx + shll $12, %ecx + shrl $20, %edx + orl $5, %ecx + movl $2, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + movl %ebp, %ecx + addl $4, %edi + addl $4096, %ebx + + loop 1b + + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator_xen_mmu_op_addr) + .long 0 + movl $3, %ecx + movl $0, %edx + movl $0x7FF0, %esi + movl $__HYPERVISOR_mmuext_op, %eax + int $0x82 + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_remap_continue) + .long 0 + + jmp *%eax + +VARIABLE(grub_relocator_xen_mmu_op) + .space 256 + +VARIABLE(grub_relocator_xen_remap_end) + + +VARIABLE(grub_relocator_xen_start) + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_remapper_virt2) + .long 0 + + movl %eax, %edi + + xorl %ecx, %ecx + xorl %edx, %edx + + movl $2, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_stack) + .long 0 + + movl %eax, %esp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_start_info) + .long 0 + + movl %eax, %esi + + cld + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_entry_point) + .long 0 + + jmp *%eax + +VARIABLE(grub_relocator_xen_end) diff --git a/grub-core/lib/ia64/longjmp.S b/grub-core/lib/ia64/longjmp.S index 729bdc76e..38afb2243 100644 --- a/grub-core/lib/ia64/longjmp.S +++ b/grub-core/lib/ia64/longjmp.S @@ -40,10 +40,10 @@ /* __longjmp(__jmp_buf buf, int val) */ - .text - .global longjmp - .proc longjmp -longjmp: + .text + + .proc EXT_C(grub_longjmp) +FUNCTION(grub_longjmp) alloc r8=ar.pfs,2,1,0,0 mov r27=ar.rsc add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr @@ -159,4 +159,4 @@ longjmp: invala // virt. -> phys. regnum mapping may change mov pr=r24,-1 br.ret.dptk.few rp - .endp longjmp + .endp EXT_C(grub_longjmp) diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S index dc19be0ce..a0382d83d 100644 --- a/grub-core/lib/ia64/setjmp.S +++ b/grub-core/lib/ia64/setjmp.S @@ -74,13 +74,13 @@ GRUB_MOD_LICENSE "GPLv2+" /* The following two entry points are the traditional entry points: */ .text - .global setjmp - .proc setjmp -setjmp: + + .proc EXT_C(grub_setjmp) +FUNCTION(grub_setjmp) alloc r8=ar.pfs,2,0,0,0 mov in1=1 br.cond.sptk.many __sigsetjmp - .endp setjmp + .endp EXT_C(grub_setjmp) /* __sigsetjmp(__jmp_buf buf, int savemask) */ diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c index fa57db9e7..328d70a0c 100644 --- a/grub-core/lib/ieee1275/cmos.c +++ b/grub-core/lib/ieee1275/cmos.c @@ -23,51 +23,53 @@ #include volatile grub_uint8_t *grub_cmos_port = 0; + +/* Helper for grub_cmos_find_port. */ +static int +grub_cmos_find_port_iter (struct grub_ieee1275_devalias *alias) +{ + grub_ieee1275_phandle_t dev; + grub_uint32_t addr[2]; + grub_ssize_t actual; + /* Enough to check if it's "m5819" */ + char compat[100]; + if (grub_ieee1275_finddevice (alias->path, &dev)) + return 0; + if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), + 0)) + return 0; + if (grub_strcmp (compat, "m5819") != 0) + return 0; + if (grub_ieee1275_get_integer_property (dev, "address", + addr, sizeof (addr), &actual)) + return 0; + if (actual == 4) + { + grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; + return 1; + } + +#if GRUB_CPU_SIZEOF_VOID_P == 8 + if (actual == 8) + { + grub_cmos_port = (volatile grub_uint8_t *) + ((((grub_addr_t) addr[0]) << 32) | addr[1]); + return 1; + } +#else + if (actual == 8 && addr[0] == 0) + { + grub_cmos_port = (volatile grub_uint8_t *) addr[1]; + return 1; + } +#endif + return 0; +} + grub_err_t grub_cmos_find_port (void) { - auto int hook (struct grub_ieee1275_devalias *alias); - int hook (struct grub_ieee1275_devalias *alias) - { - grub_ieee1275_phandle_t dev; - grub_uint32_t addr[2]; - grub_ssize_t actual; - /* Enough to check if it's "m5819" */ - char compat[100]; - if (grub_ieee1275_finddevice (alias->path, &dev)) - return 0; - if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), - 0)) - return 0; - if (grub_strcmp (compat, "m5819") != 0) - return 0; - if (grub_ieee1275_get_integer_property (dev, "address", - addr, sizeof (addr), &actual)) - return 0; - if (actual == 4) - { - grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; - return 1; - } - -#if GRUB_CPU_SIZEOF_VOID_P == 8 - if (actual == 8) - { - grub_cmos_port = (volatile grub_uint8_t *) - ((((grub_addr_t) addr[0]) << 32) | addr[1]); - return 1; - } -#else - if (actual == 8 && addr[0] == 0) - { - grub_cmos_port = (volatile grub_uint8_t *) addr[1]; - return 1; - } -#endif - return 0; - } - - grub_ieee1275_devices_iterate (hook); + grub_ieee1275_devices_iterate (grub_cmos_find_port_iter); if (!grub_cmos_port) return grub_error (GRUB_ERR_IO, "no cmos found"); diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c index 1947135fe..74578f15a 100644 --- a/grub-core/lib/ieee1275/datetime.c +++ b/grub-core/lib/ieee1275/datetime.c @@ -30,22 +30,23 @@ GRUB_MOD_LICENSE ("GPLv3+"); static char *rtc = 0; static int no_ieee1275_rtc = 0; +/* Helper for find_rtc. */ +static int +find_rtc_iter (struct grub_ieee1275_devalias *alias) +{ + if (grub_strcmp (alias->type, "rtc") == 0) + { + grub_dprintf ("datetime", "Found RTC %s\n", alias->path); + rtc = grub_strdup (alias->path); + return 1; + } + return 0; +} + static void find_rtc (void) { - auto int hook (struct grub_ieee1275_devalias *alias); - int hook (struct grub_ieee1275_devalias *alias) - { - if (grub_strcmp (alias->type, "rtc") == 0) - { - grub_dprintf ("datetime", "Found RTC %s\n", alias->path); - rtc = grub_strdup (alias->path); - return 1; - } - return 0; - } - - grub_ieee1275_devices_iterate (hook); + grub_ieee1275_devices_iterate (find_rtc_iter); if (!rtc) no_ieee1275_rtc = 1; } @@ -89,7 +90,7 @@ grub_get_datetime (struct grub_datetime *datetime) grub_ieee1275_close (ihandle); - if (status == -1) + if (status == -1 || args.catch_result) return grub_error (GRUB_ERR_IO, "get-time failed"); datetime->year = args.year; @@ -148,7 +149,7 @@ grub_set_datetime (struct grub_datetime *datetime) grub_ieee1275_close (ihandle); - if (status == -1) + if (status == -1 || args.catch_result) return grub_error (GRUB_ERR_IO, "set-time failed"); return GRUB_ERR_NONE; diff --git a/grub-core/lib/ieee1275/halt.c b/grub-core/lib/ieee1275/halt.c index 7ede29de9..8fc16d243 100644 --- a/grub-core/lib/ieee1275/halt.c +++ b/grub-core/lib/ieee1275/halt.c @@ -25,8 +25,8 @@ grub_halt (void) { /* Not standardized. We try three known commands. */ - grub_ieee1275_interpret ("shut-down", 0); grub_ieee1275_interpret ("power-off", 0); + grub_ieee1275_interpret ("shut-down", 0); grub_ieee1275_interpret ("poweroff", 0); while (1); diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c index 021f0ce71..c6dd8facb 100644 --- a/grub-core/lib/ieee1275/relocator.c +++ b/grub-core/lib/ieee1275/relocator.c @@ -21,65 +21,81 @@ #include #include +/* Helper for grub_relocator_firmware_get_max_events. */ +static int +count (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t len __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused)), void *data) +{ + int *counter = data; + + (*counter)++; + return 0; +} + unsigned grub_relocator_firmware_get_max_events (void) { int counter = 0; - 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)) + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) return 0; - grub_machine_mmap_iterate (count); + grub_machine_mmap_iterate (count, &counter); return 2 * counter; } +/* Context for grub_relocator_firmware_fill_events. */ +struct grub_relocator_firmware_fill_events_ctx +{ + struct grub_relocator_mmap_event *events; + int counter; +}; + +/* Helper for grub_relocator_firmware_fill_events. */ +static int +grub_relocator_firmware_fill_events_iter (grub_uint64_t addr, + grub_uint64_t len, + grub_memory_type_t type, void *data) +{ + struct grub_relocator_firmware_fill_events_ctx *ctx = data; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) + return 0; + + if (addr < 0x180000) + { + len = addr + len - 0x180000; + addr = 0x180000; + } + } + + ctx->events[ctx->counter].type = REG_FIRMWARE_START; + ctx->events[ctx->counter].pos = addr; + ctx->counter++; + ctx->events[ctx->counter].type = REG_FIRMWARE_END; + ctx->events[ctx->counter].pos = addr + len; + ctx->counter++; + + return 0; +} + unsigned grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) { - 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++; + struct grub_relocator_firmware_fill_events_ctx ctx = { + .events = events, + .counter = 0 + }; + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) return 0; - } - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) - return 0; - grub_machine_mmap_iterate (fill); - return counter; + grub_machine_mmap_iterate (grub_relocator_firmware_fill_events_iter, &ctx); + return ctx.counter; } int diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 775eaad1f..300d8b961 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2010 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2010,2012 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -65,23 +65,27 @@ struct legacy_command */ static struct legacy_command legacy_commands[] = { + /* FIXME: background unsupported. */ {"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the blocklist notation of the file FILE."}, {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, "Boot the OS/chain-loader which has been loaded."}, - {"bootp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + {"bootp", "net_bootp; net_ls_addr; echo $\"" N_("Default server is ${net_default_server}") "\"; if [ x%s = x--with-configfile ]; then " "if net_get_dhcp_option configfile_name pxe 150 string; then " "configfile $configfile_name; fi; fi\n", NULL, 0, 1, {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", "Initialize a network device via BOOTP. If the option `--with-configfile'" " is given, try to load a configuration file specified by the 150 vendor" " tag."}, + /* FIXME: border unsupported. */ {"cat", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the contents of the file FILE."}, {"chainloader", "chainloader %s '%s'\n", NULL, 0, 2, {TYPE_FORCE_OPTION, TYPE_FILE}, 0, "[--force] FILE", "Load the chain-loader FILE. If --force is specified, then load it" " forcibly, whether the boot loader signature is present or not."}, + {"clear", "clear\n", NULL, 0, 0, {}, 0, 0, + "Clear the screen."}, {"cmp", "cmp '%s' '%s'\n", NULL, 0, 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, "FILE1 FILE2", "Compare the file FILE1 with the FILE2 and inform the different values" @@ -125,6 +129,7 @@ static struct legacy_command legacy_commands[] = {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed."}, + /* FIXME: device and efimap unsupported. */ /* NOTE: embed unsupported. */ {"fallback", "set fallback='%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "NUM...", @@ -136,6 +141,8 @@ static struct legacy_command legacy_commands[] = {"find", "search -f '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", "Search for the filename FILENAME in all of partitions and print the list of" " the devices which contain the file."}, + /* FIXME: findiso unsupported. */ + /* FIXME: foreground unsupported. */ /* FIXME: fstest unsupported. */ /* NOTE: The obsolete C/H/S geometry isn't shown anymore. */ {"geometry", "insmod regexp; ls -l (%s*)\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "DRIVE", @@ -243,6 +250,10 @@ static struct legacy_command legacy_commands[] = {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, + {"print", "echo %s\n", NULL, 0, 1, + {TYPE_REST_VERBATIM}, 0, + "[MESSAGE ...]", "Print MESSAGE."}, + /* FIXME: quit unsupported. */ /* FIXME: rarp unsupported. */ {"read", "read_dword %s\n", NULL, 0, 1, {TYPE_INT}, 0, "ADDR", "Read a 32-bit value from memory at address ADDR and" @@ -288,14 +299,18 @@ static struct legacy_command legacy_commands[] = " STOP is the length of stop bit(s). The option --device can be used only" " in the grub shell, which specifies the file name of a tty device. The" " default values are COM1, 9600, 8N1."}, + /* FIXME: shade unsupported. */ + /* FIXME: silent unsupported. */ + /* FIXME: splashimage unsupported. */ /* FIXME: setkey unsupported. */ /* NUL_TERMINATE */ /* NOTE: setup unsupported. */ - /* FIXME: --no-echo, --no-edit, hercules unsupported. */ + /* FIXME: --no-echo, --no-edit unsupported. */ /* NOTE: both terminals are activated so --silent and --timeout are useless. */ + /* FIXME: graphics unsupported. */ {"terminal", NULL, NULL, 0, 0, {}, FLAG_TERMINAL | FLAG_IGNORE_REST, "[--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] " - "[--silent] [console] [serial] [hercules]", + "[--silent] [console] [serial] [hercules] [graphics]", "Select a terminal. When multiple terminals are specified, wait until" " you push any key to continue. If both console and serial are specified," " the terminal to which you input a key first will be selected. If no" @@ -307,7 +322,7 @@ static struct legacy_command legacy_commands[] = " seconds. The option --lines specifies the maximum number of lines." " The option --silent is used to suppress messages."}, /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ - {"testload", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + {"testload", "testload '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Read the entire contents of FILE in several different ways and" " compares them, to test the filesystem code. " " If this test succeeds, then a good next" @@ -334,6 +349,9 @@ static struct legacy_command legacy_commands[] = " the information about only the mode."}, {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL} + /* FIXME: verbose unsupported. */ + /* FIXME: version unsupported. */ + /* FIXME: viewport unsupported. */ }; char * @@ -373,6 +391,29 @@ adjust_file (const char *in, grub_size_t len) if (*ptr == '\'' || *ptr == '\\') overhead++; comma = ptr; + if (*comma == ')' && comma - in == 3 + && in[1] == 'n' && in[2] == 'd') + { + rest = comma + 1; + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + ret = grub_malloc (ptr - in + overhead + 15); + if (!ret) + return NULL; + + outptr = grub_stpcpy (ret, "(tftp)");; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr = 0; + return ret; + } if (*comma != ',') return grub_legacy_escape (in, len); part = grub_strtoull (comma + 1, (char **) &rest, 0); @@ -386,7 +427,7 @@ adjust_file (const char *in, grub_size_t len) overhead++; /* 35 is enough for any 2 numbers. */ - ret = grub_malloc (ptr - in + overhead + 35); + ret = grub_malloc (ptr - in + overhead + 35 + 5); if (!ret) return NULL; @@ -507,11 +548,11 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) int dumb = 0, lines = 24; #ifdef TODO int no_echo = 0, no_edit = 0; - int hercules = 0; #endif - int console = 0, serial = 0; + int hercules = 0; + int console = 0, serial = 0, graphics = 0; /* Big enough for any possible resulting command. */ - char outbuf[256] = ""; + char outbuf[512] = ""; char *outptr; while (*ptr) { @@ -541,45 +582,40 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) serial = 1; -#ifdef TODO if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) hercules = 1; -#endif + if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) + graphics = 1; while (*ptr && !grub_isspace (*ptr)) ptr++; while (*ptr && grub_isspace (*ptr)) ptr++; } - if (!console && !serial) + if (!console && !serial && !hercules && !graphics) return grub_strdup ("terminal_input; terminal_output; terminfo\n"); - grub_strcpy (outbuf, "terminal_input "); - outptr = outbuf + grub_strlen (outbuf); + outptr = outbuf; + + if (graphics) + outptr = grub_stpcpy (outptr, "insmod all_video; "); + + outptr = grub_stpcpy (outptr, "terminal_input "); if (serial) - { - grub_strcpy (outptr, "serial "); - outptr += grub_strlen (outptr); - } - if (console) - { - grub_strcpy (outptr, "console "); - outptr += grub_strlen (outptr); - } - grub_strcpy (outptr, "; terminal_output "); - outptr += grub_strlen (outptr); + outptr = grub_stpcpy (outptr, "serial "); + if (console || hercules || graphics) + outptr = grub_stpcpy (outptr, "console "); + outptr = grub_stpcpy (outptr, "; terminal_output "); if (serial) - { - grub_strcpy (outptr, "serial "); - outptr += grub_strlen (outptr); - } + outptr = grub_stpcpy (outptr, "serial "); if (console) - { - grub_strcpy (outptr, "console "); - outptr += grub_strlen (outptr); - } - grub_strcpy (outptr, "; "); - outptr += grub_strlen (outptr); + outptr = grub_stpcpy (outptr, "console "); + if (hercules) + outptr = grub_stpcpy (outptr, "mda_text "); + if (graphics) + outptr = grub_stpcpy (outptr, "gfxterm "); + outptr = grub_stpcpy (outptr, "; "); + *outptr = '\0'; if (serial) { grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog b/grub-core/lib/libgcrypt/cipher/ChangeLog index 8924f17e1..1b3694f58 100644 --- a/grub-core/lib/libgcrypt/cipher/ChangeLog +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog @@ -1,3 +1,93 @@ +2010-08-19 Werner Koch + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards (wk) + + Spelling fixes. + +2010-03-26 Werner Koch + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + 2009-01-22 Werner Koch * ecc.c (compute_keygrip): Remove superfluous const. @@ -3888,8 +3978,8 @@ Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) (digest_algo_to_string): New. - Copyright 1998,1999,2000,2001,2002,2003,2004,2005,2006 - 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 b/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 new file mode 100644 index 000000000..05516c99e --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 @@ -0,0 +1,4247 @@ +2011-12-01 Werner Koch + + NB: ChangeLog files are no longer manually maintained. Starting + on December 1st, 2011 we put change information only in the GIT + commit log, and generate a top-level ChangeLog file from logs at + "make dist". See doc/HACKING for details. + +2011-06-29 Werner Koch + + * cipher.c (cipher_get_keylen): Return zero for an invalid algorithm. + (cipher_get_blocksize): Ditto. + +2011-06-13 Werner Koch + + * dsa.c (selftest_sign_1024): Use the raw and not the pkcs1 flag. + + * pubkey.c (gcry_pk_sign): Special case output generation for PKCS1. + (sexp_data_to_mpi): Parse "random-override" for pkcs1 encryption. + (pkcs1_encode_for_encryption): Add args RANDOM_OVERRIDE and + RANDOM_OVERRIDE_LEN. + (gcry_pk_encrypt): Special case output generation for PKCS1. + (sexp_data_to_mpi): Use GCRYMPI_FMT_USG for raw encoding. + +2011-06-10 Werner Koch + + * pubkey.c (gcry_pk_sign): Use format specifier '%M' to avoid + leading zeroes. Special case output generation for PSS. + (gcry_pk_encrypt): Special case output generation for OAEP. + (sexp_data_to_mpi): Use GCRYMPI_FMT_USG for PSS verify. + +2011-06-09 Werner Koch + + * pubkey.c (oaep_decode): Make use of octet_string_from_mpi. + (sexp_to_enc): Skip "random-override". + + * pubkey.c (oaep_encode, pss_encode): Add args RANDOM_OVERRIDE and + RANDOM_OVERRIDE_LEN. + (sexp_data_to_mpi): Extract new random-override parameter. + + * pubkey.c (pss_encode, pss_verify): Use VALUE verbatim for MHASH. + (octet_string_from_mpi): Add arg SPACE. + +2011-06-08 Werner Koch + + * pubkey.c (pss_encode, pss_verify): Restructure and comment code + to match rfc-3447. Replace secure allocs by plain allocs and + wipememory. Use gcry_md_hash_buffer. + (octet_string_from_mpi): New. + +2011-06-03 Werner Koch + + * pubkey.c (oaep_decode): Add more comments and restructure to + match the description in RFC-3447. + (oaep_encode): Check for mgf1 error. s/dlen/hlen/. + +2011-05-31 Werner Koch + + * pubkey.c (mgf1): Optimize by using gcry_md_reset. Re-implement + for easier readability. + (oaep_encode): Add more comments and restructure to match the + description in RFC-3447. + + * pubkey.c (pkcs1_encode_for_signature, oaep_decode): Change + return value from one MPI to a buffer. + (gcry_pk_decrypt): Adjust for this change. + +2011-05-30 Werner Koch + + * pubkey.c (pkcs1_decode_for_encryption): Change handling of + leading zero byte. + +2011-05-27 Daiki Ueno + + * pubkey.c (gcry_pk_decrypt): Fix double-free when un-padding + invalid data. Thanks to Tom Ritter. + +2011-05-24 Daiki Ueno + + * rsa.c (rsa_verify): Use CMP if given, to check the decrypted + sig. + + * pubkey.c (sexp_to_enc, sexp_data_to_mpi): Factor out + CTX initialization to ... + (init_encoding_ctx): .. new. + (gcry_pk_verify): Pass verify func and the arg to pubkey_verify. + (pss_encode, pss_verify, pss_verify_cmp): New. + +2011-05-23 Daiki Ueno + + * pubkey.c (pkcs1_decode_for_encryption, oaep_decode): Fix memleak + when gcry_mpi_print fails. + +2011-05-18 Daiki Ueno + + * pubkey.c (sexp_data_to_mpi): Factor some code out to ... + (pkcs1_encode_for_encryption): .. new, + (pkcs1_encode_for_signature): .. new. + (pkcs1_decode_for_encryption): New. + (gcry_pk_decrypt): Do un-padding for PKCS#1 as well as OAEP. + (sexp_to_enc): Abolish "unpad" flag, which is not necessary since + we can do un-padding implicitly when "pkcs1" or "oaep" is given. + +2011-05-11 Werner Koch + + * pubkey.c (sexp_to_enc, sexp_data_to_mpi): Set LABEL to NULL + after free. + (sexp_to_enc, sexp_data_to_mpi): Do not allow multiple encoding + flags. + (oaep_encode, oaep_decode, sexp_to_key, sexp_to_sig) + (sexp_to_enc, sexp_data_to_mpi, gcry_pk_encrypt, gcry_pk_sign) + (gcry_pk_genkey, _gcry_pk_get_elements): Replace access to ERRNO + by gpg_err_code_from_syserror. + +2011-05-11 Daiki Ueno + + * pubkey.c (sexp_data_to_mpi): Factor some code out to ... + (get_hash_algo): .. new. + (mgf1, oaep_encode, oaep_decode): New. + (sexp_to_enc): Add arg CTX. Remove arg RET_WANT_PKCS1. Support + OAEP. + (sexp_data_to_mpi): Add arg CTX. Support OAEP. + (gcry_pk_encrypt): Pass a CTX to sexp_data_to_mpi. + (gcry_pk_decrypt): Pass a CTX tp sexp_to_enc and replace + WANT_PKCS1. Implement unpadding for OAEP. + (gcry_pk_sign): Pass NULL for CTX arg of sexp_data_to_mpi. + (gcry_pk_verify): Ditto. + +2011-04-19 Werner Koch + + * cipher.c (gcry_cipher_open): Replace gpg_err_code_from_errno by + gpg_err_code_from_syserror. + +2011-04-11 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Avoid double free of L2. + + * cipher.c (_gcry_cipher_setctr): Clear unused lastiv info. + (gcry_cipher_ctl) : Implement by calling + _gcry_cipher_setctr. + (do_ctr_encrypt): Save last counter and reuse it. + + * cipher.c (do_ctr_encrypt): Allow arbitrary length inputs to + match the 1.4 behaviour. + +2011-04-04 Werner Koch + + * ecc.c (compute_keygrip): Release L1 while parsing "curve". + + * pubkey.c (gcry_pk_get_keygrip): Always release NAME and L2. + Reported by Ben Kibbey. + +2011-03-28 Werner Koch + + * primegen.c (_gcry_generate_elg_prime): Make sure that PRIME is + NULL if the called func ever returns an error. + + * pubkey.c (gcry_pk_decrypt): Remove unused var PUBKEY. + +2011-03-09 Werner Koch + + * kdf.c: New. + +2011-02-22 Werner Koch + + * rijndael.c (aesni_cleanup_2_4): New. + (aesenc_xmm1_xmm0, do_aesni_ctr_4): New. + (_gcry_aes_ctr_enc): New. + * cipher.c (struct gcry_cipher_handle): Add CTR_ENC. Move field + CTR into an u_ctr union and adjust all users. + (gcry_cipher_open): Use _gcry_aes_ctr_enc. + (do_ctr_encrypt): Use bulk mode. + +2011-02-18 Werner Koch + + * rijndael.c (u32_a_t): New. + (do_encrypt_aligned, do_encrypt_aligned): Use the new type to + avoid problems with strict aliasing rules. + +2011-02-16 Werner Koch + + * rijndael.c (do_aesni_cfb) [USE_AESNI]: New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec) [USE_AESNI]: Use new fucntion. + +2011-02-15 Werner Koch + + * rijndael.c (do_aesni_enc_aligned, do_aesni_dec_aligned): Use + movdqa for the key but keep using movdqu for the data. + (do_aesni): Remove alignment detection. Don't burn the stack. + (aesni_prepare, aesni_cleanup): New macros. + (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (rijndael_decrypt, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use + these macros. Don't burn the stack in the USE_AESNI case. + (do_setkey): Add disabled code to use aeskeygenassist. + +2011-02-14 Werner Koch + + * rijndael.c (ATTR_ALIGNED_16): New + (do_aesni): Do not copy if already aligned. + (do_encrypt, do_decrypt): Ditto. + (rijndael_decrypt, rijndael_encrypt): Increase stack burning amount. + + * rijndael.c (RIJNDAEL_context): Reorder fields. Change fieldname + ROUNDS to rounds. Move padlock_key into u1. + (keySched, keySched2): Rename macros to keyscherr and keyschdec + and change all users. + (padlockkey): New macro. Change all users of padlock_key. + * cipher.c (NEED_16BYTE_ALIGNED_CONTEXT): Always define if using gcc. + (struct gcry_cipher_handle): Align U_IV to at least 16 byte. + +2011-02-13 Werner Koch + + * rijndael.c (USE_AESNI): New. Define for ia32 and gcc >= 4. + (m128i_t) [USE_AESNI]: New. + (RIJNDAEL_context) [USE_AESNI]: Add field use_aesni. + (do_setkey): Set USE_AESNI for all key lengths. + (prepare_decryption) [USE_AESNI]: Use aesimc instn if requested. + (do_aesni_enc_aligned, do_aesni_dec_aligned) + (do_aesni) [USE_AESNI]: New. + (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (rijndael_decrypt, _gcry_aes_cfb_dec) + (_gcry_aes_cbc_dec) [USE_AESNI]: Use do_aesni. + +2011-02-01 Werner Koch + + * pubkey.c (gcry_pk_get_curve): New. + (sexp_to_key): Add arg OVERRIDE_ELEMS. + (sexp_elements_extract_ecc): Allow for params only. + (gcry_pk_get_param): New. + * ecc.c (ecc_get_curve): New. + (ecc_get_param_sexp): New. + +2011-01-28 Werner Koch + + * pubkey.c (gcry_pk_genkey): Hack to insert the used curve name. + +2011-01-27 Werner Koch + + * ecc.c (fill_in_curve): Remove. + (generate_curve): Rename to .. + (fill_in_curve): this. Remove setting of NAME_OID. + (ecc_encrypt_raw): Change name of arg DATA to K for better + readability. Use ECC_public_key instead of ECC_secret_key. + Require a caller to pass a complete pkey array. + (ecc_decrypt_raw): Require a caller to pass a complete skey array. + (elliptic_curve_t): Add field NAME. + (fill_in_curve): Set field. + (generate_key): Add arg R_USED_CURVE. + (ecc_generate_ext): Return used curve name. + +2011-01-13 Andrey Jivsov (wk) + + * ecc.c (ec2os): Do not free passed parameters X and Y. Adjust + callers. + (ecc_encrypt_raw, ecc_decrypt_raw): New. + (ecdh_names, _gcry_pubkey_spec_ecdh): New. + * pubkey.c (pubkey_table): Support ECDH. + +2010-08-19 Werner Koch + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards (wk) + + Spelling fixes. + +2010-03-26 Werner Koch + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + +2009-01-22 Werner Koch + + * ecc.c (compute_keygrip): Remove superfluous const. + +2009-01-06 Werner Koch + + * rmd160.c (oid_spec_rmd160): Add TeleTrust identifier. + +2008-12-10 Werner Koch + + * dsa.c (generate): Add arg DOMAIN and use it if specified. + (generate_fips186): Ditto. + (dsa_generate_ext): Parse and check the optional "domain" + parameter and pass them to the generate functions. + + * rijndael.c (rijndael_names): Add "AES128" and "AES-128". + (rijndael192_names): Add "AES-192". + (rijndael256_names): Add "AES-256". + +2008-12-05 Werner Koch + + * dsa.c (generate): Add arg TRANSIENT_KEY and use it to detrmine + the RNG quality needed. + (dsa_generate_ext): Parse the transient-key flag und pass it to + generate. + +2008-11-28 Werner Koch + + * dsa.c (generate_fips186): Add arg DERIVEPARMS and use the seed + value if available. + + * primegen.c (_gcry_generate_fips186_2_prime): Fix inner p loop. + +2008-11-26 Werner Koch + + * primegen.c (_gcry_generate_fips186_3_prime): New. + * dsa.c (generate_fips186): Add arg USE_FIPS186_2. + (dsa_generate_ext): Parse new flag use-fips183-2. + +2008-11-25 Werner Koch + + * dsa.c (generate_fips186): New. + (dsa_generate_ext): Use new function if derive-parms are given or + if in FIPS mode. + * primegen.c (_gcry_generate_fips186_2_prime): New. + +2008-11-24 Werner Koch + + * pubkey.c (gcry_pk_genkey): Insert code to output extrainfo. + (pubkey_generate): Add arg R_EXTRAINFO and pass it to the extended + key generation function. + * rsa.c (gen_x931_parm_xp, gen_x931_parm_xi): New. + (generate_x931): Generate params if not given. + (rsa_generate_ext): Parse use-x931 flag. Return p-q-swapped + indicator. + * dsa.c (dsa_generate_ext): Put RETFACTORS into R_EXTRAINFO if + possible. + + * pubkey.c (gcry_pk_genkey): Remove parsing of almost all + parameters and pass the parameter S-expression to pubkey_generate. + (pubkey_generate): Simplify by requitring modules to parse the + parameters. Remove the special cases for Elgamal and ECC. + (sexp_elements_extract_ecc): Add arg EXTRASPEC and use it. Fix + small memory leak. + (sexp_to_key): Pass EXTRASPEC to sexp_elements_extract_ecc. + (pubkey_table) [USE_ELGAMAL]: Add real extraspec. + * rsa.c (rsa_generate_ext): Adjust for new calling convention. + * dsa.c (dsa_generate_ext): Ditto. + * elgamal.c (_gcry_elg_generate): Ditto. Rename to elg_generate_ext. + (elg_generate): New. + (_gcry_elg_generate_using_x): Remove after merging code with + elg_generate_ext. + (_gcry_pubkey_extraspec_elg): New. + (_gcry_elg_check_secret_key, _gcry_elg_encrypt, _gcry_elg_sign) + (_gcry_elg_verify, _gcry_elg_get_nbits): Make static and remove + _gcry_ prefix. + * ecc.c (_gcry_ecc_generate): Rename to ecc_generate_ext and + adjust for new calling convention. + (_gcry_ecc_get_param): Rename to ecc_get_param and make static. + (_gcry_pubkey_extraspec_ecdsa): Add ecc_generate_ext and + ecc_get_param. + +2008-11-20 Werner Koch + + * pubkey.c (pubkey_generate): Add arg DERIVEPARMS. + (gcry_pk_genkey): Parse derive-parms and pass it to above. + * rsa.c (generate_x931): New. + (rsa_generate_ext): Add arg DERIVEPARMS and call new function in + fips mode or if DERIVEPARMS is given. + * primegen.c (_gcry_derive_x931_prime, find_x931_prime): New. + +2008-11-19 Werner Koch + + * rsa.c (rsa_decrypt): Use gcry_create_nonce for blinding. + (generate): Rename to generate_std. + +2008-11-05 Werner Koch + + * md.c (md_open): Use a switch to set the Bsize. + (prepare_macpads): Fix long key case for SHA384 and SHA512. + + * cipher.c (gcry_cipher_handle): Add field EXTRASPEC. + (gcry_cipher_open): Set it. + (gcry_cipher_ctl): Add private control code to disable weak key + detection and to return the current input block. + * des.c (_tripledes_ctx): Add field FLAGS. + (do_tripledes_set_extra_info): New. + (_gcry_cipher_extraspec_tripledes): Add new function. + (do_tripledes_setkey): Disable weak key detection. + +2008-10-24 Werner Koch + + * md.c (digest_table): Allow MD5 in fips mode. + (md_register_default): Take special action for MD5. + (md_enable, gcry_md_hash_buffer): Ditto. + +2008-09-30 Werner Koch + + * rijndael.c (do_setkey): Properly align "t" and "tk". + (prepare_decryption): Properly align "w". Fixes bug #936. + +2008-09-18 Werner Koch + + * pubkey.c (gcry_pk_genkey): Parse domain parameter. + (pubkey_generate): Add new arg DOMAIN and remove special case for + DSA with qbits. + * rsa.c (rsa_generate): Add dummy args QBITS, NAME and DOMAIN and + rename to rsa_generate_ext. Change caller. + (_gcry_rsa_generate, _gcry_rsa_check_secret_key) + (_gcry_rsa_encrypt, _gcry_rsa_decrypt, _gcry_rsa_sign) + (_gcry_rsa_verify, _gcry_rsa_get_nbits): Make static and remove + _gcry_ prefix. + (_gcry_pubkey_spec_rsa, _gcry_pubkey_extraspec_rsa): Adjust names. + * dsa.c (dsa_generate_ext): New. + (_gcry_dsa_generate): Replace code by a call to dsa_generate. + (_gcry_dsa_check_secret_key, _gcry_dsa_sign, _gcry_dsa_verify) + (_gcry_dsa_get_nbits): Make static and remove _gcry prefix. + (_gcry_dsa_generate2): Remove. + (_gcry_pubkey_spec_dsa): Adjust to name changes. + (_gcry_pubkey_extraspec_rsa): Add dsa_generate_ext. + +2008-09-16 Werner Koch + + * ecc.c (run_selftests): Add arg EXTENDED. + +2008-09-12 Werner Koch + + * rsa.c (test_keys): Do a bad case signature check. + * dsa.c (test_keys): Do a bad case check. + + * cipher.c (_gcry_cipher_selftest): Add arg EXTENDED and pass it + to the called tests. + * md.c (_gcry_md_selftest): Ditto. + * pubkey.c (_gcry_pk_selftest): Ditto. + * rijndael.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftest_fips_128): Add arg EXTENDED and run only one test + non-extended mode. + (selftest_fips_192): Add dummy arg EXTENDED. + (selftest_fips_256): Ditto. + * hmac-tests.c (_gcry_hmac_selftest): Ditto. + (run_selftests): Ditto. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha224, selftests_sha256): Ditto. + (selftests_sha384, selftests_sha512): Ditto. + * sha1.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + * sha256.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha224): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha256): Ditto. + * sha512.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha384): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha512): Ditto. + * des.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftest_fips): Add dummy arg EXTENDED. + * rsa.c (run_selftests): Add dummy arg EXTENDED. + + * dsa.c (run_selftests): Add dummy arg EXTENDED. + + * rsa.c (extract_a_from_sexp): New. + (selftest_encr_1024): Check that the ciphertext does not match the + plaintext. + (test_keys): Improve tests and return an error status. + (generate): Return an error if test_keys fails. + * dsa.c (test_keys): Add comments and return an error status. + (generate): Return an error if test_keys failed. + +2008-09-11 Werner Koch + + * rsa.c (_gcry_rsa_decrypt): Return an error instead of calling + BUG in case of a practically impossible condition. + (sample_secret_key, sample_public_key): New. + (selftest_sign_1024, selftest_encr_1024): New. + (selftests_rsa): Implement tests. + * dsa.c (sample_secret_key, sample_public_key): New. + (selftest_sign_1024): New. + (selftests_dsa): Implement tests. + +2008-09-09 Werner Koch + + * hmac-tests.c (selftests_sha1): Add tests. + (selftests_sha224, selftests_sha384, selftests_sha512): Make up tests. + + * hash-common.c, hash-common.h: New. + * sha1.c (selftests_sha1): Add 3 tests. + * sha256.c (selftests_sha256, selftests_sha224): Ditto. + * sha512.c (selftests_sha512, selftests_sha384): Ditto. + +2008-08-29 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Remove the special case for RSA + and check whether a custom computation function has been setup. + * rsa.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_rsa): Setup this function. + * ecc.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_ecdsa): Setup this function. + +2008-08-28 Werner Koch + + * cipher.c (cipher_decrypt, cipher_encrypt): Return an error if + mode NONE is used. + (gcry_cipher_open): Allow mode NONE only with a debug flag set and + if not in FIPS mode. + +2008-08-26 Werner Koch + + * pubkey.c (pubkey_generate): Add arg KEYGEN_FLAGS. + (gcry_pk_genkey): Implement new parameter "transient-key" and + pass it as flags to pubkey_generate. + (pubkey_generate): Make use of an ext_generate function. + * rsa.c (generate): Add new arg transient_key and pass appropriate + args to the prime generator. + (_gcry_rsa_generate): Factor all code out to ... + (rsa_generate): .. new func with extra arg KEYGEN_FLAGS. + (_gcry_pubkey_extraspec_ecdsa): Setup rsa_generate. + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Add new arg RANDOM_LEVEL. + +2008-08-21 Werner Koch + + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Use a constant macro for the random + level. + +2008-08-19 Werner Koch + + * pubkey.c (sexp_elements_extract_ecc) [!USE_ECC]: Do not allow + allow "curve" parameter. + +2008-08-15 Werner Koch + + * pubkey.c (_gcry_pk_selftest): New. + * dsa.c (selftests_dsa, run_selftests): New. + * rsa.c (selftests_rsa, run_selftests): New. + * ecc.c (selftests_ecdsa, run_selftests): New. + + * md.c (_gcry_md_selftest): New. + * sha1.c (run_selftests, selftests_sha1): New. + * sha256.c (selftests_sha224, selftests_sha256, run_selftests): New. + * sha512.c (selftests_sha384, selftests_sha512, run_selftests): New. + + * des.c (selftest): Remove static variable form selftest. + (des_setkey): No on-the-fly self test in fips mode. + (tripledes_set3keys): Ditto. + + * cipher.c (_gcry_cipher_setkey, _gcry_cipher_setiv): + + * dsa.c (generate): Bail out in fips mode if NBITS is less than 1024. + * rsa.c (generate): Return an error code if the the requested size + is less than 1024 and we are in fpis mode. + (_gcry_rsa_generate): Take care of that error code. + + * ecc.c (generate_curve): In fips mode enable only NIST curves. + + * cipher.c (_gcry_cipher_selftest): New. + + * sha512.c (_gcry_digest_extraspec_sha384) + (_gcry_digest_extraspec_sha512): New. + * sha256.c (_gcry_digest_extraspec_sha224) + (_gcry_digest_extraspec_sha256): New. + * sha1.c (_gcry_digest_extraspec_sha1): New. + * ecc.c (_gcry_pubkey_extraspec_ecdsa): New. + * dsa.c (_gcry_pubkey_extraspec_dsa): New. + * rsa.c (_gcry_pubkey_extraspec_rsa): New. + * rijndael.c (_gcry_cipher_extraspec_aes) + (_gcry_cipher_extraspec_aes192, _gcry_cipher_extraspec_aes256): New. + * des.c (_gcry_cipher_extraspec_tripledes): New. + + * cipher.c (gcry_cipher_register): Rename to _gcry_cipher_register. + Add arg EXTRASPEC. + (dummy_extra_spec): New. + (cipher_table_entry): Add extraspec field. + * md.c (_gcry_md_register): Rename to _gcry_md_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (digest_table_entry): Add extraspec field. + * pubkey.c (gcry_pk_register): Rename to _gcry_pk_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (pubkey_table_entry): Add extraspec field. + + * ac.c: Let most public functions return GPG_ERR_UNSUPPORTED in + fips mode. + + * pubkey.c (pubkey_table_entry): Add field FIPS_ALLOWED and mark + appropriate algorithms. + (dummy_generate, dummy_check_secret_key, dummy_encrypt) + (dummy_decrypt, dummy_sign, dummy_verify, dummy_get_nbits): Signal + a fips error when used. + (gcry_pk_register): In fips mode do not allow to register new + algorithms. + + * md.c (digest_table): Add field FIPS_ALLOWED and mark appropriate + algorithms. + (md_register_default): In fips mode register only fips algorithms. + (gcry_md_register): In fips mode do not allow to register new + algorithms. + (gcry_md_get): Signal a fips error if called. + (gcry_md_hash_buffer): Do not allow rmd160 when not in fips mode. + (md_start_debug): Disable in fips_mode. + + * md.c (gcry_md_register_default): Rename to .. + (md_register_default): .. this. + (md_digest): Remove this commented fucntion. + * pubkey.c (gcry_pk_register_default): Rename to .. + (pk_register_default): .. this. + + * cipher.c (cipher_table_entry): Add field FIPS_ALLOWED. + (gcry_cipher_register_default): Register only fips approved + algorithms. + (gcry_cipher_register): Do not allow to register new ciphers. + (cipher_setiv): Signal fips error. + + * cipher (gcry_cipher_register_default): Rename to .. + (cipher_register_default): .. this. + (REGISTER_DEFAULT_CIPHERS): Adjust for that change. + +2008-07-05 Werner Koch + + * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h + * random.c, rndegd.c, rndlinux.c, rndw32.c: Move to ../cipher. + * Makefile.am: Remove random stuff. + +2008-06-24 Szakats Istvan (wk) + + * ac.c (_gcry_ac_key_destroy, _gcry_ac_key_pair_generate): Relase + some more memory. + +2008-04-22 Werner Koch + + * rijndael.c (_gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (_gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use Padlock if possible. + +2008-04-18 Werner Koch + + * sha1.c (transform_aligned): Remove. That is will obviosuly not + work because we need a scratch working area and our internal API + does not allow to modify the buffers. + + * rijndael.c: Factor tables out to .. + * rijndael-tables.h: .. new. + + * ac.c (ac_data_extract): Make static. + + * camellia.h [HAVE_CONFIG_H]: Include config.h. + + * rndw32.c (registry_poll): Only print the performance data + problem warning once. Suggested by Simon Josefsson. + +2008-03-19 Werner Koch + + * cipher.c (gcry_cipher_open) [USE_AES]: Init bulk encryption only + if requested. Suggested by Dirk Stoecker. + +2008-03-18 Werner Koch + + * sha1.c: Include stdint.h. + (transform): Add arg NBLOCKS so that we can work on more than one + block and avoid updates of the chaining variables. Changed all + callers to use 1. + (sha1_write): Replace loop around transform. + (transform_aligned) [WORDS_BIGENDIAN]: New. + (TRANSFORM): New macro to replace all direct calls of transform. + +2008-03-17 Werner Koch + + * rijndael.c (_gcry_aes_cfb_dec): New. + (do_encrypt): Factor code out to .. + (do_encrypt_aligned): .. New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec): Use new function. + (do_decrypt): Factor code out to .. + (do_decrypt_aligned): .. new. + (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec): New. + * cipher.c (struct gcry_cipher_handle): Put field IV into new + union U_IV to enforce proper alignment. Change all users. + (do_cfb_decrypt): Optimize. + (do_cbc_encrypt, do_cbc_decrypt): Optimize. + +2008-03-15 Werner Koch + + * rijndael.c (_gcry_aes_cfb_enc): New. + * cipher.c (struct gcry_cipher_handle): Add field ALGO and BULK. + (gcry_cipher_open): Set ALGO and BULK. + (do_cfb_encrypt): Optimize. + +2008-02-18 Werner Koch + + * rsa.c (_gcry_rsa_verify) [IS_DEVELOPMENT_VERSION]: Print + intermediate results. + +2008-01-08 Werner Koch + + * random.c (add_randomness): Do not just increment + POOL_FILLED_COUNTER but update it by the actual amount of data. + +2007-12-13 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Support SHA-224. + +2007-12-05 Werner Koch + + * rijndael.c (USE_PADLOCK): Depend on ENABLE_PADLOCK_SUPPORT. + * rndhw.c (USE_PADLOCK): Ditto + + * rsa.c (secret): Fixed condition test for using CRT. Reported by + Dean Scarff. Fixes bug#864. + (_gcry_rsa_check_secret_key): Return an erro if the optional + parameters are missing. + * pubkey.c (sexp_elements_extract): Add arg ALGO_NAME. Changed all + callers to pass NULL. Add hack to allow for optional RSA + parameters. + (sexp_to_key): Pass algo name to sexp_elements_extract. + +2007-12-03 Werner Koch + + * random.c (gcry_random_add_bytes): Implement it. + * rand-internal.h (RANDOM_ORIGIN_EXTERNAL): New. + +2007-11-30 Werner Koch + + * rndhw.c: New. + * rndlinux.c (_gcry_rndlinux_gather_random): Try to read 50% + directly from the hwrng. + * random.c (do_fast_random_poll): Also run the hw rng fast poll. + (_gcry_random_dump_stats): Tell whether the hw rng failed. + +2007-11-29 Werner Koch + + * rijndael.c (USE_PADLOCK): Define new macro used for ia32. + (RIJNDAEL_context) [USE_PADLOCK]: Add fields USE_PADLOCK and + PADLOCK_KEY. + (do_setkey) [USE_PADLOCK]: Enable padlock if available for 128 bit + AES. + (do_padlock) [USE_PADLOCK]: New. + (rijndael_encrypt, rijndael_decrypt) [USE_PADLOCK]: Divert to + do_padlock. + * cipher.c (cipher_context_alignment_t): New. Use it in this + module in place of PROPERLY_ALIGNED_TYPE. + (NEED_16BYTE_ALIGNED_CONTEXT): Define macro for ia32. + (struct gcry_cipher_handle): Add field HANDLE_OFFSET. + (gcry_cipher_open): Take care of increased alignment requirements. + (gcry_cipher_close): Ditto. + +2007-11-28 Werner Koch + + * sha256.c (asn224): Fixed wrong template. It happened due to a + bug in RFC4880. SHA-224 is not in the stable version of libgcrypt + so the consequences are limited to users of this devel version. + +2007-10-31 Werner Koch + + * ac.c (gcry_ac_data_new): Remove due to the visibility wrapper. + (gcry_ac_data_destroy, gcry_ac_data_copy, gcry_ac_data_length) + (gcry_ac_data_set, gcry_ac_data_get_name, gcry_ac_data_get_index) + (gcry_ac_data_to_sexp, gcry_ac_data_from_sexp) + (gcry_ac_data_clear, gcry_ac_io_init, gcry_ac_open) + (gcry_ac_close, gcry_ac_key_init, gcry_ac_key_pair_generate) + (gcry_ac_key_pair_extract, gcry_ac_key_destroy) + (gcry_ac_key_pair_destroy, gcry_ac_key_data_get) + (gcry_ac_key_test, gcry_ac_key_get_nbits, gcry_ac_key_get_grip) + (gcry_ac_data_encrypt, gcry_ac_data_decrypt, gcry_ac_data_sign) + (gcry_ac_data_verify, gcry_ac_data_encode, gcry_ac_data_decode) + (gcry_ac_mpi_to_os, gcry_ac_mpi_to_os_alloc, gcry_ac_os_to_mpi) + (gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme) + (gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme) + (gcry_ac_io_init_va): Ditto. + (gcry_ac_id_to_name, gcry_ac_name_to_id): Remove as these + deprecated functions are now implemented by visibility.c. + +2007-10-26 Werner Koch + + * rndw32.c: Disable debug flag. + +2007-10-25 Werner Koch + + * rndw32.c: Updated from current cryptlib snapshot and modified + for our use. Removed support from pre NT systems. + (slow_gatherer_windows95): Remove. + (_gcry_rndw32_gather_random): Require an NT platform. + (init_system_rng, read_system_rng, read_mbm_data): New. + (slow_gatherer_windowsNT): Rename to ... + (slow_gatherer): .. this. Read system RNG and MBM. + (registry_poll): New with code factored out from slow_gatherer. + +2007-08-23 Werner Koch + + * random.c (pool_filled_counter): New. + (add_randomness): Use it. + +2007-08-22 Werner Koch + + * rndw32.c, rndunix.c: Switched to LGPL. + +2007-05-30 Werner Koch + + * camellia.h, camellia.c: Replace by new LGPL version and adjusted + camellia.h. + +2007-05-09 Marcus Brinkmann + + * ac.c (_gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read): + Adjust users of gcry_ac_io_t because union is not anonymous + anymore. + +2007-05-02 Werner Koch + + * camellia-glue.c (camellia_setkey, camellia_encrypt) + (camellia_decrypt): Recalculated used stack size in called + functions. + * camellia.h: Redefine external symbols. + +2007-05-02 David Shaw + + * Makefile.am, cipher.c: Add Camellia. + + * camellia-glue.c: New. The necessary glue to interface libgcrypt + to the stock NTT Camellia distribution. + + * camellia.h, camellia.c: The stock NTT Camellia distribution + (GPL). + +2007-04-30 David Shaw + + * cipher.c: Use #if instead of #ifdef as configure defines the + USE_cipher defines as 0 for disabled. + +2007-04-30 Werner Koch + + * rndegd.c (_gcry_rndegd_set_socket_name): New. + +2007-04-30 Marcus Brinkmann + + * ecc.c (ec2os): Fix relocation of short numbers. + + * ecc.c (generate_key): Do not allocate D, which will be allocated + by GEN_K. Remove G. Fix test if g_x, g_y resp. q_x, q_y are + requested. + (_gcry_ecc_generate): Release unneeded members of SK. + * pubkey.c (sexp_to_key): Release NAME. + +2007-04-28 Marcus Brinkmann + + * ac.c (gcry_ac_mpi): Remove member NAME_PROVIDED. + (ac_data_mpi_copy, _gcry_ac_data_set, _gcry_ac_data_get_name) + (_gcry_ac_data_get_index, ac_data_construct): Adjust handling of + NAME accordingly. + +2007-04-20 Werner Koch + + * ecc.c (domain_parms): Add standard brainpool curves. + +2007-04-18 Werner Koch + + * ecc.c (generate_curve): Implement alias mechanism. + + * pubkey.c (sexp_elements_extract_ecc): New. + (sexp_to_key): Add special case for ecc. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_genkey): Replace + name_terminated stuff by a call to _gcry_sexp_nth_string. + (gcry_pk_get_keygrip): Ditto. + +2007-04-16 Werner Koch + + * ecc.c (_gcry_ecc_generate): Renamed DUMMY to CURVE and use it. + +2007-04-13 Marcus Brinkmann + + * ac.c (ac_data_construct): Cast const away to suppress compiler + warning. + + * ecc.c (ecc_generate): Avoid compiler warning for unused argument + DUMMY. + (ecc_verify): Avoid compiler warning for unused arguments CMP and + OPAQUEV. + +2007-04-06 Werner Koch + + * sha1.c (oid_spec_sha1): Add another oid from X9.62. + +2007-03-28 Werner Koch + + * pubkey.c (gcry_pk_genkey): Do not issue misc-key-info if it is + empty. + (gcry_pk_genkey): New parameter "curve". + + * ecc.c: Entirely rewritten with only a few traces of the old + code left. + (_gcry_ecc_generate): New. + (generate_key) New arg NAME. + (generate_curve): Ditto. Return actual number of NBITS. + +2007-03-26 Werner Koch + + * pubkey.c (gcry_pk_genkey): Increase size of SKEY array and add a + runtime bounds check. + +2007-03-23 Werner Koch + + * ecc.c (ecc_ctx_init, ecc_ctx_free, ecc_mod, ecc_mulm): New. + (duplicate_point, sum_points, escalar_mult): Don't use a + copy of base->p. Replaced all mpi_mulm by ecc_mulm so that we can + experiment with different algorithms. + (generate_key, check_secret_key, sign, verify): Initialize a + computation context for use by ecc_mulm. + +2007-03-22 Werner Koch + + * pubkey.c (pubkey_table): Initialize ECC. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc.c. + * ecc.c: New. Heavily reformatted and changed for use in libgcrypt. + (point_init): New. + (escalar_mult): Make arg R the first arg to be similar to the mpi + functions. + (duplicate_point): Ditto + (sum_points): Ditto + (sign, verify): Remove unneeded copy operations. + (sum_points): Removed memory leaks and optimized some compares. + (verify): Simplified input check. + +2007-03-14 Werner Koch + + * random.c (MASK_LEVEL): Removed macro as it was used only at one + place. Open coded it there. + (gcry_randomize, _gcry_update_random_seed_file) + (_gcry_fast_random_poll): Factor lock code out to .. + (lock_pool, unlock_pool): .. new. + (initialize): Look the pool while allocating. + (read_random_source, do_fast_random_poll): Moved intialization to ... + (initialize): .. here. + (_gcry_enable_quick_random_gen): No more need for initialization. + (is_initialized): Moved this global flag to .. + (initialize): .. here and changed all users to unconditionally call + initialize. + (add_randomness): Remove initalization here. It simply can't + happen. + + * random.c (enum random_origins): Moved to .. + * rand-internal.h: .. here. + * rndunix.c (_gcry_rndunix_gather_random): Use enum in prototype + for ORIGIN and renamed REQUESTOR to ORIGIN. + * rndegd.c (_gcry_rndegd_gather_random): Ditto. + * rndlinux.c (_gcry_rndlinux_gather_random): Ditto. + * rndw32.c (_gcry_rndw32_gather_random): Ditto. + (_gcry_rndw32_gather_random_fast): Ditto. + +2007-03-13 Werner Koch + + * random.c (enum random_origins): New. + (add_randomness): Renamed arg SOURCE to ORIGIN. + (read_random_source): Renamed arg REQUESTOR to ORIGIN. + (getfnc_gather_random): Removed static variable because this + function is only called one and thus we don't need this + optimization. + (_gcry_quick_random_gen): Removed and replaced by.. + (_gcry_enable_quick_random_gen): .. this. It is onlyu used to + enable it and it does not make sense to disable it later. Changed + the only one caller too. + (get_random_bytes): Removed. + (gcry_random_bytes, gcry_random_bytes_secure): Implement in terms + of gcry_randomize. + * random-daemon.c (_gcry_daemon_get_random_bytes): Removed. + +2007-02-23 Werner Koch + + * elgamal.c (generate): Removed unused variable TEMP. + (test_keys): New arg NODIE. + (generate_using_x, _gcry_elg_generate_using_x): New. + * pubkey.c (pubkey_generate): New arg XVALUE and direct call to + the new elgamal generate fucntion. + (gcry_pk_genkey): Parse the new "xvalue" tag. + +2007-02-22 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Handle dynamically allocated + algorithms. Suggested by Neil Dunbar. Fixes bug#596. + + * rndw32.c (_gcry_rndw32_gather_random_fast): Make it return void. + + * cipher.c (gcry_cipher_algo_name): Simplified. + + * random.c: Use the daemon only if compiled with USE_RANDOM_DAEMON. + + * Makefile.am (libcipher_la_SOURCES): Build random-daemon support + only if requested. + +2007-02-21 Werner Koch + + * random.c (rndpool, keypool): Make unsigned. + (mix_pool): Change char* variables to unsigned char*. + (gcry_randomize): Make arg BUFFER a void*. + (gcry_create_nonce): Ditto. + + * rmd160.c (gcry_rmd160_mixblock): Make BUFFER a void*. + (_gcry_rmd160_hash_buffer): Make OUTBUF and BUFFER void*. + * sha1.c (_gcry_sha1_hash_buffer): Ditto. + + * cipher.c (gcry_cipher_encrypt, cry_cipher_decrypt): Change + buffer args to void*. + (gcry_cipher_register): Make ALGORITHM_ID a int *. + + * md.c (md_start_debug): Make SUFFIX a const char*. Use snprintf. + (gcry_md_debug): New. + (gcry_md_ctl): Changed arg BUFFER from unsigned char*. + + * md.c (md_write): Make INBUF a const void*. + (gcry_md_write): Remove needless cast. + * crc.c (crc32_write): Make INBUF a const void* + (update_crc32, crc24rfc2440_write): Ditto. + * sha512.c (sha512_write, transform): Ditto. + * sha256.c (sha256_write, transform): Ditto. + * rmd160.c (rmd160_write, transform): Ditto. + * md5.c (md5_write, transform): Ditto. + * md4.c (md4_write, transform): Ditto. + * sha1.c (sha1_write, transform): Ditto. + + * tiger.c (tiger_write, transform): Ditto. + * whirlpool.c (whirlpool_write, whirlpool_add, transform): Ditto. + + * elgamal.c (elg_names): Change to a const*. + * dsa.c (dsa_names): Ditto. + * rsa.c (rsa_names): Ditto. + * pubkey.c (gcry_pk_lookup_func_name): Make ALIASES a const. + +2007-02-20 Werner Koch + + * rndlinux.c (open_device): Remove unsused arg MINOR. + +2007-01-30 Werner Koch + + * sha256.c (oid_spec_sha256): Add alias from pkcs#1. + * sha512.c (oid_spec_sha512): Ditto. + (oid_spec_sha384): Ditto. + +2006-12-18 Werner Koch + + * rndlinux.c (set_cloexec_flag): New. + (open_device): Set close-on-exit flags. Suggested by Max + Kellermann. Fixes Debian#403613. + + * Makefile.am (AM_CPPFLAGS, AM_CFLAGS): Splitted and merged + Moritz' changes. + (INCLUDES): Removed. + +2006-11-30 Werner Koch + + * serpent.c (byte_swap_32): Remove trailing semicolon. + +2006-11-15 Werner Koch + + * Makefile.am (INCLUDES): Include ../src/ + +2006-11-03 Werner Koch + + * random.c [HAVE_GETTIMEOFDAY]: Included sys/time.h and not + sys/times.h. Reported by Rafaël Carré. + +2006-11-05 Moritz Schulte + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-25 Werner Koch + + * primegen.c (prime_generate_internal): Tweaked use of secure + memory and entropy use. Safe unused primes from the pool. Allocate + at least a pool of 30. + (save_pool_prime, get_pool_prime): New. + +2006-10-23 Werner Koch + + * ac.c (_gcry_ac_data_from_sexp): Reset sexp_tmp for failsafe + means. Release sexp_cur if needed. Reported by Dirk Stoecker. + + * pubkey.c (pubkeys_registered_lock): Intialized it. It is not + realy needed because this is a mere initialization to 0 anyway. + Noted by Victor Stinner. + +2006-10-17 Werner Koch + + * dsa.c (_gcry_dsa_generate2): New. + (generate): New arg QBITS. Add sanity checks for reasonable qbits + and nbits. + * pubkey.c (gcry_pk_genkey): Parse an qbits element. + (pubkey_generate): New arg QBITS. Pass it to the DSA generation. + +2006-10-05 Werner Koch + + * md.c (gcry_md_algo_info) : Check that the algo is + available. + +2006-10-04 David Shaw (wk) + + * tiger.c (round): Rename to tiger_round as gcc 4 has a built-in + round function that this conflicts with. + +2006-09-11 Werner Koch + + * rndw32.c (slow_gatherer_windowsNT): While adding data use the + size of the diskPerformance and not its address. Has been fixed in + GnuPG more than a year ago. Noted by Lee Fisher. + +2006-08-30 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Need to allow "ripemd160" here as + this is the canonical name. + +2006-08-29 Hye-Shik Chang (wk) + + * seed.c: New. + +2006-08-03 Werner Koch + + * random-daemon.c (_gcry_daemon_initialize_basics): Don't + initialize the socket. Remove arg SOCKETNAME. + (connect_to_socket): Make sure that daemon is set to -1 on error. + (call_daemon): Initialize the socket on the first call. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): New arg SOCKETNAME. + * random.c (initialize): Call new daemon initializator. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Pass socket + name to daemon call and reset allow_daemon on failure. + +2006-07-26 Werner Koch + + * rmd160.c (_gcry_rmd160_mixblock): Add cast to transform call. + + * blowfish.c (selftest): Cast string to usnigned char*. + + * primegen.c (prime_generate_internal): Cast unsigned/char* + mismatch in calling m_out_of_n. + (is_prime): Changed COUNT to unsigned int *. + + * ac.c (_gcry_ac_data_copy): Initialize DATA_MPIS. + + * random.c (gcry_create_nonce): Update the pid after a fork. + Reported by Uoti Urpala. + +2006-07-04 Marcus Brinkmann + + * sha512.c: Fix typo in copyright notice. + +2006-06-21 Werner Koch + + * rsa.c (_gcry_rsa_generate): Replace xcalloc by calloc. + * pubkey.c (gcry_pk_encrypt, gcry_pk_sign): Ditto. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_encrypt) + (gcry_pk_sign, gcry_pk_genkey, gcry_pk_get_keygrip): Ditto. + * md.c (md_copy): Ditto. + +2006-04-22 Moritz Schulte + + * random-daemon.c (_gcry_daemon_initialize_basics): New argument: + SOCKETNAME. Passing on to connect_to_socket() if non-NULL. + (connect_to_socket, writen, readn, call_daemon): New functions. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): Call call_daemon(). + (RANDOM_DAEMON_SOCKET): New symbol. + (daemon_socket): New static variable. + + * random.h (_gcry_daemon_initialize_basics): New parameter: + SOCKETNAME. + (_gcry_set_random_daemon_socket): New declaration. + + * random.c (initialize_basics): Pass DAEMON_SOCKET_NAME to + _gcry_daemon_initialize_basics. + (_gcry_set_random_daemon_socket): New function, setting + DAEMON_SOCKET_NAME. + +2006-04-01 Moritz Schulte + + * ac.c (eme_pkcs_v1_5_encode): Use KEY_SIZE directly, no need to + call gcry_ac_key_get_nbits. + (eme_pkcs_v1_5_decode): Likewise. + (ac_es_dencode_prepare_pkcs_v1_5): Fill options_em structure with + key_size. + (_gcry_ac_data_dump, gcry_ac_data_dump): New functions. + (_gcry_ac_data_to_sexp, _gcry_ac_data_from_sexp): More or less + rewritten; changed S-Expression format so that it matches the one + used in pubkey.c. + +2006-03-15 Werner Koch + + * random-daemon.c: New. + * random.c (_gcry_use_random_daemon): New. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Try + diverting to the daemon functions. + +2006-03-14 Werner Koch + + * random.c (lock_seed_file): New. + (read_seed_file, _gcry_update_random_seed_file): Use it. + + * random.c (gcry_create_nonce): Detect a fork and re-seed. + (read_pool): Fixed the fork detection; it used to work only for + multi-threaded processes. + +2006-03-12 Brad Hards (wk) + + * md.c (md_open): Use new variable macpads_Bsize instead of + hardwiring the block size. Changed at all places. + +2006-03-10 Brad Hards (wk, patch 2005-04-22) + + * md.c, sha256.c: Add support for SHA-224. + (sha224_init): New. + +2006-01-18 Brad Hards (wk 2006-03-07) + + * cipher.c (cipher_encrypt, cipher_decrypt, do_ofb_encrypt) + (do_ofb_decrypt, gcry_cipher_open): Implement Output Feedback Mode. + +2005-11-02 Moritz Schulte + + * pubkey.c (gcry_pk_algo_name): Return "?" instead of NULL for + unknown algorithm IDs. + * cipher.c (cipher_algo_to_string): Likewise. + +2005-11-01 Moritz Schulte + + * pubkey.c (gcry_pk_algo_info): Don't forget to break after switch + case. + +2005-09-19 Werner Koch + + * dsa.c (generate): Add preliminary support for 2 and 4 keys. + Return an error code if the key size is not supported. + (_gcry_dsa_generate): Return an error. + +2005-08-22 Werner Koch + + * primegen.c (check_prime): New arg RM_ROUNDS. + (prime_generate_internal): Call it here with 5 rounds as used + before. + (gcry_prime_check): But here with 64 rounds. + (is_prime): Make sure never to use less than 5 rounds. + +2005-04-16 Moritz Schulte + + * ac.c (_gcry_ac_init): New function. + +2005-04-12 Moritz Schulte + + * ac.c (_gcry_ac_io_write, _gcry_ac_io_read): Initialize err to + make the compiler happy. + Always use errno, now that gcry_malloc() is guaranteed to set + errno on failure. + (_gcry_ac_data_to_sexp): Don't forget to goto out after error in + loop. + (_gcry_ac_data_to_sexp): Remove unused variable: mpi_list; + (_gcry_ac_data_to_sexp): Always deallocate sexp_buffer. + (_gcry_ac_data_from_sexp): Don't forget to initialize data_set_new. + (_gcry_ac_data_from_sexp): Handle special case, which is + necessary, since gcry_sexp_nth() does not distinguish between + "element does not exist" and "element is the empty list". + (_gcry_ac_io_init_va): Use assert to make sure that mode and type + are correct. + Use gcry_error_t types where gcry_err_code_t types have been used + before. + +2005-04-11 Moritz Schulte + + * ac.c (_gcry_ac_data_sign_scheme): Don't forget to initialize + buffer. + + * whirlpool.c: New file. + * md.c (digest_table): Add whirlpool. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Added: whirlpool.c. + +2005-03-30 Moritz Schulte + + * ac.c (_gcry_ac_data_from_sexp): Use length of SEXP_CUR, not + length of SEXP; do not forget to set SEXP_TMP to NULL after it has + been released. + + (struct gcry_ac_mpi): New member: name_provided. + (_gcry_ac_data_set): Rename variable `name_final' to `name_cp'; + remove const qualifier; change code to not cast away const + qualifiers; use name_provided member as well. + (_gcry_ac_data_set, _gcry_ac_data_get_name): Use name_provided + member of named mpi structure. + + (gcry_ac_name_to_id): Do not forget to initialize err. + (_gcry_ac_data_get_index): Do not forget to initialize mpi_return; + use gcry_free() instead of free(); remove unnecessary cast; rename + mpi_return and name_return to mpi_cp and name_cp; adjust code. + (ac_data_mpi_copy): Do not cast away const qualifier. + (ac_data_values_destroy): Likewise. + (ac_data_construct): Likewise. + + (ac_data_mpi_copy): Initialize flags to GCRY_AC_FLAG_DEALLOC. + (ac_data_extract): Use GCRY_AC_FLAG_DEALLOC instead of + GCRY_AC_FLAG_COPY. + + (_gcry_ac_io_init_va, _gcry_ac_io_init, gcry_ac_io_init) + (gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read) + (_gcry_ac_io_read_all, _gcry_ac_io_process): New functions. + (gry_ac_em_dencode_t): Use gcry_ac_io_t in prototype instead of + memroy strings directly; adjust encode/decode functions to use io + objects. + (emsa_pkcs_v1_5_encode_data_cb): New function ... + (emsa_pkcs_v1_5_encode): ... use it here. + (ac_data_dencode): Use io objects. + (_gcry_ac_data_encode, _gcry_ac_data_decode, gcry_ac_data_encode) + (gcry_ac_data_decode): Likewise. + (_gcry_ac_data_encrypt_scheme, gcry_ac_data_encrypt_scheme) + (_gcry_ac_data_decrypt_scheme, gcry_ac_data_decrypt_scheme) + (_gcry_ac_data_sign_scheme, gcry_ac_data_sign_scheme) + (_gcry_ac_data_verify_scheme, gcry_ac_data_verify_scheme): + Likewise. + +2005-03-23 Werner Koch + + * rndw32.c (_gcry_rndw32_gather_random_fast): While adding data + use the size of the object and not the one of its address. Bug + reported by Sascha Kiefer. + +2005-03-19 Moritz Schulte + + * cipher.c (do_cbc_encrypt): Be careful to not overwrite data, + which is to be used later on. This happend, in case CTS is + enabled and OUTBUF is equal to INBUF. + +2005-02-25 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Allow for shadowed-private-key. + +2005-02-13 Moritz Schulte + + * serpent.c: Updated from 1.2 branch: + + s/u32_t/u32/ and s/byte_t/byte/. Too match what we have always + used and are using in all other files too + (serpent_test): Moved prototype out of a fucntion. + +2005-02-07 Moritz Schulte + + * ac.c: Major parts rewritten. + * pubkey.c (_gcry_pk_get_elements): New function. + +2004-12-09 Werner Koch + + * serpent.c (serpent_setkey): Moved prototype of serpent_test to + outer scope. + +2004-09-11 Moritz Schulte + + * pubkey.c (pubkey_table): Added an alias entry for GCRY_PK_ELG_E. + +2004-08-23 Moritz Schulte + + * ac.c: Do not include . + * rndegd.c: Likewise. + * sha1.c: Likewise. + * rndunix.c: Likewise. + * rndlinux.c: Likewise. + * rmd160.c: Likewise. + * md5.c: Likewise. + * md4.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * blowfish.c: Likewise. + + * pubkey.c (dummy_generate, dummy_check_secret_key) + (dummy_encrypt, dummy_decrypt, dummy_sign, dummy_verify): Return + err code GPG_ERR_NOT_IMPLEMENTED instead of aborting through + log_bug(). + (dummy_get_nbits): Return 0 instead of aborting though log_bug(). + +2004-08-19 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Changed the zero random byte + substituting code to actually do clever things. Thanks to + Matthias Urlichs for noting the implementation problem. + +2004-08-09 Moritz Schulte + + * pubkey.c (gcry_pk_sign): Fixed memory leak; fix provided by + Modestas Vainius. + +2004-07-16 Werner Koch + + * rijndael.c (do_encrypt): Fix alignment problem. Bugs found by + Matthias Urlichs. + (do_decrypt): Ditto. + (keySched, keySched2): Use 2 macros along with unions in the key + schedule context. + +2004-07-14 Moritz Schulte + + * rsa.c (_gcry_rsa_decrypt): Don't forget to free "a". Thanks to + Nikos Mavroyanopoulos. + +2004-05-09 Werner Koch + + * random.c (read_pool): Mix the PID in to better protect after a + fork. + +2004-07-04 Moritz Schulte + + * serpent.c: Use "u32_t" instead of "unsigned long", do not + declare S-Box variables as "register". Fixes failure on + OpenBSD/sparc64, reported by Nikolay Sturm. + +2004-05-07 Werner Koch + + * random.c (initialize): Factored out some code to .. + (initialize_basics): .. new function. + (_gcry_random_initialize): Just call initialize_basics unless the + new arg FULL is set to TRUE. + (_gcry_fast_random_poll): Don't do anything unless the random + system has been really initialized. + +2004-05-07 Moritz Schulte + + * ac.c (gcry_ac_open): Do not dereference NULL pointer. Reported + by Umberto Salsi. + +2004-02-20 Werner Koch + + * primegen.c (check_prime): New args CB_FUNC and CB_ARG; call them + at different stages. Pass these arguments through all callers. + +2004-02-06 Werner Koch + + * des.c: Add a new OID as used by pkcs#12. + + * rfc2268.c: New. Taken from libgcrypt. + * cipher.c: Setup the rfc2268 algorithm. + +2004-01-25 Moritz Schulte + + * primegen.c (prime_generate_internal): Do not forget to free + `q_factor'; fixed by Brieuc Jeunhomme. + (prime_generate_internal): Do not forget to free `prime'. + +2004-01-14 Moritz Schulte + + * ac.c (gcry_ac_data_set): New argument: flags; slightly + rewritten. + (gcry_ac_data_get_name, gcry_ac_data_get_index): Likewise. + (gcry_ac_key_pair_generate): New argument: misc_data; modified + order of arguments. + (gcry_ac_key_test): New argument: handle. + (gcry_ac_key_get_nbits, gcry_ac_key_get_grip): Likewise. + Use GCRY_AC_FLAG_NO_BLINDING instead of + GCRY_AC_DATA_FLAG_NO_BLINDING. + (gcry_ac_mpi): New member: flags. + (gcry_ac_data_search, gcry_ac_data_add): Removed functions. + +2003-12-22 Werner Koch + + * primegen.c (is_prime): Release A2. + +2003-12-19 Werner Koch + + * md.c: Moved a couple of functions down below the data structure + definitions. + (struct gcry_md_context): New field ACTUAL_HANDLE_SIZE. + (md_open): Set it here. + (strcut gcry_md_list): New field ACTUAL_STRUCT_SIZE. + (md_enable): Set it here. + (md_close): Wipe the context memory. + secure memory. + * cipher.c (struct gcry_cipher_handle): New field ACTUAL_HANDLE_SIZE. + (gcry_cipher_open): Set it here. + (gcry_cipher_close): Use it to always wipe out the handle data. + + * ac.c (gcry_ac_open): Make sure HANDLE gets initialized even when + the function is not successful. + (gcry_ac_close): Allow a NULL handle. + (gcry_ac_key_destroy, gcry_ac_key_pair_destroy): Ditto. + (gcry_ac_key_get_grip): Return INV_OBJ on error. + + * primegen.c (prime_generate_internal): Fixed error code for + failed malloc. Replaced the !err if chain by gotos. + (gcry_prime_group_generator): Remove the extra sanity check. + + * md.c: Minor code and comment cleanups. + +2003-12-16 Werner Koch + + * primegen.c (gen_prime): Doc fix. Thanks to Newton Hammet. + +2003-12-11 Werner Koch + + * rndunix.c (slow_poll): Don't use #warning but #error. + + * rndegd.c: Changed indentation. + (my_make_filename): Removd the var_arg cruft becuase we + don't need it here. Changed caller. + + * rndlinux.c: Changed indentation. + (open_device): Remove the superfluous stat call and clarify + comment. + + * rsa.c: Changed indentation. + (secret): Use the standard algorithm if p, q and u are not + available. + (rsa_blind, rsa_unblind): Renamed from _gcry_rsa_blind, + _gcry_rsa_unblind and moved more to the top. + + * md4.c: Changed indentation. Removed unnecessary casts. + * md5.c, rmd160.c, sha1.c, tiger.c: Ditto. + * rijndael.c, twofish.c: Ditto. + * serpent.c: Removed unnecessary casts. + * sha256.c, sha512.c: Ditto. + +2003-12-09 Werner Koch + + * dsa.c: Unified indentation style. + * elgamal.c: Ditto. + * des.c (des_key_schedule): Code beautifications. + * blowfish.c: Changed indentation style. + * cast5.c (do_cast_setkey): Ditto. + + * pubkey.c (gcry_pk_encrypt): Replaced the chain of if(!err) tests + by straightforward gotos. Other cleanups. + (gcry_pk_decrypt): Ditto. + (gcry_pk_sign): Ditto. + (gcry_pk_verify): Ditto. + (gcry_pk_genkey): Ditto. Use strtoul instead of strtol. + (gcry_pk_ctl): Use GPG_ERR_INV_ARG to indicate bad arguments. + +2003-12-07 Werner Koch + + * pubkey.c (gcry_pk_register_default): Undef the helper macro. + (gcry_pk_map_name): Allow NULL for string. + (sexp_to_key): Use memcpy and not strncpy. Use gcry_free and not + free. + (sexp_to_sig): Ditto. + (sexp_to_enc): Ditto. Replaced the chain of if(!err) tests by + straightforward gotos. + +2003-12-05 Werner Koch + + * cipher.c: Documentation cleanups. + (gcry_cipher_mode_from_oid): Allow NULL for STRING. + +2003-12-03 Werner Koch + + * elgamal.c (sign, do_encrypt, gen_k): Make sure that a small K is + only used for encryption. + +2003-11-18 Werner Koch + + * random.h (rndw32_set_dll_name): Removed unused prototype. + + * Makefile.am (EXTRA_DIST): Added Manifest. + +2003-11-11 Werner Koch + + * Manifest: New. + +2003-11-04 Werner Koch + + * md.c (gcry_md_hash_buffer): Use shortcut for SHA1 + * sha1.c (_gcry_sha1_hash_buffer): New. + + * random.c: Reformatted most functions. + (mix_pool): Moved the failsafe_digest from global + scope to here. + (do_fast_random_poll): Use the generic fucntions even if a fast + gathering function has been used. + (read_pool): Detect a fork and retry. + (gcry_randomize, get_random_bytes): Don't distinguish anymore + between weak and strong random. + (gcry_create_nonce): New. + +2003-10-31 Werner Koch + + * rndw32.c (slow_gatherer_windowsNT): Use a plain buffer for the + disk performance values and not the W32 API structure. + + * dsa.c (verify): s/exp/ex/ due to shadowing of a builtin. + * elgamal.c (verify): Ditto. + + * ac.c (gcry_ac_data_get_index): s/index/idx/ + (gcry_ac_data_copy_internal): Remove the cast in _gcry_malloc. + (gcry_ac_data_add): Must use gcry_realloc instead of realloc. + * pubkey.c (sexp_elements_extract): s/index/idx/ as tribute to the + forehackers. + (gcry_pk_encrypt): Removed shadowed definition of I. Reordered + arguments to malloc for clarity. + (gcry_pk_sign, gcry_pk_genkey): Ditto. + * primegen.c (prime_generate_internal): s/random/randomlevel/. + +2003-10-27 Moritz Schulte + + * pubkey.c (gcry_pk_encrypt): Don't forget to deallocate pkey. + +2003-10-27 Werner Koch + + * random.c (gcry_random_add_bytes): Return if buflen is zero to + avoid gcc warning about unsed parameter. + (MASK_LEVEL): Simplified; does now work for signed and unsigned + w/o warnings. + + * md.c (md_start_debug): Removed the const from SUFFIX, because + this function is called from the control fucntion which does not + require const. + + Prefixed all (pubkey,digest,cipher}_spec_* globale variables with + _gcry_. + + * ac.c (ac_key_identifiers): Made static. + + * random.c (getfnc_gather_random,getfnc_fast_random_poll): Move + prototypes to .. + * rand-internal.h: .. here + * random.c (getfnc_gather_random): Include rndw32 gatherer. + * rndunix.c, rndw32.c, rndegd.c: Include them here. + * rndlinux.c (_gcry_rndlinux_gather_random): Prepend the _gcry_ + prefix. Changed all callers. + * rndegd.c (_gcry_rndegd_gather_random): Likewise. + (_gcry_rndegd_connect_socket): Likewise. + * rndunix.c (_gcry_rndunix_gather_random): Likewise. + (waitpid): Made static. + * rndw32.c: Removed the old and unused winseed.dll cruft. + (_gcry_rndw32_gather_random_fast): Renamed from + gather_random_fast. + (_gcry_rndw32_gather_random): Renamed from gather_random. Note, + that the changes 2003-04-08 somehow got lost. + + * sha512.c (sha512_init, sha384_init): Made static. + + * cipher.c (do_ctr_decrypt): Removed "return" from this void + function. + +2003-10-24 Moritz Schulte + + * serpent.c: Fix an issue on big-endian systems. + + * rndw32.c: Removed IS_MODULE -cruft. + * rndlinux.c (rndlinux_gather_random): Likewise. + +2003-10-10 Werner Koch + + * primegen.c (gen_prime): Bail out if NBITS is less than 16. + (prime_generate_internal): Initialize prime variable to suppress + compiler warning. Check pbits, initialize qbits when passed as + zero. + + * primegen.c (prime_generate_internal): New arg + ALL_FACTORS. Changed all callers. + (gcry_prime_generate): Make the factors arg optional. Request + all_factors. Make sure PRIME is set to NULL even on error. + (gcry_prime_group_generator): New. + (gcry_prime_release_factors): New. + +2003-10-06 Werner Koch + + * primegen.c (gen_prime): Assert that NBITS is never zero, it + would cause a segv. + +2003-09-28 Moritz Schulte + + * ac.c: Include "cipher.h". + +2003-09-27 Moritz Schulte + + * rndegd.c (do_read): Return nread instead of nbytes; thanks to + Michael Caerwyn. + +2003-09-04 Werner Koch + + * pubkey.c (_gcry_pk_aliased_algo_name): New. + * ac.c (gcry_ac_open): Use it here. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add serpent.c + +2003-09-02 Moritz Schulte + + * primegen.c (gcry_prime_check, gcry_prime_generate): New + functions. + (prime_generate_internal): New function, based on + _gcry_generate_elg_prime. + (_gcry_generate_elg_prime): Rewritten as a wrapper for + prime_generate_internal. + +2003-08-28 Werner Koch + + * pubkey.c (gcry_pk_encrypt): Don't include the flags list in the + return value. This does not make sense and breaks any programs + parsing the output strictly (e.g. current gpgsm). + (gcry_pk_encrypt): If aliases for the algorithm name exists, take + the first one instead of the regular name to adhere to SPKI + conventions. + (gcry_pk_genkey): Ditto. + (gcry_pk_sign): Ditto. Removed unused KEY_ALGO_NAME. + +2003-08-19 Moritz Schulte + + * cipher.c: Add support for Serpent + * serpent.c: New file. + +2003-08-10 Moritz Schulte + + * rsa.c (_gcry_rsa_blind, _gcry_rsa_unblind): Declare static. + +2003-08-09 Timo Schulz + + * random.c (getfnc_gather_random): Don't check NAME_OF_DEV_RANDOM + two times, but also the NAME_OF_DEV_URANDOM device. + +2003-08-08 Moritz Schulte + + * pubkey.c (sexp_to_enc): Fixed extraction of S-Expression: do not + fail if no `flags' sub S-Expression is found. + +2003-07-27 Werner Koch + + * md.c (gcry_md_lookup_func_oid): Allow for empty OID lists. + +2003-07-23 Moritz Schulte + + * ac.c (gcry_ac_data_construct): New argument: include_flags, only + include `flags' S-expression, if include_flags is true. Adjust + callers. Thanks for triggering a bug caused by `flags' + sub-S-expression where they are not expected to Ralf Schneider. + +2003-07-21 Moritz Schulte + + * pubkey.c (gcry_pk_lookup_func_name): Use new member name + `aliases' instead of `sexp_names'. + + * ac.c (gcry_ac_key_data_get): New function. + + * cipher.c (gcry_cipher_lookup_func_name): Fix return value. + +2003-07-20 Moritz Schulte + + * blowfish.c: Adjusted for new gcry_cipher_spec_t structure. + * cast5.c: Likewise. + * twofish.c: Likewise. + * arcfour.c: Likewise. + * rijndael.c (rijndael_oids, rijndael192_oids, rijndael256_oids): + New variables, adjust for new gcry_cipher_spec_t structure. + * des.c (oids_tripledes): New variable, adjust for new + gcry_cipher_spec_t structure. + + * md.c (oid_table): Removed. + + * tiger.c (oid_spec_tiger): New variable. + (digest_spec_tiger): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha512): New variable. + (digest_spec_sha512): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha384): New variable. + (digest_spec_sha384): Adjusted for new gry_md_spec_t structure. + + * sha256.c (oid_spec_sha256): New variable. + (digest_spec_sha256): Adjusted for new gry_md_spec_t structure. + + * sha1.c (oid_spec_sha1): New variable. + (digest_spec_sha1): Adjusted for new gry_md_spec_t structure. + + * rmd160.c (oid_spec_rmd160): New variable. + (digest_spec_rnd160): Adjusted for new gry_md_spec_t structure. + + * md5.c (oid_spec_md5): New variable. + (digest_spec_md5): Adjusted for new gry_md_spec_t structure. + + * md4.c (oid_spec_md4): New variable. + (digest_spec_md4): Adjusted for new gry_md_spec_t structure. + + * crc.c (digest_spec_crc32, digest_spec_crc32_rfc1510, + digest_spec_crc32_rfc2440): Adjusted for new gry_md_spec_t + structure. + +2003-07-19 Moritz Schulte + + * md.c (gcry_md_lookup_func_oid): New function. + (search_oid): New function, copied from cipher.c. + (gcry_md_map_name): Adjust for new search_oid_interface. + + * cipher.c (oid_table): Removed table. + (gcry_cipher_lookup_func_oid): New function. + (search_oid): Rewritten to use the module functions. + (gcry_cipher_map_name): Adjust for new search_oid interface. + (gcry_cipher_mode_from_oid): Likewise. + +2003-07-18 Werner Koch + + * md.c (gcry_md_hash_buffer): Convert ERR to gpg_error_t in + gpg_strerror. + +2003-07-14 Moritz Schulte + + * cipher.c (gcry_cipher_lookup_func_name): Also check the cipher + name aliases, not just the primary name. + (gcry_cipher_map_name): Remove kludge for aliasing Rijndael to + AES. + + * arcfour.c, blowfish.c, cast5.c, des.c, twofish.c: Adjust cipher + specification structures. + + * rijndael.c (rijndael_names, rijndael192_names, + rijndael256_names): New variables, use them in the cipher + specifications. + + * rmd160test.c: Removed file. + + * ac.c, arcfour.c, blowfish.c, cast5.c, cipher.c, des.c, dsa.c, + elgamal.c, md.c, pubkey.c, random.c, rijndael.c, rsa.c, twofish.c: + Used gcry_err* wrappers for libgpg symbols. + + * primegen.c (gen_prime): Correct the order arguments to + extra_check. + +2003-07-12 Moritz Schulte + + * ac.c: Replaced all public occurences of gpg_error_t with + gcry_error_t. + * cipher.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * random.c: Likewise. + + * cipher.c: Added support for TWOFISH128. + +2003-07-08 Moritz Schulte + + * ac.c (gcry_ac_data_copy_internal): New function, based on + gcry_ac_data_copy. + (gcry_ac_data_copy): Made public, use gcry_ac_data_copy_internal. + (gcry_ac_key_init): Use gcry_ac_data_copy_internal. + +2003-07-07 Moritz Schulte + + * ac.c (gcry_ac_data_set): Only release old MPI value if it is + different from the new value. Bug reported by Simon Josefsson + . + + * pubkey.c (gcry_pk_list): New function. + * md.c (gcry_md_list): New function. + + * ac.c (gcry_ac_key_pair_generate): Fix calculation of format + string size. + +2003-07-05 Moritz Schulte + + * md.c: Named struct of digest_table `digest_table_entry'. + (digest_table_entry): New member: algorithm; filled in. + (digest_table_entry): Removed unused member: flags. + (gcry_md_register): New argument: algorithm_id, filled in. + (gcry_md_register_default): Used algorithm ID from module + structure. + (gcry_md_map_name): Likewise. + (md_enable): Likewise. + (md_read): Likewise. + (gcry_md_info): Likewise. + + * pubkey.c: Named truct for pubkey_table `pubkey_table_entry'. + (pubkey_table_entry): New member: algorithm; filled in. + (gcry_pk_register_default): Used algorithm ID from pubkey_table. + (gcry_pk_register): New argument: algorithm_id, filled in. + (gcry_pk_map_name): Used algorithm ID from module structure. + (gcry_pk_decrypt): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_get_nbits): Likewise. + (sexp_to_key): Removed unused variable: algo. + (sexp_to_sig): Likewise. + + * cipher.c: Named struct for cipher_table `cipher_table_entry'. + (cipher_table_entry): New member: algorithm; filled in. + (gcry_cipher_register_default): Used algorithm ID from + cipher_table. + (gcry_cipher_register): New argument: algorithm_id, filled in. + (gcry_cipher_map_name): Used algorithm ID from module structure. + + * arcfour.c (cipher_spec_arcfour): Removed algorithm ID. + * blowfish.c (cipher_spec_blowfish): Likewise. + * cast5.c (cipher_spec_cast5): Likewise. + * crc.c (digest_spec_crc32): Likewise. + * crc.c (digest_spec_crc32_rfc1510): Likewise. + * crc.c (digest_spec_crc32_rfc2440): Likewise. + * des.c (cipher_spec_des): Likewise. + * des.c (cipher_spec_tripledes): Likewise. + * dsa.c (pubkey_spec_dsa): Likewise. + * elgamal.c (pubkey_spec_elg): Likewise. + * md4.c (digest_spec_md4): Likewise. + * md5.c (digest_spec_md5): Likewise. + * aes.c (cipher_spec_aes): Likewise. + * aes.c (cipher_spec_aes192): Likewise. + * aes.c (cipher_spec_aes256): Likewise. + * rsa.c (pubkey_spec_rsa): Likewise. + * sha1.c (digest_spec_sha1): Likewise. + * sha256.c (digest_spec_sha256): Likewise. + * sha512.c (digest_spec_sha512): Likewise. + * tiger.c (digest_spec_tiger): Likewise. + * twofish.c (cipher_spec_twofish): Likewise. + * twofish.c (cipher_spec_twofish128): Likewise. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Fix list of source + files; reported by Simon Josefsson . + + * pubkey.c: Replaced all occurences of `id' with `algorithm', + since `id' is a keyword in obj-c. + * md.c: Likewise. + * cipher.c: Likewise. + + * crc.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, tiger.c: + Replaced all occurences of gcry_digest_spec_t with gcry_md_spec_t. + + * dsa.c, rsa.c, elgamal.c: Replaced all occurencens of + gcry_pubkey_spec_t with gcry_pk_spec_t. + + * md.c: Replaced all occurences of gcry_digest_spec_t with + gcry_md_spec_t. + (gcry_digest_register_default): Renamed to ... + (gcry_md_register_default): ... this; adjusted callers. + (gcry_digest_lookup_func_name): Renamed to ... + (gcry_md_lookup_func_name): ... this; adjusted callers. + (gcry_digest_lookup_name): Renamed to ... + (gcry_md_lookup_name): ... this; adjusted callers. + (gcry_digest_register): Renamed to ... + (gcry_md_register): ... this. + (gcry_digest_unregister): Renamed to ... + (gcry_md_unregister): ... this. + + * pubkey.c (gcry_pubkey_register): Renamed to ... + (gcry_pk_register): ... this. + (gcry_pubkey_unregister): Renamed to ... + (gcry_pk_unregister): ... this. + Replaced all occurences of gcry_pubkey_spec_t with gcry_pk_spec_t. + (gcry_pubkey_register_default): Renamed to ... + (gcry_pk_register_default): ... this; adjusted callers. + (gcry_pubkey_lookup_func_name): Renamed to ... + (gcry_pk_lookup_func_name): ... this; adjusted callers. + (gcry_pubkey_lookup_name): Renamed to ... + (gcry_pk_lookup_name): ... this; adjusted callers. + + * md.c (gcry_md_hash_buffer): Fix error checking. Thanks to Simon + Josefsson . + +2003-07-04 Moritz Schulte + + * cipher.c (gcry_cipher_list): New function. + +2003-07-01 Moritz Schulte + + * pubkey.c (sexp_to_sig): Accept a `flags' S-expression to be more + consistent with sexp_to_enc. + +2003-06-30 Moritz Schulte + + * Makefile.am (libcipher_la_SOURCES): Added: ac.c. + + * pubkey.c (_gcry_pk_module_lookup): New function. + (_gcry_pk_module_release): New function. + +2003-06-29 Moritz Schulte + + * ac.c: New file. + +2003-06-26 Werner Koch + + * md.c (gcry_md_hash_buffer): Trigger BUG correcly with new API. + +2003-06-19 Werner Koch + + * md.c (gcry_md_is_enabled): Fixed. + +2003-06-18 Werner Koch + + * cipher.c (gcry_cipher_get_algo_keylen): New. + (gcry_cipher_get_algo_blklen): New. + +2003-06-18 Moritz Schulte + + * arcfour.c, cipher.c, blowfish.c, md.c, cast5.c, pubkey.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, random.c, rijndael.c, + rmd160.c, rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: + Replaced older types GcryDigestSpec, GcryCipherSpec and + GcryPubkeySpec with newer types: gcry_digest_spec_t, + gcry_cipher_spec_t and gcry_pubkey_spec_t. + + * md.c (gcry_digest_id_new): Removed function. + (gcry_digest_register): Removed code for generating a new module + ID. + + * pubkey.c (gcry_pubkey_id_new): Removed function. + (gcry_pubkey_register): Removed code for generating a new module + ID. + + * cipher.c, md.c, pubkey.c: Replace old type GcryModule with newer + one: gcry_module_t. + (gcry_cipher_id_new): Removed function. + (gcry_cipher_register): Removed code for generating a new module + ID. + + * cipher.c (gcry_cipher_register): Adjust call to + _gcry_module_add. + (gcry_cipher_register_default): Likewise. + * pubkey.c (gcry_pubkey_register_default): Likewise. + (gcry_pubkey_register): Likewise. + * md.c (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + + * md.c (gcry_digest_lookup_func_id): Removed function. + (gcry_digest_lookup_id): Likewise. + (gcry_digest_id_new): Use _gcry_module_lookup_id instead of + gcry_digest_lookup_id. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + + * pubkey.c (gcry_pubkey_lookup_id): Removed function. + (gcry_pubkey_lookup_func_id): Likewise. + (gcry_pubkey_id_new): Use _gcry_module_lookup_id instead of + gcry_pubkey_id_new. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_algo_info): Likewise. + + * cipher.c (gcry_cipher_lookup_func_id): Removed function. + (gcry_cipher_lookup_id): Likewise. + (cipher_algo_to_string): use _gcry_module_lookup_id instead of + gcry_cipher_lookup_id. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (gcry_cipher_id_new): Likewise. + +2003-06-17 Moritz Schulte + + * Makefile.am (GCRYPT_MODULES): Set to @GCRYPT_CIPHERS@, + @GCRYPT_PUBKEY_CIPHERS@, @GCRYPT_DIGESTS@ and @GCRYPT_RANDOM@. + (libcipher_la_DEPENDENCIES): Set to $(GCRYPT_MODULES). + (libcipher_la_LIBADD): Likewise. + (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + (EXTRA_libcipher_la_SOURCES): Added all conditional sources. + + * md.c (md_open): Use _gcry_fast_random_poll instead of + fast_random_poll. + * cipher.c (gcry_cipher_open): Likewise. + + * random.h (fast_random_poll): Removed macro. + + * blowfish.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, sha512.c, + tiger.c: Use Autoconf's WORDS_BIGENDIAN instead of our own + BIG_ENDIAN_HOST. + +2003-06-16 Moritz Schulte + + * random.c (getfnc_gather_random): Do not special-case + USE_ALL_RANDOM_MODULES, make it the default. + + * dsa.c: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * elgamal.c: Likewise. + * primegen.c: Likewise. + * pubkey.c: Likewise. + * rsa.c: Likewise. + +2003-06-14 Moritz Schulte + + * des.c (des_setkey): Add selftest check. + (tripledes_set3keys): Likewise. + (do_tripledes_setkey): Remove selftest check. + (do_des_setkey): Likewise. + +2003-06-11 Moritz Schulte + + * md.c (_gcry_md_init): New function. + * cipher.c (_gcry_cipher_init): New function. + * pubkey.c (_gcry_pk_init): New function. + +2003-06-13 Werner Koch + + * md.c (gcry_md_get_algo): Reverted to old API. This is a + convenience function anyway and error checking is not approriate. + (gcry_md_is_secure): New. + (gcry_md_is_enabled): New. + +2003-06-12 Werner Koch + + * cipher.c (gcry_cipher_open): Make sure HANDLE is set to NULL on + error. + +2003-06-11 Werner Koch + + * md.c (gcry_md_open): Make sure H receives either NULL or an + valid handle. + (gcry_md_copy): Swapped arguments so that it is more in lione with + md_open and most other API fucntions like memcpy (destination + comes first). Make sure HANDLE is set to NULL on error. + + * rijndael.c (do_encrypt): Hack to force correct alignment. It + seems not to be not sufficient, though. We should rework this + fucntions and remove all these ugly casts. Let the compiler + optimize or have an assembler implementation. + +2003-06-09 Moritz Schulte + + * Makefile.am: Removed rules serpent, since that is not commited + yet. + +2003-06-08 Moritz Schulte + + * pubkey.c (gcry_pk_encrypt): Improve calculation for size of the + format string. + +2003-06-07 Moritz Schulte + + * arcfour.c, bithelp.h, blowfish.c, cast5.c, cipher.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, md.c, primegen.c, pubkey.c, + rand-internal.h, random.c, random.h, rijndael.c, rmd160.c, + rmd160test.c, rmd.h, rndeged.c, rndlinux.c, rndunix.c, rndw32.c, + rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: Edited all + preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. Replaced any occurence of the now + deprecated type names with the new ones. + +2003-06-04 Moritz Schulte + + * pubkey.c (gcry_pk_encrypt): Construct an arg_list and use + gcry_sexp_build_array instead of gcry_sexp_build. + (gcry_pk_sign): Likewise. + (gcry_pk_genkey): Likewise. + +2003-06-01 Moritz Schulte + + * dsa.c (_gcry_dsa_generate): Do not check wether the algorithm ID + does indeed belong to DSA. + (_gcry_dsa_sign): Likewise. + (_gcry_dsa_verify): Likewise. + (_gcry_dsa_get_nbits): Likewise. + + * elgamal.c (_gcry_elg_check_secret_key): Do not check wether the + algorithm ID does indeed belong to ElGamal. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + (_gcry_elg_get_nbits): Likewise. + (_gcry_elg_generate): Likewise. + + * rsa.c (_gcry_rsa_generate): Do not check wether the algorithm ID + does indeed belong to RSA. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + (_gcry_rsa_get_nbits): Likewise. + +2003-05-30 Moritz Schulte + + * md.c (md_get_algo): Return zero in case to algorithm is enabled. + + * md.c (gcry_md_info): Adjusted for new no-errno-API. + (md_final): Likewise. + (gcry_md_get_algo): Likewise. + * pubkey.c (gcry_pk_get_keygrip): Likewise. + (gcry_pk_ctl): Likewise. + (gcry_pk_algo_info): Likewise. + * des.c (selftest): Likewise. + +2003-05-29 Moritz Schulte + + * md.c (md_enable): Do not forget to release module on error. + (gcry_md_open): Adjusted for new no-errno-API. + (md_open): Likewise. + (md_copy): Likewise. + (gcry_md_copy): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_algo_info): Likewise. + + * cipher.c (gcry_cipher_open): Adjusted for new no-errno-API and + also fixed a locking bug. + (gcry_cipher_encrypt): Adjusted for new no-errno-API. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_ctl): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + +2003-05-28 Moritz Schulte + + * md.c (md_enable): Adjusted for libgpg-error. + (gcry_md_enable): Likewise. + (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + (check_digest_algo): Likewise. + (prepare_macpads): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_ctl): Likewise. + (gcry_md_get): Likewise. + (gcry_md_algo_info): Likewise. + (gcry_md_info): Likewise. + * dsa.c (_gcry_dsa_generate): Likewise. + (_gcry_dsa_check_secret_key): Likewise. + (_gcry_dsa_sign): Likewie. + (_gcry_dsa_verify): Likewise. + * twofish.c (do_twofish_setkey): Likewise. + (twofish_setkey): Likewise. + * cipher.c (gcry_cipher_register): Likewise. + +2003-05-25 Moritz Schulte + + * rijndael.c (do_setkey): Adjusted for libgpg-error. + (rijndael_setkey): Likewise. + * random.c (gcry_random_add_bytes): Likewise. + * elgamal.c (_gcry_elg_generate): Likewise. + (_gcry_elg_check_secret_key): Likewise. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + * rsa.c (_gcry_rsa_generate): Likewise. + (_gcry_rsa_check_secret_key): Likewise. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + * pubkey.c (dummy_generate, dummy_check_secret_key, dummy_encrypt, + dummy_decrypt, dummy_sign, dummy_verify): Likewise. + (gcry_pubkey_register): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (sexp_elements_extract): Likewise. + (sexp_to_key): Likewise. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + (sexp_data_to_mpi): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_decrypt): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_ctl): Likewise. + * cipher.c (dummy_setkey): Likewise. + (check_cipher_algo): Likewise. + (gcry_cipher_open): Likewise. + (cipher_setkey): Likewise. + (gcry_cipher_ctl): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + * cast5.c (cast_setkey): Likewise. + (do_cast_setkey): Likewise. + * arcfour.c (arcfour_setkey): Likewise. + (do_arcfour_setkey): Likewise. + * blowfish.c (do_bf_setkey): Likewise. + (bf_setkey): Likewise. + * des.c (do_des_setkey): Likewise. + (do_tripledes_setkey): Likewise. + +2003-05-22 Moritz Schulte + + * tiger.c: Merged code ussing the U64_C macro from GnuPG. + + * sha512.c: Likewise. + +2003-05-17 Moritz Schulte + + * pubkey.c (gcry_pk_genkey): Fix type: acquire a lock, instead of + releasing it. + +2003-05-11 Moritz Schulte + + * pubkey.c (gcry_pk_testkey): Call REGISTER_DEFAULT_CIPHERS. + (gcry_pk_ctl): Likewise. + +2003-04-27 Moritz Schulte + + * pubkey.c (gcry_pk_genkey): Release sexp after extracted data has + been used. + + * md.c (gcry_md_get_algo_dlen): Simplified, simply call + md_digest_length to do the job. + + * des.c (do_des_setkey): Check for selftest failure not only + during initialization. + (do_tripledes_setkey): Include check for selftest failure. + + * pubkey.c (gcry_pubkey_register_default): New macro + `pubkey_use_dummy', use it. + + * elgamal.c (elg_names): New variable. + (pubkey_spec_elg): Include elg_names. + + * dsa.c (dsa_names): New variable. + (pubkey_spec_dsa): Include dsa_names. + + * rsa.c (rsa_names): New variable. + (pubkey_spec_rsa): Include rsa_names. + + * pubkey.c (gcry_pubkey_lookup_func_name): Compare name also with + the names listed in `sexp_names'. + +2003-04-24 Moritz Schulte + + * pubkey.c (sexp_to_key): New variables: module, pubkey. Adjusted + to new module interface. + (sexp_to_key): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. Removed argument: + r_algotblidx. + (sexp_to_sig): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. + (sexp_to_enc): Likewise. + + (pubkey_get_npkey, pubkey_get_nskey, pubkey_get_nsig, + pubkey_get_nenc): Use strlen to find out the number. + + * rsa.c: Adjust pubkey_spec_rsa to new internal interface. + * dsa.c: Likewise. + * elgamal.c: Likewise. + +2003-04-17 Moritz Schulte + + * pubkey.c (sexp_elements_extract): New function. + * pubkey.c (sexp_to_key): Removed variable `idx', added `err', use + sexp_elements_extract. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + + * pubkey.c: Terminate list correctly. + * md.c: Include sha512/sha384 in digest_table. + +2003-04-16 Moritz Schulte + + * Makefile.am: Include support for sha512.c. + + * sha512.c: New file, merged from GnuPG, with few modifications + for libgcrypt. + + * rand-internal.h: Removed declarations for constructor functions. + + * md.c (md_copy): Call _gcry_module_use for incrementing the usage + counter of the digest modules. + + * rsa.c: Do not include "rsa.h". + * dsa.c: Do not include "dsa.h". + * elgamal.c: Do not include "elgamal.h". + * des.c: Do not include "des.h". + * cast5.c: Do not include "cast5.h". + * blowfish.c: Do not include "blowfish.h". + * arcfour.c: Do not include "arcfour.h". + + * Makefile.am (libcipher_la_DEPENDENCIES): Removed. + (libcipher_la_LIBADD): Removed. + Use Automake conditionals for conditional compilation. + +2003-04-13 Moritz Schulte + + * cipher.c (gcry_cipher_open): Call REGISTER_DEFAULT_CIPHERS. + + * md.c (gcry_md_list): New member: module. + (md_enable): New variable: module, changed use of module and + digest. + (md_enable): Initialize member: module. + (md_close): Call _gcry_module_release. + + * cipher.c (gcry_cipher_open): New variable: module, changed use of + module and cipher. + (struct gcry_cipher_handle): New member: module. + (gcry_cipher_open): Initialize member: module. + (gcry_cipher_close): Call _gcry_module_release. + +2003-04-09 Moritz Schulte + + * cipher.c: Include "ath.h". + * md.c: Likewise. + * pubkey.c: Likewise. + + * cipher.c (ciphers_registered_lock): New variable. + * md.c (digests_registered_lock): New variable. + * pubkey.c (pubkeys_registered_lock): New variable. + + * rndlinux.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndlinux_constructor): Removed function. + + * rndegd.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndegd_constructor): Removed function. + + * rndunix.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndunix_constructor): Removed function. + + * rndw32.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndw32_constructor): Removed function. + + * rndegd.c (rndegd_connect_socket): Simplify code for creating the + egd socket address. + (rndegd_connect_socket): Call log_fatal use instead of + g10_log_fatal. + (egd_gather_random): Renamed to ... + (rndegd_gather_random): ... here. + +2003-04-08 Moritz Schulte + + * rndlinux.c: Do not include "dynload.h". + * rndunix.c: Likewise. + * rndw32.c: Likewise. + + * rndegd.c (rndegd_connect_socket): Factored out from ... + (egd_gather_random): here; call it. + (egd_socket): New variable. + (egd_gather_random): Initialize fd with egd_socket, do not declare + fd static. + (do_read): Merged few changes from GnuPG. FIXME - not finished? + Do not include "dynload.h". + + * rndw32.c (gather_random): Renamed to rndw32_gather_random, do + not declare static. + (gather_random_fast): Renamed to rndw32_gather_random_fast, do not + declare static. + + * rndunix.c (gather_random): Renamed to rndunix_gather_random, do + not declare static. + * rndegd.c (gather_random): Renamed to rndegd_gather_random, do + not declare static. + * rndlinux.c (gather_random): Renamed to rndlinux_gather_random, + do not declare static. + +2003-04-07 Moritz Schulte + + * Makefile.am (libcipher_la_SOURCES): Removed construct.c. + (libcipher_la_SOURCES): Added sha1.c, sha256.c, rmd160.c, md4.c, + md5.c, tiger.c and crc.c + (EXTRA_PROGRAMS): Removed sha1, sha256, rmd160, md4, md5, tiger + and crc. Removed definitions: EXTRA_md4_SOURCES, + EXTRA_md5_SOURCES, EXTRA_rmd160_SOURCES, EXTRA_sha1_SOURCES, + EXTRA_sha256_SOURCES, EXTRA_tiger_SOURCES and EXTRA_crc_SOURCES, + BUILT_SOURCES, DISTCLEANFILES. + + * pubkey.c: Do not include "elgamal.h", "dsa.h" and "rsa.h". + + * Makefile.am (libcipher_la_SOURCES): Removed rsa.h, elgamal.h, + dsa.h, des.h, cast5.h, arcfour.h and blowfish.h. + + * rsa.h: Removed file. + * elgamal.h: Removed file. + * dsa.h: Removed file. + * des.h: Removed file. + * cast5.h: Removed file. + * arcfour.h: Removed file. + * blowfish.h: Removed file. + + * Makefile.am (libcipher_la_SOURCES): Removed dynload.c and + dynload.h. + + * rsa.c (pubkey_spec_rsa): New variable. + * dsa.c (pubkey_spec_rsa): New variable. + * elgamal.c (pubkey_spec_elg): New variable. + + * rsa.c (_gcry_rsa_get_info): Removed function. + * elgamal.c (_gcry_elg_get_info): Removed function. + * dsa.c (_gcry_dsa_get_info): Removed function. + + * tiger.c (tiger_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_tiger_constructor): Removed function. + + * sha1.c (sha1_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha1_constructor): Removed function. + + * sha256.c (sha256_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha256_constructor): Removed function. + + * rmd160.c (rmd160_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rmd160_constructor): Removed function. + + * md5.c (md5_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md5_constructor): Removed function. + + * md4.c (md4_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md4_constructor): Removed function. + + * crc.c (crc_get_info): Removed function. + + * arcfour.c (do_arcfour_setkey): Changed type of context argument + to `void *', added local variable for cast, adjusted callers. + (arcfour_setkey): Likewise. + (encrypt_stream): Likewise. + * cast5.c (cast_setkey): Likewise. + (encrypt_block): Likewise. + * rijndael.c (rijndael_setkey): Likewise. + (rijndael_encrypt): Likewise. + (rijndael_decrypt): Likewise. + * twofish.c (twofish_setkey): Likewise. + (twofish_encrypt): Likewise. + (twofish_decrypt): Likewise. + * des.c (do_des_setkey): Likewise. + (do_des_encrypt): Likewise. + (do_des_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + * blowfish.c (bf_setkey: Likewise. + (encrypt_block): Likewise. + (decrypt_block): Likewise. + + * arcfour.c (encrypt_stream): Likewise. + + * rijndael.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * twofish.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * cast5.c (CIPHER_ALGO_CAST5): Removed. + + * blowfish.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + (CIPHER_ALGO_BLOWFISH): Removed symbol. + * cast5.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Likewise. + * des.c (selftest_failed): Removed. + (initialized): New variable. + (do_des_setkey): Run selftest, if not yet done. + (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + + * arcfour.c (_gcry_arcfour_get_info): Removed function. + * blowfish.c (_gcry_blowfish_get_info): Removed function. + * cast5.c (_gcry_cast5_get_info): Removed function. + * des.c (_gcry_des_get_info): Removed function. + * rijndael.c (_gcry_rijndael_get_info): Removed function. + * twofish.c (_gcry_twofish_get_info): Removed function. + + * arcfour.c (cipher_spec_arcfour): New variable. + * twofish.c (cipher_spec_twofish, cipher_spec_twofish128): New + variables. + * rijndael.c (cipher_spec_aes, cipher_spec_aes192, + cipher_spec256): New variables. + * des.c (cipher_spec_des, cipher_spec_tripledes): New variables. + * cast5.c (cipher_spec_cast5): New variable. + * blowfish.c (cipher_spec_blowfish): Likewise. + + * twofish.c: Do not include "dynload.h". + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * rijndael.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + + * arcfour.c: Include "cipher.h". + * twofish.c: Likewise. + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + + * twofish.c (twofish_setkey): Declared argument `key' const. + (twofish_encrypt): Declared argument `inbuf' const. + (twofish_decrypt): Likewise. + + * rijndael.c (rijndael_setkey): Declared argument `key' const. + (rijndael_encrypt): Declared argument `inbuf' const. + (rijndael_decrypt): Likewise. + + * des.c (do_des_setkey): Declared argument `key' const. + (do_tripledes_setkey): Likewise. + (do_des_encrypt): Declared argument `inbuf' const. + (do_des_decrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_decrypt): Likewise. + + * cast5.c (encrypt_block): Declared argument `inbuf' const. + (decrypt_block): Likewise. + (cast_setkey): Declared argument `key' const. + + * blowfish.c (do_bf_setkey): Declared argument `key' const. + (encrypt_block): Declared argument `inbuf' const. + (encrypt_block): Likewise. + + + + * cipher.c: Remove CIPHER_ALGO_DUMMY related code. + Removed struct cipher_table_s. + Changed definition of cipher_table. + Removed definition of disabled_algos. + (ciphers_registered, default_ciphers_registered): New variables. + (REGISTER_DEFAULT_CIPHERS): New macro. + (dummy_setkey): Declared argument `key' const. + (dummy_encrypt_block): Declared argument `inbuf' const. + (dummy_encrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_setkey): Use `unsigned char' instead of `byte'. + (dummy_encrypt_block): Likewise. + (dummy_decrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_decrypt_stream): Likewise. + (gcry_cipher_register_default): New function. + (gcry_cipher_lookup_func_id): New function. + (gcry_cipher_lookup_func_name): New function. + (gcry_cipher_lookup_id): New function. + (gcry_cipher_lookup_name): New function. + (gcry_cipher_id_new): New function. + (gcry_cipher_register): New function. + (gcry_cipher_unregister): New function. + (setup_cipher_table): Removed function. + (load_cipher_modules): Removed function. + (gcry_cipher_map_name): Adjusted to use new module management. + (cipher_algo_to_string): Likewise. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_keylen): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (struct gcry_cipher_handle): Replaced members algo, algo_index, + blocksize, setkey, encrypt, decrypt, stencrypt, stdecrypt with one + member: cipher. + (gcry_cipher_open): Adjusted code for new handle structure. + (cipher_setkey): Likewise. + (cipher_setiv): Likewise. + (cipher_reset): Likewise. + (do_ecb_encrypt): Likewise. + (do_ecb_decrypt): Likewise. + (do_cbc_encrypt): Likewise. + (do_cbc_decrypt): Likewise. + (do_cfb_encrypt): Likewise. + (do_cfb_decrypt): Likewise. + (do_ctr_encrypt): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (cipher_sync): Likewise. + (gcry_cipher_ctl): Likewise. + + * pubkey.c: Removed struct pubkey_table_s. + Changed definition of pubkey_table. + Removed definition of disabled_algos. + (pubkeys_registered, default_pubkeys_registered): New variables. + (REGISTER_DEFAULT_PUBKEYS): New macro. + (setup_pubkey_table): Removed function. + (load_pubkey_modules): Removed function. + (gcry_pubkey_register_default): New function. + (gcry_pubkey_lookup_func_id): New function. + (gcry_pubkey_lookup_func_name): New function. + (gcry_pubkey_lookup_id): New function. + (gcry_pubkey_lookup_name): New function. + (gcry_pubkey_id_new): New function. + (gcry_pubkey_register): New function. + (gcry_pubkey_unregister): New function. + (gcry_pk_map_name): Adjusted to use new module management. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_get_nbits): Likewise. + (gcry_pk_algo_info): Likewise. + + * md.c: Removed struct md_digest_list_s. + (digest_list): Changed definition. + (digests_registered, default_digests_registered): New variables. + (REGISTER_DEFAULT_DIGESTS): New macro. + (new_list_item): Removed function. + (setup_md_table): Removed function. + (load_digest_module): Removed function. + (gcry_digest_register_default): New function. + (gcry_digest_lookup_func_id): New function. + (gcry_digest_lookup_func_name): New function. + (gcry_digest_lookup_id): New function. + (gcry_digest_lookup_name): New function. + (gcry_digest_id_new): New function. + (gcry_digest_register): New function. + (gcry_digest_unregister): New function. + (GcryDigestEntry): New type. + (struct gcry_md_context): Adjusted type of `list'. + (gcry_md_map_name): Adjusted to use new module management. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + +2003-04-07 Moritz Schulte + + * pubkey.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA, + PUBKEY_ALGO_RSA with GCRY_PK_RSA and PUBKEY_ALGO_ELGAMAL with + GCRY_PK_ELG. + + * dsa.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA. + +2003-04-01 Moritz Schulte + + * des.c: Removed checks for GCRY_CIPHER_3DES and GCRY_CIPHER_DES. + +2003-03-31 Moritz Schulte + + * tiger.c (tiger_get_info): Do not declare static. + * sha256.c (sha256_get_info): Likewise. + * sha1.c (sha1_get_info): Likewise. + * rmd160.c (rmd160_get_info): Likewise. + * md5.c (md5_get_info): Likewise. + * md4.c (md4_get_info): Likewise. + * crc.c (crc_get_info): Likewise. + + * md.c (load_digest_module): Call setup_md_table during + initialization. + (new_list_item): Link new element into digest_list. + + * cipher.c (do_ctr_decrypt): Made do_ctr_encrypt act as a wrapper + for do_ctr_encrypt, since these functions are identical. + +2003-03-30 Simon Josefsson + + * cipher.c (struct gcry_cipher_handle): Add counter field. + (gcry_cipher_open): Add CTR. + (cipher_reset): Clear counter field. + (do_ctr_encrypt, do_ctr_decrypt): New functions. + (cipher_encrypt, cipher_decrypt): Call CTR functions. + (gcry_cipher_ctl): Add SET_CTR to set counter. + +2003-03-30 Moritz Schulte + + * rsa.c (_gcry_rsa_blind): New function. + (_gcry_rsa_unblind): New function. + (_gcry_rsa_decrypt): Use _gcry_rsa_blind and _gcry_rsa_decrypt. + +2003-03-26 Moritz Schulte + + * dynload.c (_gcry_enum_gnupgext_pubkeys): Adjust `encrypt' and + `decrypt' function arguments. + (_gcry_enum_gnupgext_pubkeys): Likewise. + * dynload.h: Likewise. + + * pubkey.c (dummy_decrypt): Add argument: int flags. + (dummy_encrypt): Likewise. + + * elgamal.c (_gcry_elg_encrypt): Add argument: int flags. + (_gcry_elg_decrypt): Likewise. + + * rsa.c (_gcry_rsa_encrypt): Add argument: int flags. + (_gcry_rsa_decrypt): Likewise. + + * pubkey.c: Add `flags' argument to members `encrypt' and + `decrypt' of struct `pubkey_table_s'. + + * rsa.h: Add `flags' argument to function declarations. + * elgamal.h: Likewise. + + * pubkey.c (sexp_data_to_mpi): New variable: int parsed_flags. + (sexp_data_to_mpi): Set `parsed_flags'. + (sexp_data_to_mpi): New argument: int *flags. + (gcry_pk_encrypt): New variable: int flags. + (gcry_pk_encrypt): Pass `flags' to pubkey_encrypt. + (pubkey_encrypt): New variable: int flags. + (pubkey_encrypt): Pass `flags' to pubkey encrypt function. + (pubkey_decrypt): Likewise. + (pubkey_decrypt): Pass `flags' to pubkey encrypt function. + (gcry_pk_encrypt): Include `flags' s-exp in return list. + (sexp_to_enc): New argument: int *flags. + (gcry_pk_decrypt): New variable: int flags. + (gcry_pk_decrypt): Pass `flags' to pubkey_decrypt. + (sexp_to_enc): New variable: int parsed_flags. + (sexp_to_enc): Set `parsed_flags'. + +2003-03-22 Simon Josefsson + + * cipher.c (gcry_cipher_open, do_cbc_encrypt) + (gcry_cipher_encrypt): Support GCRY_CIPHER_CBC_MAC. + (gcry_cipher_ctl): Support GCRYCTL_SET_CBC_MAC. + +2003-03-19 Werner Koch + + * primegen.c (gen_prime): New args EXTRA_CHECK and EXTRA_CHECK_ARG + to allow for a user callback. Changed all callers. + (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Ditto, pass them to gen_prime. + * rsa.c (check_exponent): New. + (generate): Use a callback to ensure that a given exponent is + actually generated. + +2003-03-12 Moritz Schulte + + * primegen.c: Initialize `no_of_small_prime_numbers' statically. + (gen_prime): Remove calculation of `no_of_small_prime_numbers'. + +2003-03-03 Moritz Schulte + + * md.c (gcry_md_ctl): Rewritten to use same style like the other + functions dispatchers. + +2003-03-02 Moritz Schulte + + * cipher.c (struct gcry_cipher_handle): New member: algo_index. + (gcry_cipher_open): Allocate memory for two cipher contexts. + Initialize algo_index. + (cipher_setkey): Duplicate context into reserved memory. + (cipher_reset): New function, which resets the context and clear + the IV. + (gcry_cipher_ctl): Call cipher_reset. + +2003-02-23 Moritz Schulte + + * cipher.c: Remove (bogus) `digitp' macro definition. + * md.c: Likewise. + + * blowfish.c (burn_stack): Removed. + * arcfour.c (burn_stack): Likewise. + * cast5.c (burn_stack): Likewise. + * des.c (burn_stack): Likewise. + * md4.c (burn_stack): Likewise. + * md5.c (burn_stack): Likewise. + * random.c (burn_stack): Likewise. + * rijndael.c (burn_stack): Likewise. + * rmd160.c (burn_stack): Likewise. + * sha1.c (burn_stack): Likewise. + * sha256.c (burn_stack): Likewise. + * tiger.c (burn_stack): Likewise. + * twofish.c (burn_stack): Likewise. + + * blowfish.c: Changed all occurences of burn_stack to + _gcry_burn_stack. + * arcfour.c: Likewise. + * cast5.c: Likewise. + * des.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * random.c: Likewise. + * rijndael.c: Likewise. + * rmd160.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + * tiger.c: Likewise. + * twofish.c: Likewise. + + * arcfour.c (_gcry_arcfour_get_info): Use GCRY_CIPHER_ARCFOUR + instead of hard-coded value `301'. + +2003-01-24 Werner Koch + + * random.c (_gcry_register_random_progress): New. + (_gcry_random_progress): New. + + * rndlinux.c (gather_random): Call the random progress function. + +2003-01-23 Werner Koch + + * rsa.c (generate): New arg USE_E to request a specific public + exponent. + (_gcry_rsa_generate): Ditto. + * elgamal.c (_gcry_elg_generate): Must add an dummy argument + instead of USE_E. + * dsa.c (_gcry_dsa_generate): Ditto. + * pubkey.c (dummy_generate): Ditto. + (pubkey_generate): Add USE_E arg and pass it down. + (gcry_pk_genkey): Detect "rsa-use-e" parameter and pass it to generate. + + * pubkey.c (sexp_to_enc): New arg RET_MODERN. + (gcry_pk_decrypt): Make use of it to return a real S-expression. + Return better error codes. + (gcry_pk_verify): Return better error codes. + +2003-01-21 Werner Koch + + * random.c (gcry_random_add_bytes): Add QUALITY argument, let + function return an error code and disable its core for now. + +2003-01-21 Timo Schulz + + * random.c (gcry_random_add_bytes): New. Function to add external + random to the pool. + +2003-01-20 Simon Josefsson + + * crc.c: New. + * Makefile.am (EXTRA_PROGRAMS, EXTRA_crc_SOURCES): Add crc.c. + * md.c (gcry_md_get_algo_dlen): Add values for CRC. + +2003-01-20 Werner Koch + + * sha256.c: New. + * bithelp.h (ror): New. + * Makfile.am: Add sha256.c. + * md.c (oid_table): Add values for SHA256 et al. + (gcry_md_get_algo_dlen): Likewise + +2003-01-20 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Implemented keygrips for DSA + and ElGamal. + +2003-01-17 Werner Koch + + * cipher.c (gcry_cipher_encrypt): Reworked so that the output will + never contain the plaintext even if the caller did not checked the + return value. + + * md.c (gcry_md_get_algo): Changed error code to GCRYERR_GENERAL + because we don't have an invalid md algo but no algorithm enabled. + + * pubkey.c (gcry_pk_genkey): Changed error code for bounds check + of table parameters to GCRYERR_INTERNAL. + + * md.c (gcry_md_open): Partly reverted Timo's change from + 2002-10-10 by removing the check for the algorithm. An algorithm + of 0 is allowed and anyway we should not double check it or check + it using a different function. Also fixed the flags check. + + * pubkey.c (gcry_pk_encrypt): Make sure that R_CIPH points to NULL + on error. + (gcry_pk_decrypt): Ditto for R_PLAIN. + (gcry_pk_sign): Ditto for R_SIG. + (gcry_pk_genkey): Ditto for R_KEY. + +2003-01-16 Werner Koch + + * md.c (gcry_md_write): Changed 2nd argument type to void*. + (gcry_md_hash_buffer): Changed type of boths buffers to void*. + (gcry_md_setkey): Changed 2nd argument type to void*. + +2003-01-15 Werner Koch + + * pubkey.c (sexp_data_to_mpi): New. This handles pkcs1 padding. + (gcry_pk_sign, gcry_pk_verify): Use it here. + (gcry_pk_encrypt): And here. + (pubkey_verify): Add debug code. + (sexp_to_enc): Handle flags in the input and return the pkcs1 flag + in a new parameter. + (gcry_pk_decrypt): Prepare for future pkcs1 handling. + +2002-12-19 Werner Koch + + * random.c (_gcry_random_initialize): New. + +2002-12-16 Werner Koch + + * cipher.c: Added a Teletrust specific OID for 3DES. + +2002-12-12 Werner Koch + + * md.c: Added another oddball OIW OID (sha-1WithRSAEncryption). + +2002-11-23 Werner Koch + + * md.c (load_digest_module): Enlarged checked_algos bitmap. + * md4.c (func_table): Fixed entry for md4. + Both by Simon Josephson. + (transform): Copy data to get the alignment straight. Tested only + on i386. + +2002-11-10 Simon Josefsson + + * cipher.c (gcry_cipher_open): Don't reject CTS flag. + (do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt) + (gcry_cipher_encrypt, cipher_decrypt) + (gcry_cipher_decrypt): Support CTS flag. + (gcry_cipher_ctl): Toggle CTS flag. + +2002-11-10 Werner Koch + + * md4.c: New. By Simon Josefsson. + * Makefile.am (EXTRA_PROGRAMS): Add md4.c. + * md.c (oid_table,gcry_md_get_algo_dlen): MD4 support. + +2002-10-14 Werner Koch + + * arcfour.c (do_encrypt_stream): Don't use increment op when + assigning to the same variable. + +2002-10-10 Timo Schulz + + * pubkey.c (gcry_pk_genkey): Check boundaries. + + * md.c (gcry_md_open): Check that algo is available and only + valid flag values are used. + (gcry_md_get_algo): Add error handling. + +2002-09-26 Werner Koch + + * md.c: Include an OID for TIGER. + * tiger.c (tiger_get_info): Use a regular OID. + +2002-09-17 Werner Koch + + * random.c: Replaced mutex.h by the new ath.h. Changed all calls. + +2002-09-16 Werner Koch + + * arcfour.c (do_encrypt_stream): Use register modifier and modulo. + According to Nikos Mavroyanopoulos this increases perfromace on + i386 system noticable. And I always tought gcc is clever enough. + * md5.c (transform): Use register modifier. + * rmd160.c (transform): Ditto. + * sha1.c (transform): Ditto. We hope that there are 6 free registers. + * random.c (gcry_randomize): Rewrote to avoid malloc calls. + + * rndlinux.c (gather_random): Replaced remaining fprintfs by log_*. + * arcfour.c (do_arcfour_setkey): Ditto. + * twofish.c (do_twofish_setkey): Ditto. + * rndegd.c (gather_random): Ditto. + * rijndael.c (do_setkey): Ditto. + * random.c (_gcry_random_dump_stats): Ditto. + * primegen.c (_gcry_generate_elg_prime): Ditto. + * des.c (_gcry_des_get_info): Ditto. + * cast5.c (do_cast_setkey): Ditto. + * blowfish.c (do_bf_setkey): Ditto. + +2002-08-26 Werner Koch + + * des.c (weak_keys): Fixed one entry in the table and compared + all entries against the literature. + (selftest): Checksum the weak key table. + +2002-08-21 Werner Koch + + * pubkey.c: Enable keygrip calculation for "openpgp-rsa". + +2002-08-17 Werner Koch + + * cipher.c (setup_cipher_table): Don't overwrite the DES entry + with the entry for DUMMY. + +2002-08-14 Werner Koch + + * des.c (do_des_setkey,do_des_encrypt, do_des_decrypt): New. + (_gcry_des_get_info): Support plain old DES. + * cipher.c (setup_cipher_table): Put DES into the table. + +2002-07-25 Werner Koch + + * rndunix.c (_gcry_rndunix_constructor): Prefixed with _gcry_. + Noted by Stephan Austermuehle. + +2002-07-08 Timo Schulz + + * rndw32.c: Replaced the m_ memory functions with the real + gcry_ functions. Renamed all g10_ prefixed functions to log_. + +2002-06-12 Werner Koch + + * rsa.c (generate): Use e = 65537 for now. + +2002-06-11 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Allow a "protected-private-key". + +2002-06-05 Timo Schulz + + * cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): + Check that the input size is a multiple of the blocksize. + +2002-05-23 Werner Koch + + * md.c (oid_table): Add an rsadsi OID for MD5. + +2002-05-21 Werner Koch + + * primegen.c, elgamal.c, dsa.c (progress): Do not print anything + by default. Pass an extra identifying string to the callback and + reserved 2 argumenst for current and total counters. Changed the + register function prototype. + +2002-05-17 Werner Koch + + * rndegd.c (rndegd_constructor): Fixed name of register function + and prefixed the function name with _gcry_. + * rndw32.c (rndw32_constructor): Ditto. + * tiger.c (tiger_constructor): Ditto. + + * Makefile.am: Removed all dynamic loading stuff. + * dynload.c: Ditto. Now only used for the constructor system. + +2002-05-15 Werner Koch + + * random.c (gcry_random_bytes,gcry_random_bytes_secure) + (gcry_randomize): Make sure we are initialized. + +2002-05-14 Werner Koch + + Changed license of most files to the LGPL. + +2002-05-02 Werner Koch + + * random.c (_gcry_fast_random_poll): Initialize the module so the + mutex can be used. + + * primegen.c (small_prime_numbers): Moved table from smallprime.c + * smallprime.c: File removed. + + * des.c (leftkey_swap, rightkey_swap, working_memcmp): Made static. + + * cipher.c (gcry_cipher_map_name): Map "RIJNDAEL" to "AES". + * rijndael.c (rijndael_get_info): We do only support a 128 bit + blocksize so it makes sense to change the algorithm strings to + AES. + + * tiger.c (tiger_final): Removed superfluous token pasting operators. + * md5.c (md5_final): Ditto. + +2002-04-30 Werner Koch + + * cipher.c: Fixed list of copyright years. + +2002-03-18 Werner Koch + + * random.c (initialize): Initialize the new pool lock mutex. + (_gcry_fast_random_poll): Add locking and moved main + code out to... + (do_fast_random_poll): new function. + (read_pool): Use the new function here. + (get_random_bytes): Add locking. + (_gcry_update_random_seed_file): Ditto. + +2002-03-11 Werner Koch + + * md.c: Add rsaSignatureWithripemd160 to OID table. + +2002-02-20 Werner Koch + + * sha1.c: Removed a left over comment note. The code has been + rewritten from scratch in 1998. Thanks to Niels Möller for + reporting this misleading comment. + +2002-02-18 Werner Koch + + * rndunix.c (rndunix_constructor): Use the the new prefixed + function name. Reported by Jordi Mallach. + +2002-02-10 Werner Koch + + * random.c (mix_pool): Carry an extra failsafe_digest buffer + around to make the function more robust. + +2002-02-08 Werner Koch + + * random.c (add_randomness): Xor new data into the pool and not + just copy it. This avoids any choosen input attacks which are not + serious in our setting because an outsider won't be able to mix + data in and even then we keep going with a PRNG. Thanks to Stefan + Keller for pointing this out. + +2002-01-04 Werner Koch + + * pubkey.c (gcry_pk_genkey): Do not release skey - it is static. + + * primegen.c (gen_prime): Of course we should use set_bit + and not set_highbit to set the second high bit. + +2001-12-18 Werner Koch + + * rsa.c (generate): Loop until we find the exact modulus size. + Changed the exponent to 41. + (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings. + * primegen.c (gen_prime): Set 2 high order bits for secret primes. + + * Makefile.am (DISTCLEANFILES): Include construct.c. + +2001-12-17 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): New - experimental. + +2001-12-11 Werner Koch + + * cipher.c: Added OIDs for AES. + (gcry_cipher_mode_from_oid): New. + (gcry_cipher_map_name): Moved OID search code to .. + (search_oid): .. new function. + +2001-12-10 Werner Koch + + * pubkey.c (gcry_pk_encrypt): Find the signature algorithm by name + and not by number. + + * pubkey.c (gcry_pk_encrypt,gcry_pk_decrypt,gcry_pk_sign) + (gcry_pk_verify,gcry_pk_testkey, gcry_pk_genkey) + (gcry_pk_get_nbits): Release the arrays. Noted by Nikos + Mavroyanopoulos. + +2001-12-06 Werner Koch + + * cipher.c (gcry_cipher_map_name): Look also for OIDs prefixed + with "oid." or "OID.". + +2001-12-05 Werner Koch + + * pubkey.c (algo_info_table): Fixed entry for openpgp-rsa. + +2001-11-24 Werner Koch + + * pubkey.c: Added the rsaEncryption OID to the tables. + (sexp_to_key): Add an arg to return the index of the algorithm, + changed all callers. + (gcry_pk_sign): Find the signature algorithm by name and not by + number. + (gcry_pk_get_nbits): Fixed so that we can now really pass a secret + key to get the result. + + * md.c (gcry_md_map_name): Look also for OIDs prefixed with "oid." + or "OID." so that an OID string can be used as an S-Exp token. + +2001-11-20 Werner Koch + + * md.c (gcry_md_map_name): Lookup by OID if the the name begins + with a digit. + (oid_table): New. + +2001-11-16 Werner Koch + + * md.c (gcry_md_info): New operator GCRYCTL_IS_ALGO_ENABLED. + +2001-11-07 Werner Koch + + * md.c (gcry_md_hash_buffer): Close the handle which was left open + for algorithms other than rmd160. + +2001-08-08 Werner Koch + + * rndw32.c (gather_random): Use toolhelp in addition to the NT + gatherer for Windows2000. Suggested by Sami Tolvanen. + + * random.c (read_pool): Fixed length check, this used to be one + byte to strict. Made an assert out of it because the caller has + already made sure that only poolsize bytes are requested. + Reported by Marcus Brinkmann. + +2001-08-03 Werner Koch + + * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return + errors. We have to change the interface to all ciphers to make + this really work but we should do so to prepare for hardware + encryption modules. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and + set lasterr. + (gcry_cipher_ctl): Make sure that errors from setkey are returned. + +2001-08-02 Werner Koch + + * rndlinux.c (gather_random): casted a size_t arg to int so that + the format string is correct. Casting is okay here and avoids + translation changes. + + * random.c (fast_random_poll): Do not check the return code of + getrusage. + + * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 + and 8. + + * tiger.c (print_abc,print_data): Removed. + + * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c + (burn_stack): New. Add wrappers for most functions to be able to + call burn_stack after the function invocation. This methods seems + to be the most portable way to zeroise the stack used. It does + only work on stack frame based machines but it is highly portable + and has no side effects. Just setting the automatic variables at + the end of a function to zero does not work well because the + compiler will optimize them away - marking them as volatile would + be bad for performance. + * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. + * random.c (burn_stack): New. + (mix_pool): Use it here to burn the stack of the mixblock function. + + * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places. + Thanks to Tommi Komulainen. + + * arcfour.c (arcfour_setkey): Check the minimim keylength against + bytes and not bits. + (selftest): Must reset the key before decryption. + +2001-05-31 Werner Koch + + * sha1.c (sha1_init): Made static. + + Changed all g10_ prefixed function names as well as some mpi_ + function names to cope with the introduced naming changes. + + * md.c (prepare_macpads): Made key const. + +2001-05-28 Werner Koch + + * rndegd.c (gather_random): Removed the use of tty_printf. + +2001-03-29 Werner Koch + + * md5.c (md5_final): Fixed calculation of hashed length. Thanks + to disastry@saiknes.lv for pointing out that it was horrible wrong + for more than 512MB of input. + * sha1.c (sha1_final): Ditto. + * rmd160.c (rmd160_final): Ditto. + * tiger.c (tiger_final): Ditto. + + * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to + avoid name clashes with an encrypt function in stdlib.h of + Dynix/PIX. Thanks to Gene Carter. + * elgamal.c (encrypt,do_encrypt): Ditto. + + * twofish.c (gnupgext_enum_func): Use only when when compiled as a + module. + * rijndael.c (gnupgext_enum_func): Ditto. + + * tiger.c (tiger_get_info): Return "TIGER192" and not just + "TIGER". By Edwin Woudt. + + * random.c: Always include time.h - standard requirement. Thanks + to James Troup. + + * rndw32.c: Fixes to the macros. + +2001-01-11 Werner Koch + + * cipher.c (cipher_encrypt,gcry_cipher_encrypt): Use blocksize and + not 8. + +2000-12-19 Werner Koch + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch + + * dsa.c (test_keys): Replaced mpi_alloc by gcry_mpi_new and + mpi_free by gcry_mpi_release. + * elgamal.c (test_keys,generate): Ditto, also for mpi_alloc_secure. + * rsa.c (test_keys,generate,rsa_verify): Ditto. + * primegen.c (generate_elg_prime): Ditto. + (gen_prime): Ditto and removed nlimbs. + + * rsa.c (generate): Allocate 2 more vars in secure memory. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-09 Werner Koch + + * arcfour.c, arcfour.h: New. + * cipher.c (cipher_encrypt, cipher_decrypt): Add stream mode. + (setup_cipher_table): Add Arcfour. + (gcry_cipher_open): Kludge to allow stream mode. + +Wed Oct 4 13:16:18 CEST 2000 Werner Koch + + * sha1.c (transform): Use rol() macro. Actually this is not needed + for a newer gcc but there are still aoter compilers. + + * rsa.c (test_keys): Use new random function. + + * md.c (gcry_md_setkey): New function to overcome problems with + const conflics. + (gcry_md_ctl): Pass set key to the new functions. + + * rijndael.c: New. + * cipher.c: Add Rijndael support. + +Mon Sep 18 16:35:45 CEST 2000 Werner Koch + + * rndlinux.c (open_device): Loose random device checking. + By Nils Ellmenreich. + + * random.c (fast_random_poll): Check ENOSYS for getrusage. + * rndunix.c: Add 2 sources for QNX. By Sam Roberts. + + * pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE. + + * rsa.c: Changed the comment about the patent. + (secret): Speed up by using the CRT. For a 2k keys this + is about 3 times faster. + (stronger_key_check): New but unused code to check the secret key. + * Makefile.am: Included rsa.[ch]. + * pubkey.c: Enabled RSA support. + (pubkey_get_npkey): Removed RSA workaround. + +Mon Jul 31 10:04:47 CEST 2000 Werner Koch + + * pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new + gcry_sexp_nth_{data,mpi} functions. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch + + * pubkey.c (exp_to_key,sexp_to_sig,sexp_to_enc,gcry_pk_encrypt, + gcry_pk_decrypt,gcry_pk_sign,gcry_pk_genkey): Changed to work with + the new S-Exp interface. + +Mon Jul 17 16:35:47 CEST 2000 Werner Koch + + * random.c (gather_faked): Replaced make_timestamp by time(2) again. + +Fri Jul 14 19:38:23 CEST 2000 Werner Koch + + * md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP. + + * Makefile.am: Never compile mingw32 as module. + + * Makefile.am: Tweaked module build and removed libtool + + * Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig. + + * elgamal.c (sign): Removed inactive code. + + * rsa.c, rsa.h: New based on the old module version (only in CVS for now). + * pubkey.c (setup_pubkey_table): Added commented support for RSA. + + * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. + (my_popen): Do the FD_CLOEXEC only if it is available + (start_gatherer): Cope with missing _SC_OPEN_MAX + + * rndunix.c: Add some more headers for QNX. By Sam Roberts. + + * rndegd.c (gather_random): Shortcut level 0. + * rndunix.c (gather_random): Ditto. + * rndw32.c (gather_random): Ditto. + + * rndw32.c: Replaced with code from Cryptlib and commented the old stuff. + * rndw32.c: Add some debuging code enabled by an environment variable. + + * random.c (read_seed_file): Binary open for DOSish system + (update_random_seed_file): Ditto. + * random.c [MINGW32]: Include process.h for getpid. + * random.c (fast_random_poll): Add clock_gettime() as fallback for + system which support this POSIX.4 fucntion. By Sam Roberts. + + * random.c (read_seed_file): Removed the S_ISLNK test becuase it + is already covered by !S_ISREG and is not defined in Unixware. + Reported by Dave Dykstra. + (update_random_seed_file): Silently ignore update request when pool + is not filled. + + * random.c (read_seed_file): New. + (set_random_seed_file): New. + (read_pool): Try to read the seeding file. + (update_random_seed_file): New. + + (read_pool): Do an initial extra seeding when level 2 quality random + is requested the first time. This requestes at least POOLSIZE/2 bytes + of entropy. Compined with the seeding file this should make normal + random bytes cheaper and increase the quality of the random bytes + used for key generation. + + * random.c (read_pool): Print a more friendly error message in + cases when too much random is requested in one call. + + * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; + this is not the case for some ESIX and Unixware, although they have + getrusage(). + + * primegen.c (generate_elg_prime): All primes are now generated with + the lowest random quality level. Because they are public anyway we + don't need stronger random and by this we do not drain the systems + entropy so much. + + * primegen.c (register_primegen_progress): New. + * dsa.c (register_pk_dsa_progress): New. + * elgamal.c (register_pk_elg_progress): New. + + * elgamal.c (wiener_map): New. + (gen_k): Use a much smaller k. + (generate): Calculate the qbits using the wiener map and + choose an x at a size comparable to the one choosen in gen_k + + * rmd160.c (rmd160_get_info): Moved casting to the left side due to a + problem with UTS4.3. Suggested by Dave Dykstra. + * sha1.c (sha1_get_info): Ditto. + * tiger.c (tiger_get_info): Ditto. + * md5.c (md5_get_info): Ditto + * des.c (des_get_info): Ditto. + * blowfish.c (blowfish_get_info): Ditto. + * cast5.c (cast5_get_info): Ditto. + * twofish.c (twofish_get_info): Ditto. + +Fri Mar 24 11:25:45 CET 2000 Werner Koch + + * md.c (md_open): Add hmac arg and allocate space for the pads. + (md_finalize): Add HMAC support. + (md_copy): Ditto. + (md_close): Ditto. + (gcry_md_reset): Ditto. + (gcry_md_ctl): Ditto. + (prepare_macpdas): New. + +Mon Mar 13 19:22:46 CET 2000 Werner Koch + + * md.c (gcry_md_hash_buffer): Add support for the other algorithms. + +Mon Jan 31 16:37:34 CET 2000 Werner Koch + + * genprime.c (generate_elg_prime): Fixed returned factors which never + worked for non-DSA keys. + +Thu Jan 27 18:00:44 CET 2000 Werner Koch + + * pubkey.c (sexp_to_key): Fixed mem leaks in case of errors. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch + + * pubkey.c (gcry_pk_decrypt): Implemented. + (gcry_pk_encrypt): Implemented. + (gcry_pk_testkey): New. + (gcry_pk_genkey): New. + (pubkey_decrypt): Made static. + (pubkey_encrypt): Ditto. + (pubkey_check_secret_key): Ditto. + (pubkey_generate): Ditto. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch + + * pubkey.c (pubkey_nbits): Removed and replaced by ... + (gcry_pk_get_nbits): this new one. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch + + * dsa.c: s/mpi_powm/gcry_mpi_powm/g + * elgamal.c: Ditto. + * primegen.c: Ditto. + + * : Replaced g10_opt_verbose by g10_log_verbosity(). + + * Makefile.am (INCLUDES): removed intl, add ../gcrypt + +Fri Nov 19 17:15:20 CET 1999 Werner Koch + + * dynload.c (cmp_filenames): New to replaced compare_filename() in + module. + (register_cipher_extension): Removed the tilde expansion stuff. + * rndeg.c (my_make_filename): New. + + * : Replaced header util.h by g10lib.h + + * random.c (gather_faked): Replaced make_timestamp by time(2). + Disabled wrning printed with tty_printf. + * rndlinux.c (gather_random): Always use fprintf instead of tty_xxx; + this should be replaced by a callback function. + + * primegen.c (gen_prime): Use gcry_mpi_randomize. + (is_prime): Ditto. + * elgamal.c (test_keys): Ditto. + * dsa.c (test_keys): Ditto. + + * cipher.c (gcry_cipher_close): Die on invalid handle. + +Mon Nov 15 21:36:02 CET 1999 Werner Koch + + * elgamal.c (gen_k): Use the new random API. + (generate): Ditto. + * dsa.c (gen_k): Ditto. + (generate): Ditto. + +Sat Nov 13 17:44:23 CET 1999 Werner Koch + + * pubkey.c (disable_pubkey_algo): Made static. + (gcry_pk_ctl): New. + + * random.c (get_random_bits): Renamed to ... + (get_random_bytes): ... this and made static. + (gcry_random_bytes): New. + (gcry_random_bytes_secure): New. + (randomize_buffer): Renamed to ... + (gcry_randomize): ...this. + + * md.c (gcry_md_hash_buffer): New. + + * pubkey.c (gcry_pk_algo_info): 4 new commands. + (pubkey_get_npkey): Made static. + (pubkey_get_nskey): Made static. + (pubkey_get_nsig): Made static. + (pubkey_get_nenc): Made static. + + * pubkey.c: Removed all G10ERR_xxx. + * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO. + * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO. + * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx. + * blowfish.c: Ditto. + * des.c: Ditto. + * twofish.c: Ditto. + * dsa.c: Ditto. + * elgamal.c: Ditto. + + * g10c.c: Removed + + * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL + if we are out of core. + * dynload.c: Replaced all memory allocation functions. + * md.c: Ditto. + * primegen.c: Ditto. + * pubkey.c: Ditto. + * random.c: Ditto. + * rndw32.c: Ditto. + * elgamal.c: Ditto. + * dsa.c: Ditto. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch + + * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). + + * cipher.c: Merged with gcrypt/symapi.c. + + * pubkey.c (string_to_pubkey_algo): Renamed function to ... + (gcry_pk_map_name): ... this. + (pubkey_algo_to_string): Renamed function to ... + (gcry_pk_algo_name): ... this. + (gcry_pk_algo_info): New. + * pubkey.c: Merged with gcrypt/pkapi.c. + + * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for + fixing this bug. + + * md.c: Merged with gcrypt/mdapi.c + +Wed Sep 15 14:39:59 CEST 1999 Michael Roth + + * des.c: Various speed improvements: One bit pre rotation + trick after initial permutation (Richard Outerbridge). + Finished test of SSLeay Tripple-DES patterns. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch + + * rndw32.c: New. + +Mon Sep 13 10:51:29 CEST 1999 Werner Koch + + * bithelp.h: New. + * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h + +Tue Sep 7 16:23:36 CEST 1999 Werner Koch + + * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch + + * des.c (selftest): Add some testpattern + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch + + * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using + in place encryption. Pointed out by Frank Stajano. + +Mon Jul 26 09:34:46 CEST 1999 Werner Koch + + * md5.c (md5_final): Fix for a SCO cpp bug. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch + + * elgamal.c (elg_check_secret_key,elg_encrypt + elg_decrypt,elg_sign,elg_verify): Sanity check on the args. + * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. + + * pubkey.c (disable_pubkey_algo): New. + (check_pubkey_algo2): Look at disabled algo table. + * cipher.c (disable_cipher_algo): New. + (check_cipher_algo): Look at disabled algo table. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch + + * dsa.c (gen_k): Changed algorithm to consume less random bytes + * elgamal.c (gen_k): Ditto. + + * random.c (random_dump_stats): New. + +Thu Jul 1 12:47:31 CEST 1999 Werner Koch + + * primegen.c, elgamal.c, dsa.c (progess): New and replaced all + fputc with a call to this function. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch + + * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. + + * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. + + * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). + * Makefile.am (install-exec-hook): Removed. + +Sun May 23 14:20:22 CEST 1999 Werner Koch + + * cipher.c (setup_cipher_table): Enable Twofish + + * random.c (fast_random_poll): Disable use of times() for mingw32. + +Mon May 17 21:54:43 CEST 1999 Werner Koch + + * dynload.c (register_internal_cipher_extension): Minor init fix. + +Tue May 4 15:47:53 CEST 1999 Werner Koch + + * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug + that we didn't correct for step when passing the prime to the + Rabin-Miller test which led to bad performance (Stefan Keller). + (check_prime): Add a first Fermat test. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch + + * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. + + * random.c (randomize_buffer): alway use secure memory because + we can't use m_is_secure() on a statically allocated buffer. + + * twofish.c: Replaced some macros by a loop to reduce text size. + * Makefile.am (twofish): No more need for sed editing. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch + + * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. + + * blowfish.c: Dropped the Blowfish 160 mode. + * cipher.c (cipher_open): Ditto. + (setup_cipher_table): Ditto. And removed support of twofish128 + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + + * twofish.c: Applied Matthew Skala's patches for 256 bit key. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + +Sat Mar 20 11:44:21 CET 1999 Werner Koch + + * rndlinux.c (tty_printf) [IS_MODULE]: Removed. + + * rndegd.c (gather_random): Some fixes. + +Wed Mar 17 13:09:03 CET 1999 Werner Koch + + * rndegd.c (do_read): New. + (gather_random): Changed the implementation. + +Mon Mar 8 20:47:17 CET 1999 Werner Koch + + * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. + +Fri Feb 26 17:55:41 CET 1999 Werner Koch + + * md.c: Nearly a total rewrote. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch + + * cipher.c (context): Fixed alignment + * md.c: Ditto. + + * rndegd.c: New + +Mon Feb 22 20:04:00 CET 1999 Werner Koch + + * rndegd.c: New. + +Wed Feb 10 17:15:39 CET 1999 Werner Koch + + * Makefile.am: Modules are now figured out by configure + * construct.c: New. Generated by configure. Changed all modules + to work with that. + * sha1.h: Removed. + * md5.h: Removed. + + * twofish.c: Changed interface to allow Twofish/256 + + * rndunix.c (start_gatherer): Die on SIGPIPE. + +Wed Jan 20 18:59:49 CET 1999 Werner Koch + + * rndunix.c (gather_random): Fix to avoid infinite loop. + +Sun Jan 17 11:04:33 CET 1999 Werner Koch + + * des.c (is_weak_key): Replace system memcmp due to bugs + in SunOS's memcmp. + (des_get_info): Return error on failed selftest. + * twofish.c (twofish_setkey): Return error on failed selftest or + invalid keylength. + * cast5.c (cast_setkey): Ditto. + * blowfish.c (bf_setkey): Return error on failed selftest. + +Tue Jan 12 11:17:18 CET 1999 Werner Koch + + * random.c (random_is_faked): New. + + * tiger.c: Only compile if we have the u64 type + +Sat Jan 9 16:02:23 CET 1999 Werner Koch + + * rndunix.c (gather_random): check for setuid. + + * Makefile.am: Add a way to staically link random modules + +Thu Jan 7 18:00:58 CET 1999 Werner Koch + + * md.c (md_stop_debug): Do a flush first. + (md_open): size of buffer now depends on the secure parameter + +Sun Jan 3 15:28:44 CET 1999 Werner Koch + + * rndunix.c (start_gatherer): Fixed stupid ==/= bug + +1998-12-31 Geoff Keating + + * des.c (is_weak_key): Rewrite loop end condition. + +Tue Dec 29 14:41:47 CET 1998 Werner Koch + + * random.c: add unistd.h for getpid(). + (RAND_MAX): Fallback value for Sun. + +Wed Dec 23 17:12:24 CET 1998 Werner Koch + + * md.c (md_copy): Reset debug. + +Mon Dec 14 21:18:49 CET 1998 Werner Koch + + * random.c (read_random_source): Changed the interface to the + random gathering function. + (gather_faked): Use new interface. + * dynload.c (dynload_getfnc_fast_random_poll): Ditto. + (dynload_getfnc_gather_random): Ditto. + * rndlinux.c (gather_random): Ditto. + * rndunix.c (gather_random): Ditto. + +Sat Dec 12 18:40:32 CET 1998 Werner Koch + + * dynload.c (SYMBOL_VERSION): New to cope with system which needs + underscores. + + * rndunix.c: Rewrote large parts + +Thu Dec 10 20:15:36 CET 1998 Werner Koch + + * dynload.c (load_extension): increased needed verbosity level. + + * random.c (fast_random_poll): Fallback to a default fast random + poll function. + (read_random_source): Always use the faked entroy gatherer if no + gather module is available. + * rndlinux.c (fast_poll): Removed. + * rndunix.c (fast_poll): Removed. + + +Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-*.c: Removed. + * rndlinux.c : New. + * rndunix.c : New. + * random.c : Restructured the interface to the gather modules. + (intialize): Call constructor functions + (read_radnom_source): Moved to here. + * dynload.c (dynload_getfnc_gather_random): New. + (dynload_getfnc_fast_random_poll): New. + (register_internal_cipher_extension): New. + (register_cipher_extension): Support of internal modules. + +Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (read_random_source): Removed the assert. + +Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) + + * pubkey.c: Hack to allow us to give some info about RSA keys back. + +Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c: Support for DLD + +Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c: Now uses names from configure for /dev/random. + +1998-10-10 SL Baur + + * Makefile.am: fix sed -O substitutions to catch -O6, etc. + +Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) + * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. + +Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest): New. + (md_reset): New. + +Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. + +Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) + + * des.c: Some patches from Michael. + +Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) + + * des.c : New file from Michael Roth + +Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) + + * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. + +Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) + + * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. + +Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) + + * Makefile.am: Fixes to allow a different build directory + +Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) + + * random.c (get_random_byte): Removed and changed all callers + to use get_random_bits() + +Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) + + * cipher.c : Support for other blocksizes + (cipher_get_blocksize): New. + * twofish.c: New. + * Makefile.am: Add twofish module. + +Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Simple alloc if secure_alloc is not set. + (get_random_bits): Ditto. + +Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c (load_extension): Function now nbails out if + the program is run setuid. + +Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_hash_buffer): New. + +Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_open): algos >=100 use standard CFB + +Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am: Support for extensions + +Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (mix_pool): simpler handling for level 0 + +Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c: Removed from dist, will reappear as dynload module + +Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pubkey.c: Major changes to allow extensions. Changed the inteface + of all public key ciphers and added the ability to load extensions + on demand. + + * misc.c: Removed. + +Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) + + * dynload.c: New. + * cipher.c: Major changes to allow extensions. + +Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Major internal chnages to support extensions. + * blowfish.c (blowfish_get_info): New and made all internal + functions static, changed heder. + * cast5.c (cast5_get_info): Likewise. + +Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (transform): Fix for big endian + + * cipher.c (do_cfb_decrypt): Big endian fix. + +Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_get_oid): Add a new one for TIGER. + +Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Add support for a dummy cipher + +Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): fixed sigbus - I should better + add Christian von Roques's new implemenation of rmd160_write. + +Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New + * random.c: Moved system specific functions to rand-****.c + +Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fast_random_poll): add call to gethrtime. + +Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): choosing x was not correct, could + yield 6 bytes which are not from the random pool, tsss, tsss.. + +Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Add arg mode, changed all + callers and implemented mode 1. + +Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_get_keylen): New. + +Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c, tiger.h: New. + +Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (check_pubkey_algo2): New. + +Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: New + * misc.c (check_cipher_algo): Moved to cipher.c + * cast5.c: Moved many functions to cipher.c + * blowfish.c: Likewise. + +Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cast5.c: Implemented and tested. + +Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): Faster generation of x in some cases. + +Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * blowfish.c (blowfish_decode_cfb): changed XOR operation + (blowfish_encode_cfb): Ditto. + +Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sha1.c (transform): Rewrote + + * blowfish.c (encrypt): Unrolled for rounds == 16 + (decrypt): Ditto. + +Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): Unrolled the loop. + +Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Add pool_balance stuff. + (get_random_bits): New. + + * elgamal.c (elg_generate): Now uses get_random_bits to generate x. + + +Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest_length): New. + +Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c (dsa_verify): Works. + +Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c, dsa.h: Removed some unused code. + +Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_open): Add call to fast_random_poll. + blowfish.c (blowfish_setkey): Ditto. + +Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_mixblock): New. + * random.c: Restructured to start with a new RNG implementation. + * random.h: New. + +Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gost.c, gost.h: Removed because they did only contain trash. + +Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fill_buffer): removed error message if n == -1. + +Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_enable): No init if called twice. + +Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Changed the progress printing. + (gen_prime): Ditto. + +Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md5.c, md.5 : Replaced by a modified version of md5.c from + GNU textutils 1.22. + +Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c, md.h : New debugging support + +Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (cipher_algo_to_string): New + (pubkey_algo_to_string): New. + (digest_algo_to_string): New. + + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt/cipher/Makefile.am b/grub-core/lib/libgcrypt/cipher/Makefile.am new file mode 100644 index 000000000..76cdc96ad --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/Makefile.am @@ -0,0 +1,83 @@ +# Makefile for cipher modules +# Copyright (C) 1998, 1999, 2000, 2001, 2002, +# 2003, 2009 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . + +# Process this file with automake to produce Makefile.in + +EXTRA_DIST = Manifest + +# Need to include ../src in addition to top_srcdir because gcrypt.h is +# a built header. +AM_CPPFLAGS = -I../src -I$(top_srcdir)/src +AM_CFLAGS = $(GPG_ERROR_CFLAGS) + + +noinst_LTLIBRARIES = libcipher.la + +GCRYPT_MODULES = @GCRYPT_CIPHERS@ @GCRYPT_PUBKEY_CIPHERS@ @GCRYPT_DIGESTS@ + +libcipher_la_DEPENDENCIES = $(GCRYPT_MODULES) +libcipher_la_LIBADD = $(GCRYPT_MODULES) + +libcipher_la_SOURCES = \ +cipher.c pubkey.c ac.c md.c kdf.c \ +hmac-tests.c \ +bithelp.h \ +primegen.c \ +hash-common.c hash-common.h \ +rmd.h + +EXTRA_libcipher_la_SOURCES = \ +arcfour.c \ +blowfish.c \ +cast5.c \ +crc.c \ +des.c \ +dsa.c \ +elgamal.c \ +ecc.c \ +idea.c \ +md4.c \ +md5.c \ +rijndael.c rijndael-tables.h \ +rmd160.c \ +rsa.c \ +seed.c \ +serpent.c \ +sha1.c \ +sha256.c \ +sha512.c \ +tiger.c \ +whirlpool.c \ +twofish.c \ +rfc2268.c \ +camellia.c camellia.h camellia-glue.c + +if ENABLE_O_FLAG_MUNGING +o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g' +else +o_flag_munging = cat +endif + + +# We need to lower the optimization for this module. +tiger.o: $(srcdir)/tiger.c + `echo $(COMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) ` + +tiger.lo: $(srcdir)/tiger.c + `echo $(LTCOMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) ` diff --git a/grub-core/lib/libgcrypt/cipher/Manifest b/grub-core/lib/libgcrypt/cipher/Manifest new file mode 100644 index 000000000..0cd64f71f --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/Manifest @@ -0,0 +1,73 @@ +# Manifest - checksums of the cipher directory +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +# Checksums for all source files in this directory. Format is +# filename, blanks, base-64 part of an OpenPGP detached signature +# without the header lines. Blank lines and lines beginning with a +# hash mark are ignored. A tool to process this file is available by +# cvs -d :pserver:anoncvs@cvs.gnupg.org:/cvs/wk co misc-scripts/manifest-tool +# +# The special entry "$names$" holds a signature over all sorted +# filenames excluding itself. + + +# Algorithm API +cipher.c iQCVAwUAQDzrVjEAnp832S/7AQIPDgP+OVJ/YNWY5m7c09EBbPAzL/WsGoj6wrBNMmkRlMOqTHeh+OOtjuFHt1f9uhfM2Nzl7sJ5+h4ryZKLEZmQPRMTZTnAqkvGdsrJWJnigUA9QwYdV0ONqC9C63gpuG465gO9TZVOqlQu/FTxSRuTQYUulkaBNG71n8nZEOusBVwV2YA==58xH +pubkey.c iQCVAwUAP9XQ3jEAnp832S/7AQJ5UgQAyHfEBvPVJ8wTRg8c7ixS2GiVmIgwIo5tvQaiQJTPWASevvYrB+2Z2qa9cATyu50ACjLzbaquGBgPzjJV3dU/qttT1gCqRuN/LCNvXFe5qnIZezejc3RAadFNTw/pOTHq0wxD1Keg66ruei9R36Nba59pEQIWIBXTfubRft2hMYk==E09t +ac.c iQCVAwUAQDzsOzEAnp832S/7AQJCBQP/WI6EV/dsR4rmha6RVhvkjZo17kQ8z6pIl5J3cXOvqEkIFeD2HYu3HHrWST5l7yXlffhpDkVHkfMih4ruK76q6Fm0dxZ98pO4C/dVtgimlvvcy/wOQjpzsE0fYAe1BYdg81LJ09X33vW5x6C29lunfKROO2tPlV5i8ffeoFvmMF8==j26g +md.c iQCVAwUAP+NFGjEAnp832S/7AQJs8wP/Qdk0EAKsyr3O1/pmOSN8AG4rPKbd6KDTzvoBPAN4upFwKYY4hWwvy12Q3YU9DmECrzZkRCXHR7mljVQKs6B7CRZJKjFKmOELpcJDtKvu40vTs1bOH4k9iJYZpGgRA83nkQ+ELAcphAbCA+KIpVr2K4mCJAB0FhpC2uOQ50JHAko==BeF6 +primegen.c iQCVAwUAQDzsoDEAnp832S/7AQKYRwP/TqAQBm1rHTnF0HYE05PqXfWlOqa6EosqVpaOcs/OIW6PaqX0xH1UlrukK7jNOjK3xC4o1qNQ1UKzz2dvQaq1bMvNNizeavxAh10SJZc0hIc/ofc83IbjLh8SZVWQ67JxjsUd3DOXmSmhPZ+Pqd7cUIiw8fDoF+I9EZqy3COu1wY==1ebT + +# Algorithm implementations +arcfour.c iQCVAwUAP9XR/TEAnp832S/7AQJcRwP6AlvYEx++fpT4mIYo0xRDqKEQeqMQvbaRhIg2eV74JxItpHa3q5YsYIl+n1yUz5g35JRWWXSWmAZBwO5wLKsHii4kRUhgrKWnSoQZoPpl49L5+N3R58ON3S0ru5lsBiEJEze3xplf2vqwrH9v1QHVD+gU7UTlfNqrIJoOUXN+1O4==Tq+x +blowfish.c iQCVAwUAP9XTETEAnp832S/7AQJaEgQAgiqqfuO+zQtscgTB0rvOzVymIKjRKjYhFuLjVuc79G4z1RCAffvIn/YM2d7kt+Z/QF7zjcTAOgETCQL1XokpX2zz9HPAMi2tlDY5zsDufTNqj0n4WBL9nM7w6XAvsiwP1B3bqCTv9SjJV4KbxJ58vw1yQE+sqW74R/QIHFvC7mU==wZnX +cast5.c iQCVAwUAP9XT6DEAnp832S/7AQJ3xgP/ehLjEN3GELGudbqeo91Xd+PqitHrkuBbtRIYX7Udd/fyXLN+h8rMJVyIQX2m+mpxbBxudVU3x8/DNT8B0ZHAwK6qqJmEBLLhEYPgIuF76i9LMrP1KqUPhAwRZ2OppjIIugBQ+rP74aD4eLyd/aKQHNuXML8QGWR6KwQShohXM5I==/BRh +crc.c iQCVAwUAP7ouejEAnp832S/7AQIgwQQApg5Nm63tH5DQkbN+zPzMO9Ygoj3ukxfFTyTBPYSXYKMiTjEbESegaU40uN8jnz2vprcIQWcgZfzO4+opEJMcI35aPwzEk0vKOp0S/PrBLUY2rJfnDVkX5XgJFZa2Q7LLe826UEBzTVYW924utiCCe8oOaOEWVNpg1mqdknu3M9o==kz5D +des.c iQCVAwUAQCN2oDEAnp832S/7AQL/jwP6Auoq6nZCDBjpgc9tDzuIRwa9DqyuM3gX94uvgEpUwdHszb2bG43dz03kVmcYxtj1MzXbyCeCZOwox0b2SKmLgxIbrNP6yGbzVdTj6592gDYuf/ZXmc1ZNJ1DDldcPQ0n9fXUipUPwyPaNWo3mSZaNcMKSWWzdK0J6ciG6nk7SWI==9k/t +dsa.c iQCVAwUAP9XZHDEAnp832S/7AQLBRgP/XrBzTEYx5ccMj1MMb6sg37liEHdIyyy49zjvt6jUqxj4RuwVEN8S6v3u4q/QyJkHAi1E0EkREgENlyHW6PKWhYbcrd0vPIAN15yjnl2yqtrCrJImexUCoqJJewK0E4JOicGbabTil8MZjk+mbhEPnjJBqOkyP1w0i31pEDgE/8M==pC8s +elgamal.c iQCVAwUAP9XbYzEAnp832S/7AQLXagQA3HrvspZfbTGgmUH0IqLQTJ0exUPxJv5DET2TvoIy62trDmMN6lTAj5P+a7jQ8udcu0w+mR2vXUHcxUpNA2PxLaMwGzNSY4zRDNe9r3SFTDrFm6m4y9Ko2e8XtEA+WF6P/XLpck4Jn7vMEDmVGPwkNd22kXFFE8dBGwG6i5Hk1Mk==oBUs +md4.c iQCVAwUAP9h50DEAnp832S/7AQJhHgQAzNA/B6MWFDlCtPkIVaW8RpP1Eg0ZNMsy0s7SJkopOCBlu6CwXUOKe+8ppcSxhjYKh4i4uQr/QtfipYlBjzKJGnrafoF/NugXNCOHSTGT11TvK7mCiBuUMVgvZGAlOJImk6eTTfUjRrMfaXM/SWl8bdJ4ZpzdjEyVh89r7I5JrGk==x2UD +md5.c iQCVAwUAP9h7LzEAnp832S/7AQJUGQP/c0cbf6WZXCzmjufHxiE9FAQBzTsA0WtaNqdFcHl7fhmikGtknlaED8n5a7eYd/C481UQW6Wgq/oZdsvgoPWPhG3fOCy2CFP9cZVXITuMSf0ucyZTFUJNO15fnZ+nDfsUv+JPdv1aSeRinAUtfAcSKfkSyR9BCPZvkx+tgU6cphU==Zv+h +rijndael.c iQCVAwUAP9h9cTEAnp832S/7AQKF1AP+P2L/tPqDJRDg+/fwbOk8Ts0MNxnvvYEm3gE73TKuLt1S+B2+jkrZcKNvM5VGPnVMJbnS0lmIK04nmedHCOftGTOwhGulZAHHIaKGystT3Jql4iPws/JMgAjE7Fyxh5WZMtB9yEljKBpJ5XNqhrMvvxcHpnyP3+YzIXNwzk34V+c==dJ5k +rmd160.c iQCVAwUAP9h+bTEAnp832S/7AQK1OgP+PNKF6Nzi6X93easVlksdLqKEsArCAw2QjGWDGyxTnbiJM55qAl9JxR1mn3V+oOL7izLLwTt6EYK9evhzfcxY5N5Mni85RAcsLPsuAfQDEzjI6GUWHtQUKPbM+BaorzfhQjYFSZyvum/dZYJ/WfiwwwhqqIKyVU2ZFSqA38YGC/c==9jdA +rsa.c iQCVAwUAP9iHIzEAnp832S/7AQKAYwQAuWtnMte54QHN+Hij9t4sGuypXogajOb1vQQwGgS0fKsaBZsuSP2amze4o5diIvsQTsFQ4CzjvqoCVuBDoHM3xkSD8wGDizgvtCamAxkdbF7wmzldKFn8SpJqlVwWQMP6kk1IjXHEuYb4IDWGTbVMhfEu+eOlU8+PSK4IhZqNvt4==/3hp +serpent.c iQCVAwUAP9h/VzEAnp832S/7AQLyCwP/d1zbmb7l/PriZNa9/Z7mo01XFe5MnAqCfIwhl9GjeaMszcoS37jECNq5nLvrTTFIIJpm3rvBePwiCG4Wwx1I18HCxaP198pcSaR+BLOJ3Aj52EZPrxtqlDKuFr38ZOP5giyUqUYVYGVdrz4kRMNWAZQK53GeJnGhXCnhxojLEgA==ck46 +sha1.c iQCVAwUAP9iATTEAnp832S/7AQKcSwQAwAs/HnNqho3lU1ZUgCPNt5P2/Brm6W21+wWWGKJkSrra/c4NYVKJGDDwlsFE0b9ln1uZt7bHReFkKXK3JnrKTmNVcx/Cy64iCMRNMhaM72Mqy7wWx5yHBAmMBxzFGnNQKbmeY52zeGih5HsNLSibc2pPuOViWo2JPJ5Ci/wIwl8==/wtO +sha256.c iQCVAwUAP9iAtzEAnp832S/7AQJD2QP/UqvL0hhjG1wEFbGrdkV9tba1sMDXdnnK6X7HdLuRpVAgNiQiFf8JDmntd/dZ2Q71p4Uae2ctqve4WoEijPUZPjACnpuZfx0SEQL0lQBkwxzJp7lz9ujVtwQ2cM/aYexJkXcWgGcloJNLM3JbWPGIJnuYbr/IwJ6RQF9vgj0357o==UWO1 +sha512.c iQCVAwUAP9iBTDEAnp832S/7AQIPBAQA28CJSUQLiW0s2x9u8/OH2eKnxPjA4sZmb50WP7920Lem66P31C3BrOqwfBot4RLhjL+zh/+Uc4s3HPwApZuj9E4BxNMlqLv+Tqk++DAbdaOeYT4jeUt+mlhQQ6mH/RDsy32rZsNsGQ2bUGxazZmfG++PL3JyhawqCy00SUDr/o0==H+0X +tiger.c iQCVAwUAP9iCfjEAnp832S/7AQKufwP/fryv3MqSOYY+90325DH7X3/CtekxeooN0scGsHX0fxBakWSMecTNrj33KPddLS46gU/S89zIc2N/Bw/7EVIAXVFA3/3Ip+OrFOuIMO4Py1sCdB8o2Y+5ygv8iXLcsXIq1O0av79i9g774V3uaXa2qN9ZnXe0AEhcy8FHJ2i/wro==5XVB +twofish.c iQCVAwUAP9iD6TEAnp832S/7AQKUnQP/Rq8FaYeHTG7HbZuqAs9pbPitzjDbkdZddmInWR7NmevBkKvhsJALjVooc0KGQfo2lAAmy3Xi/4QQN8VPn51DVjDIgf7x+DQh/9TFJHMccxI9asUgi4+TNnmMqLU1k3N8S2PjyZ1sjeC8B79fKPpwCzj72WkqPkzZw3l2jArr+dU==NdJT +rfc2268.c iQCVAwUAQCN+3jEAnp832S/7AQLv1gQA1hJh29hAjKi4uLSGxXvJ6cyYmPdmevdKrbLnuHZWtHe4xvCgy/nTdEojEpxgLp/hL/ogasuWRC1W16Wiz9ryxf7YR0uhZWayO/bQNagpfU5MIkJTLuKqqgpwYumCSQfOugXVAqcgEzj+13eeyJaFVrzwrNa67sh84nmbjOjNjvE==0zBq + +# Random number related +random.c iQCVAwUAP7nsITEAnp832S/7AQK4SAQAtvfUgrtGOQ2PlxGMla0qJLPHjJacMwgq0ecusiI79elPdDsFfCCk6dK1Ug2kFbNm22nCGHNcUquqbX7noi7ZVQnmPBQXzyLNZd7GmrawRZfdlRerTUDBpSnR8V8ui/5+YYp627E7kKGC0hPSgqXFql6oBMIfno0LZwFJTjIevRY==L419 +random.h iQCVAwUAP7ovKDEAnp832S/7AQJ3bQQAjnPebnyTC7sphAv2I7uIz+yPgw1ZfbVhLv+OiWDlO9ish+fRyyMpy+HELBOgZjJdgRegqhlZC6qyns5arM/VglYi+PzvdLO3hIqHE/YFfpIFPz8wBrcmlqrYyd3CsGqcYsfjocXNttCBLeSWmoJ09ltKQH8yzJf3oAgN6X1yuc4==eNoU +rand-internal.h iQCVAwUAP7ouvDEAnp832S/7AQLYnAQAhdI7ERoJVCkV8GiV7MjaUxv1WIL7iZ+jIOvVhv4fNyhCGCGoEtTjkyput/lj7Nsh3FXEqRhypGGrCLf47x/gua5n+BwffogxVyUDqiOyyGhNTPpe3fQcNBvbPCtco8yMK4GJO5G3BqzlPyN+BMeogLymyV6Sm1mvh5LZDyAFbfQ==tZSE +rndlinux.c iQCVAwUAP9iPYTEAnp832S/7AQL6/AP/ZDrbOkVuB9qJ7sKeX1MImZEsz3mi0xPovJzaBtBU7a0idcUKrWYOvQFWRlLUeq0iCT6+h2l5bniP7q7hepzlKa+VPY9VWaQthqeJm2l5LN6QQ5PyMfBq04QuBncw9BJnCGmEyTLt3RxIXBAPdxmiVxtcRIFUqCBtQvoUXGLvemw==t37k +rndegd.c iQCVAwUAP9iPRDEAnp832S/7AQImBQP/WHKg+hKXcm1pQvilzML0jZpwK5PAMM4uBnnPJNIXWOYBO6I/Xg9d/tPLg8NlmmtyQCo2Eu0ybDSt+8mu+dWveAys+0LTi0MIqeP9BMzCKz8dnWH6+S8huLXwTF3m0IrqM0JLb6b71GK9SOq6sWQ22yW5vf61hXP8kH9dhIaoMZs==FaHV +rndunix.c iQCVAwUAP9iQlzEAnp832S/7AQL/KgQA29GnvcD4Xb5qjDMBgW9THEE4+4lfex/6k+Fh0IT61OLJsWVLJ7bJpRntburw4uQm4Tf7CO8vaiDFDYhKKrzXeOF1fmdpcL8hA+fNp9I/MUOc4e9kN9+YJ9wikVa0SZj1OBfhzgcFLd1xOtulkr3ii52HLF9vhrxzkgVwvD10Bi8==2cML +rndw32.c iQCVAwUAP9iRKDEAnp832S/7AQIuaAQA3AJr3WqnxNDsWCIdvehf8Suotthj+laX8nJsvDfFhXPKcXDpsg0wTTXSnnKgyED53+uYiMDnVRsxeWAyhKwvx1MjjlaSMMjzbH6isWTH8FaWpLgrxEkXoPeNqYf5FXpdUkcUxGX2RkQeuX/cIfiHLNE9CV0usaF2jysjBX2iERY==EEnO + +# Helper +bithelp.h iQCVAwUAP7ouPTEAnp832S/7AQKXggQAqjcgvihIF3WclOgw1JV2rbARw4ISIDRMFqdaNCqBRx6BwEz3UGsEIlz6+iR1sS/reqN61WvtjLb+D0+tujAkGrgQJhFLG85WtG2tB5UVoI3am1fpkwiRm+bR4rv0rGk0BYk81bC7+l4KrK9o5lVp4lCsrorlUKsd48lNmBHyAXM==mDDN +rmd.h iQCVAwUAP7oumjEAnp832S/7AQJiJQP/V4bJwjZaYndJzV+KRnIDbl1koHuw+ZK5heMYVu8Qk4ylqv//BGyeRa3jZCcfPHI35q6HilCs2VBm8hiBMjHSqY/VPn2ZQ0yg/lt6qEvl7YjsLmyMICvjG+ncszHoq9pRvnF3vTnM18sPIioXLk8fskuM0XOCNBs0ARBAQjY9UGI==olUN + +# Configuration +Makefile.am iQCVAwUAQCN33TEAnp832S/7AQKFJAQAz7BDkC814q+QiuE/jnutJHR5qlgbrm3ikGbQwdRzYUscst4bCCWy3uKL/sIPGLg+JQXtF5FnsQy3s4D9BOYhp72cA9ktYK65hhi4pNm/JQ0lXkZMNfk8Go5lNzKezlWwHvkMwRXR0Fep0wPdyeaKW5BfaW2ABvgep6Bp+hHEbyg==zSyi +$names$ iQCVAwUAQCN3EDEAnp832S/7AQJXLAP8DvHTpm5DkTF35EmzeKpi9ie59AZcZanD19ir/e/7+PaQxr2riuLHDGwFKTju+dcvvBsqrygXOC378GXVWzIF2OZwS4EdDcJ+pgojo9UpsqpKsJHouY4Ugx5cQialxba462kUn8hcihSBnMyc4LzbJ5WQ4puQuqy544d2x94+2ms==G4Ls diff --git a/grub-core/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c index ee9498b23..f5e946a2d 100644 --- a/grub-core/lib/libgcrypt/cipher/ac.c +++ b/grub-core/lib/libgcrypt/cipher/ac.c @@ -1,19 +1,19 @@ /* ac.c - Alternative interface for asymmetric cryptography. Copyright (C) 2003, 2004, 2005, 2006 2007, 2008 Free Software Foundation, Inc. - + This file is part of Libgcrypt. - + Libgcrypt is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser general Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + Libgcrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, see . */ @@ -115,7 +115,7 @@ struct gcry_ac_key_pair -/* +/* * Functions for working with data sets. */ @@ -151,7 +151,7 @@ static void ac_data_values_destroy (gcry_ac_data_t data) { unsigned int i; - + for (i = 0; i < data->data_n; i++) if (data->data[i].flags & GCRY_AC_FLAG_DEALLOC) { @@ -256,7 +256,7 @@ _gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data) err = ac_data_mpi_copy (data->data, data->data_n, &data_mpis); if (err) goto out; - + data_new->data_n = data->data_n; data_new->data = data_mpis; *data_cp = data_new; @@ -524,13 +524,13 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, i++; } identifiers_n = i; - + if (! identifiers_n) /* If there are NO identifiers, we still add surrounding braces so that we have a list of named MPI value lists. Otherwise it wouldn't be too much fun to process these lists. */ sexp_buffer_n += 2; - + data_n = _gcry_ac_data_length (data); for (i = 0; i < data_n; i++) { @@ -666,7 +666,7 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, /* Identifier matches. Now we have to distinguish two cases: - + (i) we are at the last identifier: leave loop @@ -725,7 +725,7 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, skip_name = 0; /* Create data set from S-expression data. */ - + err = gcry_ac_data_new (&data_set_new); if (err) goto out; @@ -793,7 +793,7 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, gcry_sexp_release (sexp_tmp); gcry_mpi_release (mpi); gcry_free (string); - + if (err) gcry_ac_data_destroy (data_set_new); @@ -1005,7 +1005,7 @@ _gcry_ac_io_read (gcry_ac_io_t *ac_io, unsigned int nread, unsigned char *buffer, size_t *buffer_n) { gcry_error_t err; - + gcry_assert (ac_io->mode == GCRY_AC_IO_READABLE); err = 0; @@ -1072,7 +1072,7 @@ _gcry_ac_io_read_all (gcry_ac_io_t *ac_io, unsigned char **buffer, size_t *buffe err = gcry_error_from_errno (errno); break; } - + if (buffer_new != p) buffer_new = p; @@ -1132,7 +1132,7 @@ _gcry_ac_io_process (gcry_ac_io_t *ac_io, -/* +/* * Functions for converting data between the native ac and the * S-expression structure used by the pk interface. */ @@ -1403,7 +1403,7 @@ _gcry_ac_open (gcry_ac_handle_t *handle, err = _gcry_pk_module_lookup (algorithm, &module); if (err) goto out; - + /* Allocate. */ handle_new = gcry_malloc (sizeof (*handle_new)); if (! handle_new) @@ -1420,7 +1420,7 @@ _gcry_ac_open (gcry_ac_handle_t *handle, *handle = handle_new; out: - + /* Deallocate resources. */ if (err) _gcry_pk_module_release (module); @@ -1443,7 +1443,7 @@ _gcry_ac_close (gcry_ac_handle_t handle) -/* +/* * Key management. */ @@ -1662,7 +1662,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, out: /* Deallocate resources. */ - + gcry_free (genkey_format); gcry_free (arg_list); gcry_sexp_release (genkey_sexp_request); @@ -1682,7 +1682,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, /* Returns the key of type WHICH out of the key pair KEY_PAIR. */ gcry_ac_key_t -_gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, +_gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, gcry_ac_key_type_t which) { gcry_ac_key_t key; @@ -1851,7 +1851,7 @@ _gcry_ac_key_get_grip (gcry_ac_handle_t handle, -/* +/* * Functions performing cryptographic operations. */ @@ -2176,7 +2176,7 @@ em_randomize_nonzero (unsigned char *buffer, size_t buffer_n, for (i = 0; i < buffer_n; i++) buffer[i] = 0; - + do { /* Count zeros. */ @@ -2384,7 +2384,7 @@ emsa_pkcs_v1_5_encode (unsigned int flags, void *opts, unsigned int i; (void)flags; - + options = opts; buffer = NULL; md = NULL; @@ -2499,7 +2499,7 @@ typedef enum dencode_action dencode_action_t; /* Encode or decode a message according to the the encoding method - METHOD; ACTION specifies wether the message that is contained in + METHOD; ACTION specifies whether the message that is contained in BUFFER_IN and of length BUFFER_IN_N should be encoded or decoded. The resulting message will be stored in a newly allocated buffer in BUFFER_OUT and BUFFER_OUT_N. */ @@ -2656,7 +2656,7 @@ _gcry_ac_mpi_to_os_alloc (gcry_mpi_t mpi, unsigned char **os, size_t *os_n) err = gcry_error_from_errno (errno); goto out; } - + _gcry_ac_mpi_to_os (mpi, buffer, buffer_n); *os = buffer; *os_n = buffer_n; @@ -2676,7 +2676,7 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) gcry_mpi_t xi; gcry_mpi_t x; gcry_mpi_t a; - + if (fips_mode ()) return; @@ -2692,7 +2692,7 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) gcry_mpi_add (x, x, xi); gcry_mpi_mul_ui (a, a, 256); } - + gcry_mpi_release (xi); gcry_mpi_release (a); @@ -2702,7 +2702,7 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) -/* +/* * Implementation of Encryption Schemes (ES) and Signature Schemes * with Appendix (SSA). */ @@ -2824,7 +2824,7 @@ ac_dencode_prepare (gcry_ac_handle_t handle, gcry_ac_key_t key, void *opts, err = gcry_error_from_errno (errno); goto out; } - + err = (*scheme.dencode_prepare) (handle, key, opts, options_em); if (err) goto out; @@ -3065,7 +3065,7 @@ _gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle, goto out; out: - + _gcry_ac_data_destroy (data_encrypted); gcry_mpi_release (mpi_encrypted); gcry_mpi_release (mpi_decrypted); @@ -3270,7 +3270,7 @@ _gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, gcry_mpi_release (mpi_signature); mpi_signature = NULL; - + err = _gcry_ac_data_verify (handle, key, mpi_data, data_signed); out: @@ -3287,7 +3287,7 @@ _gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, } -/* +/* * General functions. */ diff --git a/grub-core/lib/libgcrypt/cipher/arcfour.c b/grub-core/lib/libgcrypt/cipher/arcfour.c index 6bb0555c6..6ef07fb20 100644 --- a/grub-core/lib/libgcrypt/cipher/arcfour.c +++ b/grub-core/lib/libgcrypt/cipher/arcfour.c @@ -45,7 +45,7 @@ do_encrypt_stream( ARCFOUR_context *ctx, register int i = ctx->idx_i; register int j = ctx->idx_j; register byte *sbox = ctx->sbox; - register int t; + register int t; while ( length-- ) { @@ -56,7 +56,7 @@ do_encrypt_stream( ARCFOUR_context *ctx, t = sbox[i]; sbox[i] = sbox[j]; sbox[j] = t; *outbuf++ = *inbuf++ ^ sbox[(sbox[i] + sbox[j]) & 255]; } - + ctx->idx_i = i; ctx->idx_j = j; } @@ -80,7 +80,7 @@ do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) byte karr[256]; ARCFOUR_context *ctx = (ARCFOUR_context *) context; - if (!initialized ) + if (!initialized ) { initialized = 1; selftest_failed = selftest(); @@ -98,14 +98,14 @@ do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) ctx->sbox[i] = i; for (i=0; i < 256; i++ ) karr[i] = key[i%keylen]; - for (i=j=0; i < 256; i++ ) + for (i=j=0; i < 256; i++ ) { int t; j = (j + ctx->sbox[i] + karr[i]) % 256; t = ctx->sbox[i]; ctx->sbox[i] = ctx->sbox[j]; ctx->sbox[j] = t; - } + } memset( karr, 0, 256 ); return GPG_ERR_NO_ERROR; @@ -125,8 +125,8 @@ static const char* selftest(void) { ARCFOUR_context ctx; - byte scratch[16]; - + byte scratch[16]; + /* Test vector from Cryptlib labeled there: "from the State/Commerce Department". */ static byte key_1[] = @@ -153,4 +153,3 @@ gcry_cipher_spec_t _gcry_cipher_spec_arcfour = "ARCFOUR", NULL, NULL, 1, 128, sizeof (ARCFOUR_context), arcfour_setkey, NULL, NULL, encrypt_stream, encrypt_stream, }; - diff --git a/grub-core/lib/libgcrypt/cipher/blowfish.c b/grub-core/lib/libgcrypt/cipher/blowfish.c index 6ef68e371..b4d2b9c9a 100644 --- a/grub-core/lib/libgcrypt/cipher/blowfish.c +++ b/grub-core/lib/libgcrypt/cipher/blowfish.c @@ -501,7 +501,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) static int initialized; static const char *selftest_failed; - if( !initialized ) + if( !initialized ) { initialized = 1; selftest_failed = selftest(); @@ -513,7 +513,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) c->p[i] = ps[i]; - for(i=0; i < 256; i++ ) + for(i=0; i < 256; i++ ) { c->s0[i] = ks0[i]; c->s1[i] = ks1[i]; @@ -521,7 +521,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) c->s3[i] = ks3[i]; } - for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) + for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) { #ifdef WORDS_BIGENDIAN ((byte*)&data)[0] = key[j]; @@ -545,7 +545,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) c->p[i] = datal; c->p[i+1] = datar; } - for(i=0; i < 256; i += 2 ) + for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s0[i] = datal; diff --git a/grub-core/lib/libgcrypt/cipher/camellia-glue.c b/grub-core/lib/libgcrypt/cipher/camellia-glue.c index 067af85bc..a26362177 100644 --- a/grub-core/lib/libgcrypt/cipher/camellia-glue.c +++ b/grub-core/lib/libgcrypt/cipher/camellia-glue.c @@ -32,7 +32,7 @@ * space of the library clean. The following macro is thus useful: * * #define CAMELLIA_EXT_SYM_PREFIX foo_ - * + * * This prefixes all external symbols with "foo_". */ #ifdef HAVE_CONFIG_H @@ -50,7 +50,7 @@ #define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) #define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) #define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) -#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) #define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) #endif /*CAMELLIA_EXT_SYM_PREFIX*/ @@ -99,7 +99,7 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ +3*2*sizeof(void*) /* Function calls. */ - ); + ); return 0; } @@ -137,7 +137,7 @@ selftest(void) { CAMELLIA_context ctx; byte scratch[16]; - + /* These test vectors are from RFC-3713 */ const byte plaintext[]= { diff --git a/grub-core/lib/libgcrypt/cipher/camellia.c b/grub-core/lib/libgcrypt/cipher/camellia.c index 79cd49b7c..2e28bce2a 100644 --- a/grub-core/lib/libgcrypt/cipher/camellia.c +++ b/grub-core/lib/libgcrypt/cipher/camellia.c @@ -19,7 +19,7 @@ */ /* - * Algorithm Specification + * Algorithm Specification * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ @@ -937,7 +937,7 @@ void camellia_setup256(const unsigned char *key, u32 *subkey) CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; - + return; } @@ -1049,14 +1049,14 @@ void camellia_encrypt128(const u32 *subkey, u32 *io) io[1] = io[3]; io[2] = t0; io[3] = t1; - + return; } void camellia_decrypt128(const u32 *subkey, u32 *io) { u32 il,ir,t0,t1; /* temporary valiables */ - + /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(24); io[1] ^= CamelliaSubkeyR(24); @@ -1267,7 +1267,7 @@ void camellia_decrypt256(const u32 *subkey, u32 *io) /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(32); io[1] ^= CamelliaSubkeyR(32); - + /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(31),CamelliaSubkeyR(31), @@ -1379,8 +1379,8 @@ void camellia_decrypt256(const u32 *subkey, u32 *io) * API for compatibility */ -void Camellia_Ekeygen(const int keyBitLength, - const unsigned char *rawKey, +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, KEY_TABLE_TYPE keyTable) { switch(keyBitLength) { @@ -1399,9 +1399,9 @@ void Camellia_Ekeygen(const int keyBitLength, } -void Camellia_EncryptBlock(const int keyBitLength, - const unsigned char *plaintext, - const KEY_TABLE_TYPE keyTable, +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, unsigned char *ciphertext) { u32 tmp[4]; @@ -1430,9 +1430,9 @@ void Camellia_EncryptBlock(const int keyBitLength, PUTU32(ciphertext + 12, tmp[3]); } -void Camellia_DecryptBlock(const int keyBitLength, - const unsigned char *ciphertext, - const KEY_TABLE_TYPE keyTable, +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, unsigned char *plaintext) { u32 tmp[4]; diff --git a/grub-core/lib/libgcrypt/cipher/camellia.h b/grub-core/lib/libgcrypt/cipher/camellia.h index 4425a3a2b..cccf786ca 100644 --- a/grub-core/lib/libgcrypt/cipher/camellia.h +++ b/grub-core/lib/libgcrypt/cipher/camellia.h @@ -25,7 +25,7 @@ * space of the library clean. The following macro is thus useful: * * #define CAMELLIA_EXT_SYM_PREFIX foo_ - * + * * This prefixes all external symbols with "foo_". */ #ifdef HAVE_CONFIG_H @@ -43,7 +43,7 @@ #define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) #define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) #define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) -#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) #define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) #endif /*CAMELLIA_EXT_SYM_PREFIX*/ @@ -60,17 +60,17 @@ typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; void Camellia_Ekeygen(const int keyBitLength, - const unsigned char *rawKey, + const unsigned char *rawKey, KEY_TABLE_TYPE keyTable); void Camellia_EncryptBlock(const int keyBitLength, - const unsigned char *plaintext, - const KEY_TABLE_TYPE keyTable, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, unsigned char *cipherText); -void Camellia_DecryptBlock(const int keyBitLength, - const unsigned char *cipherText, - const KEY_TABLE_TYPE keyTable, +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, unsigned char *plaintext); diff --git a/grub-core/lib/libgcrypt/cipher/cast5.c b/grub-core/lib/libgcrypt/cipher/cast5.c index 333d55e91..9905f5cb9 100644 --- a/grub-core/lib/libgcrypt/cipher/cast5.c +++ b/grub-core/lib/libgcrypt/cipher/cast5.c @@ -569,7 +569,7 @@ do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) u32 z[4]; u32 k[16]; - if( !initialized ) + if( !initialized ) { initialized = 1; selftest_failed = selftest(); diff --git a/grub-core/lib/libgcrypt/cipher/cipher.c b/grub-core/lib/libgcrypt/cipher/cipher.c index 2c33ee94f..9852d6a5a 100644 --- a/grub-core/lib/libgcrypt/cipher/cipher.c +++ b/grub-core/lib/libgcrypt/cipher/cipher.c @@ -1,6 +1,6 @@ /* cipher.c - cipher dispatcher * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * 2005, 2007, 2008 Free Software Foundation, Inc. + * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -33,9 +33,12 @@ #define CTX_MAGIC_NORMAL 0x24091964 #define CTX_MAGIC_SECURE 0x46919042 +/* Try to use 16 byte aligned cipher context for better performance. + We use the aligned attribute, thus it is only possible to implement + this with gcc. */ #undef NEED_16BYTE_ALIGNED_CONTEXT -#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) -#define NEED_16BYTE_ALIGNED_CONTEXT 1 +#if defined (__GNUC__) +# define NEED_16BYTE_ALIGNED_CONTEXT 1 #endif /* A dummy extraspec so that we do not need to tests the extraspec @@ -58,39 +61,39 @@ static struct cipher_table_entry &dummy_extra_spec, GCRY_CIPHER_BLOWFISH }, #endif #if USE_DES - { &_gcry_cipher_spec_des, + { &_gcry_cipher_spec_des, &dummy_extra_spec, GCRY_CIPHER_DES }, { &_gcry_cipher_spec_tripledes, &_gcry_cipher_extraspec_tripledes, GCRY_CIPHER_3DES, 1 }, #endif #if USE_ARCFOUR - { &_gcry_cipher_spec_arcfour, + { &_gcry_cipher_spec_arcfour, &dummy_extra_spec, GCRY_CIPHER_ARCFOUR }, #endif #if USE_CAST5 - { &_gcry_cipher_spec_cast5, + { &_gcry_cipher_spec_cast5, &dummy_extra_spec, GCRY_CIPHER_CAST5 }, #endif #if USE_AES - { &_gcry_cipher_spec_aes, + { &_gcry_cipher_spec_aes, &_gcry_cipher_extraspec_aes, GCRY_CIPHER_AES, 1 }, - { &_gcry_cipher_spec_aes192, + { &_gcry_cipher_spec_aes192, &_gcry_cipher_extraspec_aes192, GCRY_CIPHER_AES192, 1 }, - { &_gcry_cipher_spec_aes256, + { &_gcry_cipher_spec_aes256, &_gcry_cipher_extraspec_aes256, GCRY_CIPHER_AES256, 1 }, #endif #if USE_TWOFISH { &_gcry_cipher_spec_twofish, &dummy_extra_spec, GCRY_CIPHER_TWOFISH }, - { &_gcry_cipher_spec_twofish128, + { &_gcry_cipher_spec_twofish128, &dummy_extra_spec, GCRY_CIPHER_TWOFISH128 }, #endif #if USE_SERPENT - { &_gcry_cipher_spec_serpent128, + { &_gcry_cipher_spec_serpent128, &dummy_extra_spec, GCRY_CIPHER_SERPENT128 }, { &_gcry_cipher_spec_serpent192, &dummy_extra_spec, GCRY_CIPHER_SERPENT192 }, - { &_gcry_cipher_spec_serpent256, + { &_gcry_cipher_spec_serpent256, &dummy_extra_spec, GCRY_CIPHER_SERPENT256 }, #endif #if USE_RFC2268 @@ -98,16 +101,20 @@ static struct cipher_table_entry &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 }, #endif #if USE_SEED - { &_gcry_cipher_spec_seed, + { &_gcry_cipher_spec_seed, &dummy_extra_spec, GCRY_CIPHER_SEED }, #endif #if USE_CAMELLIA { &_gcry_cipher_spec_camellia128, &dummy_extra_spec, GCRY_CIPHER_CAMELLIA128 }, - { &_gcry_cipher_spec_camellia192, + { &_gcry_cipher_spec_camellia192, &dummy_extra_spec, GCRY_CIPHER_CAMELLIA192 }, { &_gcry_cipher_spec_camellia256, &dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 }, +#endif +#ifdef USE_IDEA + { &_gcry_cipher_spec_idea, + &dummy_extra_spec, GCRY_CIPHER_IDEA }, #endif { NULL } }; @@ -118,7 +125,7 @@ static gcry_module_t ciphers_registered; /* This is the lock protecting CIPHERS_REGISTERED. */ static ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER; -/* Flag to check wether the default ciphers have already been +/* Flag to check whether the default ciphers have already been registered. */ static int default_ciphers_registered; @@ -137,19 +144,20 @@ static int default_ciphers_registered; while (0) -/* A VIA processor with the Padlock engine requires an alignment of - most data on a 16 byte boundary. Because we trick out the compiler - while allocating the context, the align attribute as used in - rijndael.c does not work on its own. Thus we need to make sure - that the entire context structure is a aligned on that boundary. - We achieve this by defining a new type and use that instead of our - usual alignment type. */ -typedef union +/* A VIA processor with the Padlock engine as well as the Intel AES_NI + instructions require an alignment of most data on a 16 byte + boundary. Because we trick out the compiler while allocating the + context, the align attribute as used in rijndael.c does not work on + its own. Thus we need to make sure that the entire context + structure is a aligned on that boundary. We achieve this by + defining a new type and use that instead of our usual alignment + type. */ +typedef union { PROPERLY_ALIGNED_TYPE foo; #ifdef NEED_16BYTE_ALIGNED_CONTEXT char bar[16] __attribute__ ((aligned (16))); -#endif +#endif char c[1]; } cipher_context_alignment_t; @@ -166,7 +174,7 @@ struct gcry_cipher_handle /* The algorithm id. This is a hack required because the module interface does not easily allow to retrieve this value. */ - int algo; + int algo; /* A structure with function pointers for bulk operations. Due to limitations of the module system (we don't want to change the @@ -174,16 +182,19 @@ struct gcry_cipher_handle open function intializes them and the actual encryption routines use them if they are not NULL. */ struct { - void (*cfb_enc)(void *context, unsigned char *iv, + void (*cfb_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); - void (*cfb_dec)(void *context, unsigned char *iv, + void (*cfb_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); - void (*cbc_enc)(void *context, unsigned char *iv, + void (*cbc_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks, int cbc_mac); - void (*cbc_dec)(void *context, unsigned char *iv, + void (*cbc_dec)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + void (*ctr_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); } bulk; @@ -192,19 +203,29 @@ struct gcry_cipher_handle int mode; unsigned int flags; - /* The initialization vector. To help code optimization we make - sure that it is aligned on an unsigned long and u32 boundary. */ + struct { + unsigned int key:1; /* Set to 1 if a key has been set. */ + unsigned int iv:1; /* Set to 1 if a IV has been set. */ + } marks; + + /* The initialization vector. For best performance we make sure + that it is properly aligned. In particular some implementations + of bulk operations expect an 16 byte aligned IV. */ union { - unsigned long dummy_iv; - u32 dummy_u32_iv; - unsigned char iv[MAX_BLOCKSIZE]; + cipher_context_alignment_t iv_align; + unsigned char iv[MAX_BLOCKSIZE]; } u_iv; + /* The counter for CTR mode. This field is also used by AESWRAP and + thus we can't use the U_IV union. */ + union { + cipher_context_alignment_t iv_align; + unsigned char ctr[MAX_BLOCKSIZE]; + } u_ctr; + + /* Space to save an IV or CTR for chaining operations. */ unsigned char lastiv[MAX_BLOCKSIZE]; - int unused; /* Number of unused bytes in the IV. */ - - unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */ - + int unused; /* Number of unused bytes in LASTIV. */ /* What follows are two contexts of the cipher in use. The first one needs to be aligned well enough for the cipher operation @@ -222,7 +243,7 @@ struct gcry_cipher_handle static gcry_err_code_t dummy_setkey (void *c, const unsigned char *key, unsigned int keylen) { - (void)c; + (void)c; (void)key; (void)keylen; return GPG_ERR_NO_ERROR; @@ -281,7 +302,7 @@ cipher_register_default (void) { gcry_err_code_t err = GPG_ERR_NO_ERROR; int i; - + for (i = 0; !err && cipher_table[i].cipher; i++) { if (! cipher_table[i].cipher->setkey) @@ -384,8 +405,8 @@ _gcry_cipher_register (gcry_cipher_spec_t *cipher, ath_mutex_lock (&ciphers_registered_lock); err = _gcry_module_add (&ciphers_registered, 0, - (void *)cipher, - (void *)(extraspec? extraspec : &dummy_extra_spec), + (void *)cipher, + (void *)(extraspec? extraspec : &dummy_extra_spec), &mod); ath_mutex_unlock (&ciphers_registered_lock); @@ -415,7 +436,7 @@ gcry_cipher_unregister (gcry_module_t module) ispassed as NULL. A pointer to the specification of the module implementing this algorithm is return in OID_SPEC unless passed as NULL.*/ -static int +static int search_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec) { gcry_module_t module; @@ -479,7 +500,7 @@ gcry_cipher_map_name (const char *string) } ath_mutex_unlock (&ciphers_registered_lock); - + return algorithm; } @@ -588,15 +609,13 @@ check_cipher_algo (int algorithm) else err = GPG_ERR_CIPHER_ALGO; ath_mutex_unlock (&ciphers_registered_lock); - + return err; } -/* Return the standard length of the key for the cipher algorithm with - the identifier ALGORITHM. This function expects a valid algorithm - and will abort if the algorithm is not available or the length of - the key is not known. */ +/* Return the standard length in bits of the key for the cipher + algorithm with the identifier ALGORITHM. */ static unsigned int cipher_get_keylen (int algorithm) { @@ -614,17 +633,13 @@ cipher_get_keylen (int algorithm) log_bug ("cipher %d w/o key length\n", algorithm); _gcry_module_release (cipher); } - else - log_bug ("cipher %d not found\n", algorithm); ath_mutex_unlock (&ciphers_registered_lock); return len; } /* Return the block length of the cipher algorithm with the identifier - ALGORITHM. This function expects a valid algorithm and will abort - if the algorithm is not available or the length of the key is not - known. */ + ALGORITHM. This function return 0 for an invalid algorithm. */ static unsigned int cipher_get_blocksize (int algorithm) { @@ -642,8 +657,6 @@ cipher_get_blocksize (int algorithm) log_bug ("cipher %d w/o blocksize\n", algorithm); _gcry_module_release (cipher); } - else - log_bug ("cipher %d not found\n", algorithm); ath_mutex_unlock (&ciphers_registered_lock); return len; @@ -678,10 +691,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, /* If the application missed to call the random poll function, we do it here to ensure that it is used once in a while. */ _gcry_fast_random_poll (); - + REGISTER_DEFAULT_CIPHERS; - /* Fetch the according module and check wether the cipher is marked + /* Fetch the according module and check whether the cipher is marked available for use. */ ath_mutex_lock (&ciphers_registered_lock); module = _gcry_module_lookup_id (ciphers_registered, algo); @@ -693,7 +706,6 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, { /* Not available for use. */ err = GPG_ERR_CIPHER_ALGO; - _gcry_module_release (module); } else { @@ -707,7 +719,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, /* check flags */ if ((! err) - && ((flags & ~(0 + && ((flags & ~(0 | GCRY_CIPHER_SECURE | GCRY_CIPHER_ENABLE_SYNC | GCRY_CIPHER_CBC_CTS @@ -724,6 +736,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_CFB: case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: + case GCRY_CIPHER_MODE_AESWRAP: if ((cipher->encrypt == dummy_encrypt_block) || (cipher->decrypt == dummy_decrypt_block)) err = GPG_ERR_INV_CIPHER_MODE; @@ -769,7 +782,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, h = gcry_calloc (1, size); if (! h) - err = gpg_err_code_from_errno (errno); + err = gpg_err_code_from_syserror (); else { size_t off = 0; @@ -805,9 +818,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, h->bulk.cfb_dec = _gcry_aes_cfb_dec; h->bulk.cbc_enc = _gcry_aes_cbc_enc; h->bulk.cbc_dec = _gcry_aes_cbc_dec; + h->bulk.ctr_enc = _gcry_aes_ctr_enc; break; #endif /*USE_AES*/ - + default: break; } @@ -882,7 +896,10 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize), (void *) &c->context.c, c->cipher->contextsize); + c->marks.key = 1; } + else + c->marks.key = 0; return gcry_error (ret); } @@ -894,7 +911,7 @@ static void cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen ) { memset (c->u_iv.iv, 0, c->cipher->blocksize); - if (iv) + if (iv) { if (ivlen != c->cipher->blocksize) { @@ -905,7 +922,10 @@ cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen ) if (ivlen > c->cipher->blocksize) ivlen = c->cipher->blocksize; memcpy (c->u_iv.iv, iv, ivlen); + c->marks.iv = 1; } + else + c->marks.iv = 0; c->unused = 0; } @@ -918,61 +938,92 @@ cipher_reset (gcry_cipher_hd_t c) memcpy (&c->context.c, (char *) &c->context.c + c->cipher->contextsize, c->cipher->contextsize); + memset (&c->marks, 0, sizeof c->marks); memset (c->u_iv.iv, 0, c->cipher->blocksize); memset (c->lastiv, 0, c->cipher->blocksize); - memset (c->ctr, 0, c->cipher->blocksize); + memset (c->u_ctr.ctr, 0, c->cipher->blocksize); } -static void -do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nblocks ) + +static gcry_err_code_t +do_ecb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - unsigned int n; - + unsigned int blocksize = c->cipher->blocksize; + unsigned int n, nblocks; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if ((inbuflen % blocksize)) + return GPG_ERR_INV_LENGTH; + + nblocks = inbuflen / c->cipher->blocksize; + for (n=0; n < nblocks; n++ ) { - c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); - inbuf += c->cipher->blocksize; - outbuf += c->cipher->blocksize; + c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); + inbuf += blocksize; + outbuf += blocksize; } + return 0; } -static void -do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nblocks ) +static gcry_err_code_t +do_ecb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - unsigned int n; + unsigned int blocksize = c->cipher->blocksize; + unsigned int n, nblocks; - for (n=0; n < nblocks; n++ ) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if ((inbuflen % blocksize)) + return GPG_ERR_INV_LENGTH; + nblocks = inbuflen / c->cipher->blocksize; + + for (n=0; n < nblocks; n++ ) { - c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); - inbuf += c->cipher->blocksize; - outbuf += c->cipher->blocksize; + c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf ); + inbuf += blocksize; + outbuf += blocksize; } + + return 0; } -static void -do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_cbc_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned int n; unsigned char *ivp; int i; size_t blocksize = c->cipher->blocksize; - unsigned nblocks = nbytes / blocksize; + unsigned nblocks = inbuflen / blocksize; - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen)) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ((inbuflen % c->cipher->blocksize) + && !(inbuflen > c->cipher->blocksize + && (c->flags & GCRY_CIPHER_CBC_CTS))) + return GPG_ERR_INV_LENGTH; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { - if ((nbytes % blocksize) == 0) + if ((inbuflen % blocksize) == 0) nblocks--; } if (c->bulk.cbc_enc) { c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks, - (c->flags & GCRY_CIPHER_CBC_MAC)); + (c->flags & GCRY_CIPHER_CBC_MAC)); inbuf += nblocks * blocksize; if (!(c->flags & GCRY_CIPHER_CBC_MAC)) outbuf += nblocks * blocksize; @@ -991,17 +1042,17 @@ do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, } } - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { /* We have to be careful here, since outbuf might be equal to inbuf. */ int restbytes; unsigned char b; - if ((nbytes % blocksize) == 0) + if ((inbuflen % blocksize) == 0) restbytes = blocksize; else - restbytes = nbytes % blocksize; + restbytes = inbuflen % blocksize; outbuf -= blocksize; for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++) @@ -1012,40 +1063,51 @@ do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, } for (; i < blocksize; i++) outbuf[i] = 0 ^ *ivp++; - + c->cipher->encrypt (&c->context.c, outbuf, outbuf); memcpy (c->u_iv.iv, outbuf, blocksize); } + + return 0; } -static void -do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes) +static gcry_err_code_t +do_cbc_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned int n; unsigned char *ivp; int i; size_t blocksize = c->cipher->blocksize; - unsigned int nblocks = nbytes / blocksize; + unsigned int nblocks = inbuflen / blocksize; - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ((inbuflen % c->cipher->blocksize) + && !(inbuflen > c->cipher->blocksize + && (c->flags & GCRY_CIPHER_CBC_CTS))) + return GPG_ERR_INV_LENGTH; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { nblocks--; - if ((nbytes % blocksize) == 0) + if ((inbuflen % blocksize) == 0) nblocks--; memcpy (c->lastiv, c->u_iv.iv, blocksize); } if (c->bulk.cbc_dec) { - c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); inbuf += nblocks * blocksize; outbuf += nblocks * blocksize; } else { - for (n=0; n < nblocks; n++ ) + for (n=0; n < nblocks; n++ ) { /* Because outbuf and inbuf might be the same, we have to * save the original ciphertext block. We use LASTIV for @@ -1060,22 +1122,22 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, } } - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { int restbytes; - - if ((nbytes % blocksize) == 0) + + if ((inbuflen % blocksize) == 0) restbytes = blocksize; else - restbytes = nbytes % blocksize; - + restbytes = inbuflen % blocksize; + memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */ c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ ) outbuf[i] ^= *ivp++; - + memcpy(outbuf + blocksize, outbuf, restbytes); for(i=restbytes; i < blocksize; i++) c->u_iv.iv[i] = outbuf[i]; @@ -1084,32 +1146,38 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, outbuf[i] ^= *ivp++; /* c->lastiv is now really lastlastiv, does this matter? */ } + + return 0; } -static void -do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_cfb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned char *ivp; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; - - if ( nbytes <= c->unused ) + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ( inbuflen <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ /* XOR the input with the IV and store input into IV. */ for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused; - nbytes; - nbytes--, c->unused-- ) + inbuflen; + inbuflen--, c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); - return; + return 0; } if ( c->unused ) { /* XOR the input with the IV and store input into IV */ - nbytes -= c->unused; + inbuflen -= c->unused; for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } @@ -1117,17 +1185,17 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, /* Now we can process complete blocks. We use a loop as long as we have at least 2 blocks and use conditions for the rest. This also allows to use a bulk encryption function if available. */ - if (nbytes >= blocksize_x_2 && c->bulk.cfb_enc) + if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc) { - unsigned int nblocks = nbytes / blocksize; - c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + unsigned int nblocks = inbuflen / blocksize; + c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; - nbytes -= nblocks * blocksize; + inbuflen -= nblocks * blocksize; } else { - while ( nbytes >= blocksize_x_2 ) + while ( inbuflen >= blocksize_x_2 ) { int i; /* Encrypt the IV. */ @@ -1135,11 +1203,11 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, /* XOR the input with the IV and store input into IV. */ for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^= *inbuf++); - nbytes -= blocksize; + inbuflen -= blocksize; } } - if ( nbytes >= blocksize ) + if ( inbuflen >= blocksize ) { int i; /* Save the current IV and then encrypt the IV. */ @@ -1148,51 +1216,56 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, /* XOR the input with the IV and store input into IV */ for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^= *inbuf++); - nbytes -= blocksize; + inbuflen -= blocksize; } - if ( nbytes ) + if ( inbuflen ) { /* Save the current IV and then encrypt the IV. */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; /* Apply the XOR. */ - c->unused -= nbytes; - for(ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } + return 0; } -static void -do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_cfb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned char *ivp; unsigned long temp; int i; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; - - if (nbytes <= c->unused) + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (inbuflen <= c->unused) { /* Short enough to be encoded by the remaining XOR mask. */ /* XOR the input with the IV and store input into IV. */ for (ivp=c->u_iv.iv+blocksize - c->unused; - nbytes; - nbytes--, c->unused--) + inbuflen; + inbuflen--, c->unused--) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - return; + return 0; } - + if (c->unused) { /* XOR the input with the IV and store input into IV. */ - nbytes -= c->unused; + inbuflen -= c->unused; for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) { temp = *inbuf++; @@ -1200,21 +1273,21 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, *ivp++ = temp; } } - + /* Now we can process complete blocks. We use a loop as long as we have at least 2 blocks and use conditions for the rest. This also allows to use a bulk encryption function if available. */ - if (nbytes >= blocksize_x_2 && c->bulk.cfb_dec) + if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec) { - unsigned int nblocks = nbytes / blocksize; - c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + unsigned int nblocks = inbuflen / blocksize; + c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; - nbytes -= nblocks * blocksize; + inbuflen -= nblocks * blocksize; } else { - while (nbytes >= blocksize_x_2 ) + while (inbuflen >= blocksize_x_2 ) { /* Encrypt the IV. */ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); @@ -1225,11 +1298,11 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - nbytes -= blocksize; + inbuflen -= blocksize; } } - if (nbytes >= blocksize ) + if (inbuflen >= blocksize ) { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize); @@ -1241,99 +1314,109 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - nbytes -= blocksize; + inbuflen -= blocksize; } - if (nbytes) - { + if (inbuflen) + { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; /* Apply the XOR. */ - c->unused -= nbytes; - for (ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } } + return 0; } -static void -do_ofb_encrypt( gcry_cipher_hd_t c, - byte *outbuf, const byte *inbuf, unsigned nbytes ) +static gcry_err_code_t +do_ofb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - byte *ivp; + unsigned char *ivp; size_t blocksize = c->cipher->blocksize; - if ( nbytes <= c->unused ) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ( inbuflen <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ /* XOR the input with the IV */ for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused; - nbytes; - nbytes--, c->unused-- ) + inbuflen; + inbuflen--, c->unused-- ) *outbuf++ = (*ivp++ ^ *inbuf++); - return; + return 0; } if( c->unused ) { - nbytes -= c->unused; + inbuflen -= c->unused; for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = (*ivp++ ^ *inbuf++); } /* Now we can process complete blocks. */ - while ( nbytes >= blocksize ) + while ( inbuflen >= blocksize ) { int i; /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); - + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^ *inbuf++); - nbytes -= blocksize; + inbuflen -= blocksize; } - if ( nbytes ) + if ( inbuflen ) { /* process the remaining bytes */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; - c->unused -= nbytes; - for(ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) *outbuf++ = (*ivp++ ^ *inbuf++); } + return 0; } -static void -do_ofb_decrypt( gcry_cipher_hd_t c, - byte *outbuf, const byte *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_ofb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - byte *ivp; + unsigned char *ivp; size_t blocksize = c->cipher->blocksize; - - if( nbytes <= c->unused ) + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if( inbuflen <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ - for (ivp=c->u_iv.iv+blocksize - c->unused; nbytes; nbytes--,c->unused--) + for (ivp=c->u_iv.iv+blocksize - c->unused; inbuflen; inbuflen--,c->unused--) *outbuf++ = *ivp++ ^ *inbuf++; - return; + return 0; } if ( c->unused ) { - nbytes -= c->unused; + inbuflen -= c->unused; for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = *ivp++ ^ *inbuf++; } /* Now we can process complete blocks. */ - while ( nbytes >= blocksize ) + while ( inbuflen >= blocksize ) { int i; /* Encrypt the IV (and save the current one). */ @@ -1341,113 +1424,335 @@ do_ofb_decrypt( gcry_cipher_hd_t c, c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = *ivp++ ^ *inbuf++; - nbytes -= blocksize; + inbuflen -= blocksize; } - if ( nbytes ) + if ( inbuflen ) { /* Process the remaining bytes. */ /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; - c->unused -= nbytes; - for (ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) *outbuf++ = *ivp++ ^ *inbuf++; } + return 0; } -static void -do_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nbytes ) +static gcry_err_code_t +do_ctr_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned int n; - byte tmp[MAX_BLOCKSIZE]; int i; + unsigned int blocksize = c->cipher->blocksize; + unsigned int nblocks; - for(n=0; n < nbytes; n++) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + /* First process a left over encrypted counter. */ + if (c->unused) { - if ((n % c->cipher->blocksize) == 0) - { - c->cipher->encrypt (&c->context.c, tmp, c->ctr); - - for (i = c->cipher->blocksize; i > 0; i--) - { - c->ctr[i-1]++; - if (c->ctr[i-1] != 0) - break; - } - } - - /* XOR input with encrypted counter and store in output. */ - outbuf[n] = inbuf[n] ^ tmp[n % c->cipher->blocksize]; + gcry_assert (c->unused < blocksize); + i = blocksize - c->unused; + for (n=0; c->unused && n < inbuflen; c->unused--, n++, i++) + { + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ c->lastiv[i]; + } + inbuf += n; + outbuf += n; + inbuflen -= n; } + + + /* Use a bulk method if available. */ + nblocks = inbuflen / blocksize; + if (nblocks && c->bulk.ctr_enc) + { + c->bulk.ctr_enc (&c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks); + inbuf += nblocks * blocksize; + outbuf += nblocks * blocksize; + inbuflen -= nblocks * blocksize; + } + + /* If we don't have a bulk method use the standard method. We also + use this method for the a remaining partial block. */ + if (inbuflen) + { + unsigned char tmp[MAX_BLOCKSIZE]; + + for (n=0; n < inbuflen; n++) + { + if ((n % blocksize) == 0) + { + c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + + for (i = blocksize; i > 0; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + } + + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ tmp[n % blocksize]; + } + + /* Save the unused bytes of the counter. */ + n %= blocksize; + c->unused = (blocksize - n) % blocksize; + if (c->unused) + memcpy (c->lastiv+n, tmp+n, c->unused); + + wipememory (tmp, sizeof tmp); + } + + return 0; } -static void -do_ctr_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nbytes ) +static gcry_err_code_t +do_ctr_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - do_ctr_encrypt (c, outbuf, inbuf, nbytes); + return do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); +} + + +/* Perform the AES-Wrap algorithm as specified by RFC3394. We + implement this as a mode usable with any cipher algorithm of + blocksize 128. */ +static gcry_err_code_t +do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen ) +{ + int j, x; + unsigned int n, i; + unsigned char *r, *a, *b; + unsigned char t[8]; + +#if MAX_BLOCKSIZE < 8 +#error Invalid block size +#endif + /* We require a cipher with a 128 bit block length. */ + if (c->cipher->blocksize != 16) + return GPG_ERR_INV_LENGTH; + + /* The output buffer must be able to hold the input data plus one + additional block. */ + if (outbuflen < inbuflen + 8) + return GPG_ERR_BUFFER_TOO_SHORT; + /* Input data must be multiple of 64 bits. */ + if (inbuflen % 8) + return GPG_ERR_INV_ARG; + + n = inbuflen / 8; + + /* We need at least two 64 bit blocks. */ + if (n < 2) + return GPG_ERR_INV_ARG; + + r = outbuf; + a = outbuf; /* We store A directly in OUTBUF. */ + b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ + + /* If an IV has been set we use that IV as the Alternative Initial + Value; if it has not been set we use the standard value. */ + if (c->marks.iv) + memcpy (a, c->u_iv.iv, 8); + else + memset (a, 0xa6, 8); + + /* Copy the inbuf to the outbuf. */ + memmove (r+8, inbuf, inbuflen); + + memset (t, 0, sizeof t); /* t := 0. */ + + for (j = 0; j <= 5; j++) + { + for (i = 1; i <= n; i++) + { + /* B := AES_k( A | R[i] ) */ + memcpy (b, a, 8); + memcpy (b+8, r+i*8, 8); + c->cipher->encrypt (&c->context.c, b, b); + /* t := t + 1 */ + for (x = 7; x >= 0; x--) + { + t[x]++; + if (t[x]) + break; + } + /* A := MSB_64(B) ^ t */ + for (x=0; x < 8; x++) + a[x] = b[x] ^ t[x]; + /* R[i] := LSB_64(B) */ + memcpy (r+i*8, b+8, 8); + } + } + + return 0; +} + +/* Perform the AES-Unwrap algorithm as specified by RFC3394. We + implement this as a mode usable with any cipher algorithm of + blocksize 128. */ +static gcry_err_code_t +do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + int j, x; + unsigned int n, i; + unsigned char *r, *a, *b; + unsigned char t[8]; + +#if MAX_BLOCKSIZE < 8 +#error Invalid block size +#endif + /* We require a cipher with a 128 bit block length. */ + if (c->cipher->blocksize != 16) + return GPG_ERR_INV_LENGTH; + + /* The output buffer must be able to hold the input data minus one + additional block. Fixme: The caller has more restrictive checks + - we may want to fix them for this mode. */ + if (outbuflen + 8 < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + /* Input data must be multiple of 64 bits. */ + if (inbuflen % 8) + return GPG_ERR_INV_ARG; + + n = inbuflen / 8; + + /* We need at least three 64 bit blocks. */ + if (n < 3) + return GPG_ERR_INV_ARG; + + r = outbuf; + a = c->lastiv; /* We use c->LASTIV as buffer for A. */ + b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ + + /* Copy the inbuf to the outbuf and save A. */ + memcpy (a, inbuf, 8); + memmove (r, inbuf+8, inbuflen-8); + n--; /* Reduce to actual number of data blocks. */ + + /* t := 6 * n */ + i = n * 6; /* The range is valid because: n = inbuflen / 8 - 1. */ + for (x=0; x < 8 && x < sizeof (i); x++) + t[7-x] = i >> (8*x); + for (; x < 8; x++) + t[7-x] = 0; + + for (j = 5; j >= 0; j--) + { + for (i = n; i >= 1; i--) + { + /* B := AES_k^1( (A ^ t)| R[i] ) */ + for (x = 0; x < 8; x++) + b[x] = a[x] ^ t[x]; + memcpy (b+8, r+(i-1)*8, 8); + c->cipher->decrypt (&c->context.c, b, b); + /* t := t - 1 */ + for (x = 7; x >= 0; x--) + { + t[x]--; + if (t[x] != 0xff) + break; + } + /* A := MSB_64(B) */ + memcpy (a, b, 8); + /* R[i] := LSB_64(B) */ + memcpy (r+(i-1)*8, b+8, 8); + } + } + + /* If an IV has been set we compare against this Alternative Initial + Value; if it has not been set we compare against the standard IV. */ + if (c->marks.iv) + j = memcmp (a, c->u_iv.iv, 8); + else + { + for (j=0, x=0; x < 8; x++) + if (a[x] != 0xa6) + { + j=1; + break; + } + } + return j? GPG_ERR_CHECKSUM : 0; } /**************** * Encrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. - * Depending on the mode some contraints apply to NBYTES. + * Depending on the mode some constraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, - const byte *inbuf, unsigned int nbytes) +cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) { - gcry_err_code_t rc = GPG_ERR_NO_ERROR; + gcry_err_code_t rc; - switch( c->mode ) { - case GCRY_CIPHER_MODE_ECB: - if (!(nbytes%c->cipher->blocksize)) - do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CBC: - if (!(nbytes%c->cipher->blocksize) - || (nbytes > c->cipher->blocksize - && (c->flags & GCRY_CIPHER_CBC_CTS))) - do_cbc_encrypt(c, outbuf, inbuf, nbytes ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CFB: - do_cfb_encrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_OFB: - do_ofb_encrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_CTR: - do_ctr_encrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_STREAM: - c->cipher->stencrypt ( &c->context.c, - outbuf, (byte*)/*arggg*/inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_NONE: - if (fips_mode () || !_gcry_get_debug_flag (0)) - { - fips_signal_error ("cipher mode NONE used"); - rc = GPG_ERR_INV_CIPHER_MODE; - } - else - { - if ( inbuf != outbuf ) - memmove (outbuf, inbuf, nbytes); - } - break; - default: - log_fatal("cipher_encrypt: invalid mode %d\n", c->mode ); - rc = GPG_ERR_INV_CIPHER_MODE; - break; + switch (c->mode) + { + case GCRY_CIPHER_MODE_ECB: + rc = do_ecb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CBC: + rc = do_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CFB: + rc = do_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_OFB: + rc = do_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CTR: + rc = do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_AESWRAP: + rc = do_aeswrap_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_STREAM: + c->cipher->stencrypt (&c->context.c, + outbuf, (byte*)/*arggg*/inbuf, inbuflen); + rc = 0; + break; + + case GCRY_CIPHER_MODE_NONE: + if (fips_mode () || !_gcry_get_debug_flag (0)) + { + fips_signal_error ("cipher mode NONE used"); + rc = GPG_ERR_INV_CIPHER_MODE; + } + else + { + if (inbuf != outbuf) + memmove (outbuf, inbuf, inbuflen); + rc = 0; + } + break; + + default: + log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode ); + rc = GPG_ERR_INV_CIPHER_MODE; + break; } - return rc; + + return rc; } @@ -1461,29 +1766,15 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, { gcry_err_code_t err; - if (!in) - { - /* Caller requested in-place encryption. */ - /* Actually cipher_encrypt() does not need to know about it, but - * we may change it in the future to get better performance. */ - err = cipher_encrypt (h, out, out, outsize); - } - else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ? - h->cipher->blocksize : inlen)) - err = GPG_ERR_TOO_SHORT; - else if ((h->mode == GCRY_CIPHER_MODE_ECB - || (h->mode == GCRY_CIPHER_MODE_CBC - && (! ((h->flags & GCRY_CIPHER_CBC_CTS) - && (inlen > h->cipher->blocksize))))) - && (inlen % h->cipher->blocksize)) - err = GPG_ERR_INV_ARG; + if (!in) /* Caller requested in-place encryption. */ + err = cipher_encrypt (h, out, outsize, out, outsize); else - err = cipher_encrypt (h, out, in, inlen); + err = cipher_encrypt (h, out, outsize, in, inlen); + /* Failsafe: Make sure that the plaintext will never make it into + OUT if the encryption returned an error. */ if (err && out) - memset (out, 0x42, outsize); /* Failsafe: Make sure that the - plaintext will never make it into - OUT. */ + memset (out, 0x42, outsize); return gcry_error (err); } @@ -1493,60 +1784,67 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, /**************** * Decrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. - * Depending on the mode some some contraints apply to NBYTES. + * Depending on the mode some some contraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nbytes) +cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) { - gcry_err_code_t rc = GPG_ERR_NO_ERROR; + gcry_err_code_t rc; - switch( c->mode ) { - case GCRY_CIPHER_MODE_ECB: - if (!(nbytes%c->cipher->blocksize)) - do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CBC: - if (!(nbytes%c->cipher->blocksize) - || (nbytes > c->cipher->blocksize - && (c->flags & GCRY_CIPHER_CBC_CTS))) - do_cbc_decrypt(c, outbuf, inbuf, nbytes ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CFB: - do_cfb_decrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_OFB: - do_ofb_decrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_CTR: - do_ctr_decrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_STREAM: - c->cipher->stdecrypt ( &c->context.c, - outbuf, (byte*)/*arggg*/inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_NONE: - if (fips_mode () || !_gcry_get_debug_flag (0)) - { - fips_signal_error ("cipher mode NONE used"); - rc = GPG_ERR_INV_CIPHER_MODE; - } - else - { - if (inbuf != outbuf) - memmove (outbuf, inbuf, nbytes); - } - break; - default: - log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); - rc = GPG_ERR_INV_CIPHER_MODE; - break; + switch (c->mode) + { + case GCRY_CIPHER_MODE_ECB: + rc = do_ecb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CBC: + rc = do_cbc_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CFB: + rc = do_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_OFB: + rc = do_ofb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CTR: + rc = do_ctr_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_AESWRAP: + rc = do_aeswrap_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_STREAM: + c->cipher->stdecrypt (&c->context.c, + outbuf, (byte*)/*arggg*/inbuf, inbuflen); + rc = 0; + break; + + case GCRY_CIPHER_MODE_NONE: + if (fips_mode () || !_gcry_get_debug_flag (0)) + { + fips_signal_error ("cipher mode NONE used"); + rc = GPG_ERR_INV_CIPHER_MODE; + } + else + { + if (inbuf != outbuf) + memmove (outbuf, inbuf, inbuflen); + rc = 0; + } + break; + + default: + log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); + rc = GPG_ERR_INV_CIPHER_MODE; + break; } - return rc; + + return rc; } @@ -1554,25 +1852,12 @@ gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize, const void *in, size_t inlen) { - gcry_err_code_t err = 0; + gcry_err_code_t err; - if (!in) - { - /* Caller requested in-place encryption. */ - /* Actually cipher_encrypt() does not need to know about it, but - * we may change it in the future to get better performance. */ - err = cipher_decrypt (h, out, out, outsize); - } - else if (outsize < inlen) - err = GPG_ERR_TOO_SHORT; - else if (((h->mode == GCRY_CIPHER_MODE_ECB) - || ((h->mode == GCRY_CIPHER_MODE_CBC) - && (! ((h->flags & GCRY_CIPHER_CBC_CTS) - && (inlen > h->cipher->blocksize))))) - && (inlen % h->cipher->blocksize) != 0) - err = GPG_ERR_INV_ARG; + if (!in) /* Caller requested in-place encryption. */ + err = cipher_decrypt (h, out, outsize, out, outsize); else - err = cipher_decrypt (h, out, in, inlen); + err = cipher_decrypt (h, out, outsize, in, inlen); return gcry_error (err); } @@ -1618,9 +1903,15 @@ gpg_error_t _gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen) { if (ctr && ctrlen == hd->cipher->blocksize) - memcpy (hd->ctr, ctr, hd->cipher->blocksize); + { + memcpy (hd->u_ctr.ctr, ctr, hd->cipher->blocksize); + hd->unused = 0; + } else if (!ctr || !ctrlen) - memset (hd->ctr, 0, hd->cipher->blocksize); + { + memset (hd->u_ctr.ctr, 0, hd->cipher->blocksize); + hd->unused = 0; + } else return gpg_error (GPG_ERR_INV_ARG); return 0; @@ -1679,17 +1970,12 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) break; case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr. */ - if (buffer && buflen == h->cipher->blocksize) - memcpy (h->ctr, buffer, h->cipher->blocksize); - else if (buffer == NULL || buflen == 0) - memset (h->ctr, 0, h->cipher->blocksize); - else - rc = GPG_ERR_INV_ARG; + rc = gpg_err_code (_gcry_cipher_setctr (h, buffer, buflen)); break; case 61: /* Disable weak key detection (private). */ if (h->extraspec->set_extra_info) - rc = h->extraspec->set_extra_info + rc = h->extraspec->set_extra_info (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0); else rc = GPG_ERR_NOT_SUPPORTED; @@ -1697,7 +1983,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) case 62: /* Return current input vector (private). */ /* This is the input block as used in CFB and OFB mode which has - initially been set as IV. The returned format is: + initially been set as IV. The returned format is: 1 byte Actual length of the block in bytes. n byte The block. If the provided buffer is too short, an error is returned. */ @@ -1708,7 +1994,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) unsigned char *ivp; unsigned char *dst = buffer; int n = h->unused; - + if (!n) n = h->cipher->blocksize; gcry_assert (n <= h->cipher->blocksize); @@ -1730,10 +2016,10 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) /* Return information about the cipher handle H. CMD is the kind of information requested. BUFFER and NBYTES are reserved for now. - There are no values for CMD yet defined. + There are no values for CMD yet defined. + + The function always returns GPG_ERR_INV_OP. - The fucntion always returns GPG_ERR_INV_OP. - */ gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) @@ -1770,11 +2056,11 @@ gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) GCRYCTL_TEST_ALGO: Returns 0 if the specified algorithm ALGO is available for use. BUFFER and NBYTES must be zero. - + Note: Because this function is in most cases used to return an integer value, we can make it easier for the caller to just look at the return value. The caller will in all cases consult the value - and thereby detecting whether a error occured or not (i.e. while + and thereby detecting whether a error occurred or not (i.e. while checking the block size) */ gcry_error_t @@ -1794,8 +2080,7 @@ gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes) if ((ui > 0) && (ui <= 512)) *nbytes = (size_t) ui / 8; else - /* The only reason is an invalid algo or a strange - blocksize. */ + /* The only reason for an error is an invalid algo. */ err = GPG_ERR_CIPHER_ALGO; } break; @@ -1839,7 +2124,7 @@ gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes) gcry_cipher_algo_info because it allows for proper type checking. */ size_t -gcry_cipher_get_algo_keylen (int algo) +gcry_cipher_get_algo_keylen (int algo) { size_t n; @@ -1855,7 +2140,7 @@ gcry_cipher_get_algo_keylen (int algo) gcry_cipher_algo_info because it allows for proper type checking. */ size_t -gcry_cipher_get_algo_blklen (int algo) +gcry_cipher_get_algo_blklen (int algo) { size_t n; @@ -1916,7 +2201,7 @@ _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report) { ec = GPG_ERR_CIPHER_ALGO; if (report) - report ("cipher", algo, "module", + report ("cipher", algo, "module", module && !(module->flags & FLAG_MODULE_DISABLED)? "no selftest available" : module? "algorithm disabled" : "algorithm not found"); diff --git a/grub-core/lib/libgcrypt/cipher/crc.c b/grub-core/lib/libgcrypt/cipher/crc.c index d04fff894..9e406f1b1 100644 --- a/grub-core/lib/libgcrypt/cipher/crc.c +++ b/grub-core/lib/libgcrypt/cipher/crc.c @@ -25,7 +25,6 @@ #include #include "g10lib.h" -#include "memory.h" #include "cipher.h" #include "bithelp.h" diff --git a/grub-core/lib/libgcrypt/cipher/des.c b/grub-core/lib/libgcrypt/cipher/des.c index f91df7771..96b06ae36 100644 --- a/grub-core/lib/libgcrypt/cipher/des.c +++ b/grub-core/lib/libgcrypt/cipher/des.c @@ -22,7 +22,7 @@ * Bruce Schneier: Applied Cryptography. Second Edition. * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. * This implementation is according to the definition of DES in FIPS - * PUB 46-2 from December 1993. + * PUB 46-2 from December 1993. */ @@ -106,7 +106,7 @@ * * if ( (error_msg = selftest()) ) * { - * fprintf(stderr, "An error in the DES/Tripple-DES implementation occured: %s\n", error_msg); + * fprintf(stderr, "An error in the DES/Triple-DES implementation occurred: %s\n", error_msg); * abort(); * } */ @@ -388,7 +388,7 @@ static byte weak_keys[64][8] = }; static unsigned char weak_keys_chksum[20] = { 0xD0, 0xCF, 0x07, 0x38, 0x93, 0x70, 0x8A, 0x83, 0x7D, 0xD7, - 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 + 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 }; @@ -888,12 +888,12 @@ selftest (void) if (memcmp (input, result, 8)) return "Triple-DES test failed."; } - + /* * More Triple-DES test. These are testvectors as used by SSLeay, * thanks to Jeroen C. van Gelderen. */ - { + { struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, @@ -901,7 +901,7 @@ selftest (void) { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, - + { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, @@ -966,7 +966,7 @@ selftest (void) { tripledes_set3keys (des3, testdata[i].key, testdata[i].key + 8, testdata[i].key + 16); - + tripledes_ecb_encrypt (des3, testdata[i].plain, result); if (memcmp (testdata[i].cipher, result, 8)) return "Triple-DES SSLeay test failed on encryption."; @@ -1047,7 +1047,7 @@ do_tripledes_set_extra_info (void *context, int what, break; default: - ec = GPG_ERR_INV_OP; + ec = GPG_ERR_INV_OP; break; } return ec; @@ -1112,7 +1112,7 @@ do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) -/* +/* Self-test section. */ @@ -1123,7 +1123,7 @@ selftest_fips (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; - + (void)extended; /* No extended tests available. */ what = "low-level"; @@ -1160,7 +1160,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_CIPHER_ALGO; break; - + } return ec; } @@ -1189,7 +1189,7 @@ gcry_cipher_spec_t _gcry_cipher_spec_tripledes = do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt }; -cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = +cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = { run_selftests, do_tripledes_set_extra_info diff --git a/grub-core/lib/libgcrypt/cipher/dsa.c b/grub-core/lib/libgcrypt/cipher/dsa.c index 100710f97..883a815f2 100644 --- a/grub-core/lib/libgcrypt/cipher/dsa.c +++ b/grub-core/lib/libgcrypt/cipher/dsa.c @@ -74,7 +74,7 @@ static const char sample_secret_key[] = " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)" " (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))"; /* A sample 1024 bit DSA key used for the selftests (public only). */ -static const char sample_public_key[] = +static const char sample_public_key[] = "(public-key" " (dsa" " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" @@ -141,14 +141,19 @@ gen_k( gcry_mpi_t q ) unsigned int nbytes = (nbits+7)/8; char *rndbuf = NULL; + /* To learn why we don't use mpi_mod to get the requested bit size, + read the paper: "The Insecurity of the Digital Signature + Algorithm with Partially Known Nonces" by Nguyen and Shparlinski. + Journal of Cryptology, New York. Vol 15, nr 3 (2003) */ + if ( DBG_CIPHER ) log_debug("choosing a random k "); - for (;;) + for (;;) { if( DBG_CIPHER ) progress('.'); - if ( !rndbuf || nbits < 32 ) + if ( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( (nbits+7)/8, GCRY_STRONG_RANDOM ); @@ -156,13 +161,20 @@ gen_k( gcry_mpi_t q ) else { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call - to get_random_bytes() and use this the here maybe it is - easier to do this directly in random.c. */ + to get_random_bytes() and use these extra bytes here. + However the required management code is more complex and + thus we better use this simple method. */ char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); memcpy( rndbuf,pp, 4 ); gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); + + /* Make sure we have the requested number of bits. This code + looks a bit funny but it is easy to understand if you + consider that mpi_set_highbit clears all higher bits. We + don't have a clear_highbit, thus we first set the high bit + and then clear it again. */ if ( mpi_test_bit( k, nbits-1 ) ) mpi_set_highbit( k, nbits-1 ); else @@ -172,7 +184,7 @@ gen_k( gcry_mpi_t q ) } if( !(mpi_cmp( k, q ) < 0) ) /* check: k < q */ - { + { if( DBG_CIPHER ) progress('+'); continue; /* no */ @@ -188,7 +200,7 @@ gen_k( gcry_mpi_t q ) gcry_free(rndbuf); if( DBG_CIPHER ) progress('\n'); - + return k; } @@ -315,7 +327,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, mpi_add_ui (h, h, 1); /* g = h^e mod p */ gcry_mpi_powm (g, h, e, p); - } + } while (!mpi_cmp_ui (g, 1)); /* Continue until g != 1. */ } @@ -330,13 +342,13 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, x = mpi_alloc_secure( mpi_get_nlimbs(q) ); mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ rndbuf = NULL; - do + do { if( DBG_CIPHER ) progress('.'); if( !rndbuf ) rndbuf = gcry_random_bytes_secure ((qbits+7)/8, random_level); - else + else { /* Change only some of the higher bits (= 2 bytes)*/ char *r = gcry_random_bytes_secure (2, random_level); memcpy(rndbuf, r, 2 ); @@ -345,7 +357,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, _gcry_mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); mpi_clear_highbit( x, qbits+1 ); - } + } while ( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); gcry_free(rndbuf); mpi_free( e ); @@ -355,7 +367,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, y = mpi_alloc( mpi_get_nlimbs(p) ); gcry_mpi_powm( y, g, x, p ); - if( DBG_CIPHER ) + if( DBG_CIPHER ) { progress('\n'); log_mpidump("dsa p", p ); @@ -406,8 +418,8 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, const void *seed; size_t seedlen; } initial_seed = { NULL, NULL, 0 }; - gcry_mpi_t prime_q = NULL; - gcry_mpi_t prime_p = NULL; + gcry_mpi_t prime_q = NULL; + gcry_mpi_t prime_p = NULL; gcry_mpi_t value_g = NULL; /* The generator. */ gcry_mpi_t value_y = NULL; /* g^x mod p */ gcry_mpi_t value_x = NULL; /* The secret exponent. */ @@ -467,15 +479,15 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, initial_seed.seed = gcry_sexp_nth_data (initial_seed.sexp, 1, &initial_seed.seedlen); } - + /* Fixme: Enable 186-3 after it has been approved and after fixing the generation function. */ /* if (use_fips186_2) */ (void)use_fips186_2; - ec = _gcry_generate_fips186_2_prime (nbits, qbits, - initial_seed.seed, + ec = _gcry_generate_fips186_2_prime (nbits, qbits, + initial_seed.seed, initial_seed.seedlen, - &prime_q, &prime_p, + &prime_q, &prime_p, r_counter, r_seed, r_seedlen); /* else */ @@ -493,33 +505,33 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, mpi_sub_ui (value_e, prime_p, 1); mpi_fdiv_q (value_e, value_e, prime_q ); value_g = mpi_alloc_like (prime_p); - value_h = mpi_alloc_set_ui (1); + value_h = mpi_alloc_set_ui (1); do { mpi_add_ui (value_h, value_h, 1); /* g = h^e mod p */ mpi_powm (value_g, value_h, value_e, prime_p); - } + } while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */ } /* Select a random number x with: 0 < x < q */ value_x = gcry_mpi_snew (qbits); - do + do { if( DBG_CIPHER ) progress('.'); gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM); mpi_clear_highbit (value_x, qbits+1); - } + } while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0)); /* y = g^x mod p */ value_y = mpi_alloc_like (prime_p); gcry_mpi_powm (value_y, value_g, value_x, prime_p); - if (DBG_CIPHER) + if (DBG_CIPHER) { progress('\n'); log_mpidump("dsa p", prime_p ); @@ -691,7 +703,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, int use_fips186_2 = 0; int use_fips186 = 0; dsa_domain_t domain; - + (void)algo; /* No need to check it. */ (void)evalue; /* Not required for DSA. */ @@ -700,7 +712,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (genparms) { gcry_sexp_t domainsexp; - + /* Parse the optional qbits element. */ l1 = gcry_sexp_find_token (genparms, "qbits", 0); if (l1) @@ -708,7 +720,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, char buf[50]; const char *s; size_t n; - + s = gcry_sexp_nth_data (l1, 1, &n); if (!s || n >= DIM (buf) - 1 ) { @@ -760,7 +772,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_sexp_release (deriveparms); return GPG_ERR_INV_VALUE; } - + /* Put all domain parameters into the domain object. */ l1 = gcry_sexp_find_token (domainsexp, "p", 0); domain.p = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); @@ -804,7 +816,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, { /* Format the seed-values unless domain parameters are used for which a H_VALUE of NULL is an indication. */ - ec = gpg_err_code (gcry_sexp_build + ec = gpg_err_code (gcry_sexp_build (&seedinfo, NULL, "(seed-values(counter %d)(seed %b)(h %m))", counter, (int)seedlen, seed, h_value)); @@ -879,7 +891,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, p = stpcpy (p, ")"); } p = stpcpy (p, ")"); - + /* Allocate space for the list of factors plus one for an S-expression plus an extra NULL entry for safety and fill it with the factors. */ @@ -894,8 +906,8 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, for (j=0; j < nfactors; j++) arg_list[i++] = (*retfactors) + j; arg_list[i] = NULL; - - ec = gpg_err_code (gcry_sexp_build_array + + ec = gpg_err_code (gcry_sexp_build_array (r_extrainfo, NULL, format, arg_list)); } } @@ -907,6 +919,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_mpi_release ((*retfactors)[i]); (*retfactors)[i] = NULL; } + gcry_free (*retfactors); *retfactors = NULL; if (ec) { @@ -1022,19 +1035,19 @@ dsa_get_nbits (int algo, gcry_mpi_t *pkey) -/* +/* Self-test section. */ static const char * selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) { - static const char sample_data[] = - "(data (flags pkcs1)" - " (hash sha1 #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; - static const char sample_data_bad[] = - "(data (flags pkcs1)" - " (hash sha1 #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; + static const char sample_data[] = + "(data (flags raw)" + " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; + static const char sample_data_bad[] = + "(data (flags raw)" + " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; const char *errtxt = NULL; gcry_error_t err; @@ -1045,7 +1058,7 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) err = gcry_sexp_sscan (&data, NULL, sample_data, strlen (sample_data)); if (!err) - err = gcry_sexp_sscan (&data_bad, NULL, + err = gcry_sexp_sscan (&data_bad, NULL, sample_data_bad, strlen (sample_data_bad)); if (err) { @@ -1092,10 +1105,10 @@ selftests_dsa (selftest_report_func_t report) /* Convert the S-expressions into the internal representation. */ what = "convert"; - err = gcry_sexp_sscan (&skey, NULL, + err = gcry_sexp_sscan (&skey, NULL, sample_secret_key, strlen (sample_secret_key)); if (!err) - err = gcry_sexp_sscan (&pkey, NULL, + err = gcry_sexp_sscan (&pkey, NULL, sample_public_key, strlen (sample_public_key)); if (err) { @@ -1145,7 +1158,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1162,7 +1175,7 @@ static const char *dsa_names[] = gcry_pk_spec_t _gcry_pubkey_spec_dsa = { - "DSA", dsa_names, + "DSA", dsa_names, "pqgy", "pqgyx", "", "rs", "pqgy", GCRY_PK_USAGE_SIGN, dsa_generate, @@ -1173,9 +1186,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_dsa = dsa_verify, dsa_get_nbits }; -pk_extra_spec_t _gcry_pubkey_extraspec_dsa = +pk_extra_spec_t _gcry_pubkey_extraspec_dsa = { run_selftests, dsa_generate_ext }; - diff --git a/grub-core/lib/libgcrypt/cipher/ecc.c b/grub-core/lib/libgcrypt/cipher/ecc.c index fcbd8e3a9..b8487dc13 100644 --- a/grub-core/lib/libgcrypt/cipher/ecc.c +++ b/grub-core/lib/libgcrypt/cipher/ecc.c @@ -1,18 +1,18 @@ /* ecc.c - Elliptic Curve Cryptography - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. This file is part of Libgcrypt. - + Libgcrypt is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + Libgcrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, @@ -33,20 +33,21 @@ up. In fact there is not much left of the orginally code except for some variable names and the text book implementaion of the sign and verification algorithms. The arithmetic functions have entirely - been rewritten and moved to mpi/ec.c. */ + been rewritten and moved to mpi/ec.c. + + ECDH encrypt and decrypt code written by Andrey Jivsov, +*/ /* TODO: - - If we support point compression we need to decide how to compute - the keygrip - it should not change due to compression. + - If we support point compression we need to uncompress before + computing the keygrip - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a special case in mpi_powm or check whether mpi_mulm is faster. - Decide whether we should hide the mpi_point_t definition. - - - Support more than just ECDSA. */ @@ -59,7 +60,6 @@ #include "mpi.h" #include "cipher.h" - /* Definition of a curve. */ typedef struct { @@ -68,7 +68,8 @@ typedef struct gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ mpi_point_t G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ -} elliptic_curve_t; + const char *name; /* Name of curve or NULL. */ +} elliptic_curve_t; typedef struct @@ -90,7 +91,7 @@ static const struct { const char *name; /* Our name. */ const char *other; /* Other name. */ -} curve_aliases[] = +} curve_aliases[] = { { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ { "NIST P-192", "prime192v1" }, /* X9.62 name. */ @@ -100,11 +101,11 @@ static const struct { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ - { "NIST P-256", "prime256v1" }, + { "NIST P-256", "prime256v1" }, { "NIST P-256", "secp256r1" }, { "NIST P-384", "secp384r1" }, - { "NIST P-384", "1.3.132.0.34" }, + { "NIST P-384", "1.3.132.0.34" }, { "NIST P-521", "secp521r1" }, { "NIST P-521", "1.3.132.0.35" }, @@ -120,11 +121,7 @@ static const struct { NULL, NULL} }; - - -/* This static table defines all available curves. */ -static const struct -{ +typedef struct { const char *desc; /* Description of the curve. */ unsigned int nbits; /* Number of bits. */ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ @@ -132,7 +129,10 @@ static const struct const char *a, *b; /* The coefficients. */ const char *n; /* The order of the base point. */ const char *g_x, *g_y; /* Base point. */ -} domain_parms[] = +} ecc_domain_parms_t; + +/* This static table defines all available curves. */ +static const ecc_domain_parms_t domain_parms[] = { { "NIST P-192", 192, 1, @@ -197,7 +197,7 @@ static const struct "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" }, - { "brainpoolP160r1", 160, 0, + { "brainpoolP160r1", 160, 0, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -206,7 +206,7 @@ static const struct "0x1667cb477a1a8ec338f94741669c976316da6321" }, - { "brainpoolP192r1", 192, 0, + { "brainpoolP192r1", 192, 0, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -369,7 +369,6 @@ curve_copy (elliptic_curve_t E) } - /* Helper to scan a hex string. */ static gcry_mpi_t scanval (const char *string) @@ -400,10 +399,10 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) axb = mpi_new (0); y = mpi_new (0); - mpi_powm (x_3, x, three, base->p); - mpi_mulm (axb, base->a, x, base->p); - mpi_addm (axb, axb, base->b, base->p); - mpi_addm (y, x_3, axb, base->p); + mpi_powm (x_3, x, three, base->p); + mpi_mulm (axb, base->a, x, base->p); + mpi_addm (axb, axb, base->b, base->p); + mpi_addm (y, x_3, axb, base->p); mpi_free (x_3); mpi_free (axb); @@ -412,9 +411,6 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) } - - - /* Generate a random secret scalar k with an order of p At the beginning this was identical to the code is in elgamal.c. @@ -428,7 +424,8 @@ gen_k (gcry_mpi_t p, int security_level) nbits = mpi_get_nbits (p); k = mpi_snew (nbits); if (DBG_CIPHER) - log_debug ("choosing a random k of %u bits\n", nbits); + log_debug ("choosing a random k of %u bits at seclevel %d\n", + nbits, security_level); gcry_mpi_randomize (k, nbits, security_level); @@ -437,23 +434,27 @@ gen_k (gcry_mpi_t p, int security_level) return k; } -/**************** - * Generate the crypto system setup. - * As of now the fix NIST recommended values are used. - * The subgroup generator point is in another function: gen_big_point. - */ + +/* Generate the crypto system setup. This function takes the NAME of + a curve or the desired number of bits and stores at R_CURVE the + parameters of the named curve or those of a suitable curve. The + chosen number of bits is stored on R_NBITS. */ static gpg_err_code_t -generate_curve (unsigned int nbits, const char *name, - elliptic_curve_t *curve, unsigned int *r_nbits) +fill_in_curve (unsigned int nbits, const char *name, + elliptic_curve_t *curve, unsigned int *r_nbits) { int idx, aliasno; + const char *resname = NULL; /* Set to a found curve name. */ if (name) { - /* First check nor native curves. */ + /* First check our native curves. */ for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (name, domain_parms[idx].desc)) - break; + { + resname = domain_parms[idx].desc; + break; + } /* If not found consult the alias table. */ if (!domain_parms[idx].desc) { @@ -465,7 +466,10 @@ generate_curve (unsigned int nbits, const char *name, for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc)) - break; + { + resname = domain_parms[idx].desc; + break; + } } } } @@ -482,8 +486,7 @@ generate_curve (unsigned int nbits, const char *name, possible to bypass this check by specifying the curve parameters directly. */ if (fips_mode () && !domain_parms[idx].fips ) - return GPG_ERR_NOT_SUPPORTED; - + return GPG_ERR_NOT_SUPPORTED; *r_nbits = domain_parms[idx].nbits; curve->p = scanval (domain_parms[idx].p); @@ -493,6 +496,7 @@ generate_curve (unsigned int nbits, const char *name, curve->G.x = scanval (domain_parms[idx].g_x); curve->G.y = scanval (domain_parms[idx].g_y); curve->G.z = mpi_alloc_set_ui (1); + curve->name = resname; return 0; } @@ -504,33 +508,39 @@ generate_curve (unsigned int nbits, const char *name, */ static gpg_err_code_t generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, + int transient_key, gcry_mpi_t g_x, gcry_mpi_t g_y, - gcry_mpi_t q_x, gcry_mpi_t q_y) + gcry_mpi_t q_x, gcry_mpi_t q_y, + const char **r_usedcurve) { gpg_err_code_t err; elliptic_curve_t E; gcry_mpi_t d; mpi_point_t Q; mpi_ec_t ctx; + gcry_random_level_t random_level; - err = generate_curve (nbits, name, &E, &nbits); + *r_usedcurve = NULL; + + err = fill_in_curve (nbits, name, &E, &nbits); if (err) return err; if (DBG_CIPHER) { - log_mpidump ("ecc generation p", E.p); - log_mpidump ("ecc generation a", E.a); - log_mpidump ("ecc generation b", E.b); - log_mpidump ("ecc generation n", E.n); - log_mpidump ("ecc generation Gx", E.G.x); - log_mpidump ("ecc generation Gy", E.G.y); - log_mpidump ("ecc generation Gz", E.G.z); + log_mpidump ("ecgen curve p", E.p); + log_mpidump ("ecgen curve a", E.a); + log_mpidump ("ecgen curve b", E.b); + log_mpidump ("ecgen curve n", E.n); + log_mpidump ("ecgen curve Gx", E.G.x); + log_mpidump ("ecgen curve Gy", E.G.y); + log_mpidump ("ecgen curve Gz", E.G.z); + if (E.name) + log_debug ("ecgen curve used: %s\n", E.name); } - if (DBG_CIPHER) - log_debug ("choosing a random x of size %u\n", nbits); - d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM); + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + d = gen_k (E.n, random_level); /* Compute Q. */ point_init (&Q); @@ -552,27 +562,29 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, if (g_x && g_y) { if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx)) - log_fatal ("ecc generate: Failed to get affine coordinates\n"); + log_fatal ("ecgen: Failed to get affine coordinates\n"); } if (q_x && q_y) { if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx)) - log_fatal ("ecc generate: Failed to get affine coordinates\n"); + log_fatal ("ecgen: Failed to get affine coordinates\n"); } _gcry_mpi_ec_free (ctx); point_free (&Q); mpi_free (d); + + *r_usedcurve = E.name; curve_free (&E); - /* Now we can test our keys (this should never fail!). */ + /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); return 0; } -/**************** +/* * To verify correct skey it use a random information. * First, encrypt and decrypt this dummy value, * test if the information is recuperated. @@ -622,54 +634,56 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) mpi_free (test); } -/**************** + +/* * To check the validity of the value, recalculate the correspondence * between the public value and the secret one. */ static int check_secret_key (ECC_secret_key * sk) { + int rc = 1; mpi_point_t Q; - gcry_mpi_t y_2, y2 = mpi_alloc (0); - mpi_ec_t ctx; + gcry_mpi_t y_2, y2; + mpi_ec_t ctx = NULL; + + point_init (&Q); /* ?primarity test of 'p' */ /* (...) //!! */ /* G in E(F_p) */ y_2 = gen_y_2 (sk->E.G.x, &sk->E); /* y^2=x^3+a*x+b */ + y2 = mpi_alloc (0); mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p); /* y^2=y*y */ if (mpi_cmp (y_2, y2)) { if (DBG_CIPHER) log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n"); - return (1); + goto leave; } /* G != PaI */ if (!mpi_cmp_ui (sk->E.G.z, 0)) { if (DBG_CIPHER) log_debug ("Bad check: 'G' cannot be Point at Infinity!\n"); - return (1); + goto leave; } - point_init (&Q); ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a); + _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); if (mpi_cmp_ui (Q.z, 0)) { if (DBG_CIPHER) log_debug ("check_secret_key: E is not a curve of order n\n"); - point_free (&Q); - _gcry_mpi_ec_free (ctx); - return 1; + goto leave; } /* pubkey cannot be PaI */ if (!mpi_cmp_ui (sk->Q.z, 0)) { if (DBG_CIPHER) log_debug ("Bad check: Q can not be a Point at Infinity!\n"); - _gcry_mpi_ec_free (ctx); - return (1); + goto leave; } /* pubkey = [d]G over E */ _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx); @@ -678,12 +692,16 @@ check_secret_key (ECC_secret_key * sk) if (DBG_CIPHER) log_debug ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); - _gcry_mpi_ec_free (ctx); - return (1); + goto leave; } + rc = 0; /* Okay. */ + + leave: _gcry_mpi_ec_free (ctx); + mpi_free (y2); + mpi_free (y_2); point_free (&Q); - return 0; + return rc; } @@ -699,6 +717,9 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_point_t I; mpi_ec_t ctx; + if (DBG_CIPHER) + log_mpidump ("ecdsa sign hash ", input ); + k = NULL; dr = mpi_alloc (0); sum = mpi_alloc (0); @@ -721,7 +742,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) has to be recomputed. */ mpi_free (k); k = gen_k (skey->E.n, GCRY_STRONG_RANDOM); - _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); + _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx)) { if (DBG_CIPHER) @@ -737,6 +758,12 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ } + if (DBG_CIPHER) + { + log_mpidump ("ecdsa sign result r ", r); + log_mpidump ("ecdsa sign result s ", s); + } + leave: _gcry_mpi_ec_free (ctx); point_free (&I); @@ -749,6 +776,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) return err; } + /* * Check if R and S verifies INPUT. */ @@ -820,10 +848,10 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) { if (DBG_CIPHER) { - log_mpidump (" x", x); - log_mpidump (" y", y); - log_mpidump (" r", r); - log_mpidump (" s", s); + log_mpidump (" x", x); + log_mpidump (" y", y); + log_mpidump (" r", r); + log_mpidump (" s", s); log_debug ("ecc verify: Not verified\n"); } err = GPG_ERR_BAD_SIGNATURE; @@ -846,7 +874,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) } - + /********************************************* ************** interface ****************** *********************************************/ @@ -879,18 +907,16 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) memmove (ptr+(pbytes-n), ptr, n); memset (ptr, 0, (pbytes-n)); } - + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); if (err) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); gcry_free (buf); - mpi_free (x); - mpi_free (y); - return result; } + /* RESULT must have been initialized and is set on success to the point given by VALUE. */ static gcry_error_t @@ -909,7 +935,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) gcry_free (buf); return err; } - if (n < 1) + if (n < 1) { gcry_free (buf); return GPG_ERR_INV_OBJ; @@ -919,7 +945,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) gcry_free (buf); return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ } - if ( ((n-1)%2) ) + if ( ((n-1)%2) ) { gcry_free (buf); return GPG_ERR_INV_OBJ; @@ -945,7 +971,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) mpi_free (x); mpi_free (y); - + return 0; } @@ -962,10 +988,11 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_mpi_t g_x, g_y, q_x, q_y; char *curve_name = NULL; gcry_sexp_t l1; + int transient_key = 0; + const char *usedcurve = NULL; (void)algo; (void)evalue; - (void)r_extrainfo; if (genparms) { @@ -978,6 +1005,14 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (!curve_name) return GPG_ERR_INV_OBJ; /* No curve name or value too large. */ } + + /* Parse the optional transient-key flag. */ + l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if (l1) + { + transient_key = 1; + gcry_sexp_release (l1); + } } /* NBITS is required if no curve name has been given. */ @@ -988,28 +1023,45 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, g_y = mpi_new (0); q_x = mpi_new (0); q_y = mpi_new (0); - ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y); + ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y, + &usedcurve); gcry_free (curve_name); if (ec) return ec; + if (usedcurve) /* Fixme: No error return checking. */ + gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve); skey[0] = sk.E.p; skey[1] = sk.E.a; skey[2] = sk.E.b; - /* The function ec2os releases g_x and g_y. */ skey[3] = ec2os (g_x, g_y, sk.E.p); skey[4] = sk.E.n; - /* The function ec2os releases g_x and g_y. */ skey[5] = ec2os (q_x, q_y, sk.E.p); skey[6] = sk.d; + mpi_free (g_x); + mpi_free (g_y); + mpi_free (q_x); + mpi_free (q_y); + point_free (&sk.E.G); point_free (&sk.Q); /* Make an empty list of factors. */ *retfactors = gcry_calloc ( 1, sizeof **retfactors ); if (!*retfactors) - return gpg_err_code_from_syserror (); + return gpg_err_code_from_syserror (); /* Fixme: relase mem? */ + + if (DBG_CIPHER) + { + log_mpidump ("ecgen result p", skey[0]); + log_mpidump ("ecgen result a", skey[1]); + log_mpidump ("ecgen result b", skey[2]); + log_mpidump ("ecgen result G", skey[3]); + log_mpidump ("ecgen result n", skey[4]); + log_mpidump ("ecgen result Q", skey[5]); + log_mpidump ("ecgen result d", skey[6]); + } return 0; } @@ -1024,7 +1076,7 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, } -/* Return the parameters of the curve NAME. */ +/* Return the parameters of the curve NAME in an MPI array. */ static gcry_err_code_t ecc_get_param (const char *name, gcry_mpi_t *pkey) { @@ -1033,8 +1085,8 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) elliptic_curve_t E; mpi_ec_t ctx; gcry_mpi_t g_x, g_y; - - err = generate_curve (0, name, &E, &nbits); + + err = fill_in_curve (0, name, &E, &nbits); if (err) return err; @@ -1053,10 +1105,120 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) pkey[4] = E.n; pkey[5] = NULL; + mpi_free (g_x); + mpi_free (g_y); + return 0; } +/* Return the parameters of the curve NAME as an S-expression. */ +static gcry_sexp_t +ecc_get_param_sexp (const char *name) +{ + gcry_mpi_t pkey[6]; + gcry_sexp_t result; + int i; + + if (ecc_get_param (name, pkey)) + return NULL; + + if (gcry_sexp_build (&result, NULL, + "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))", + pkey[0], pkey[1], pkey[2], pkey[3], pkey[4])) + result = NULL; + + for (i=0; pkey[i]; i++) + gcry_mpi_release (pkey[i]); + + return result; +} + + +/* Return the name matching the parameters in PKEY. */ +static const char * +ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits) +{ + gpg_err_code_t err; + elliptic_curve_t E; + int idx; + gcry_mpi_t tmp; + const char *result = NULL; + + if (r_nbits) + *r_nbits = 0; + + if (!pkey) + { + idx = iterator; + if (idx >= 0 && idx < DIM (domain_parms)) + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + } + return result; + } + + if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4]) + return NULL; + + E.p = pkey[0]; + E.a = pkey[1]; + E.b = pkey[2]; + point_init (&E.G); + err = os2ec (&E.G, pkey[3]); + if (err) + { + point_free (&E.G); + return NULL; + } + E.n = pkey[4]; + + for (idx = 0; domain_parms[idx].desc; idx++) + { + tmp = scanval (domain_parms[idx].p); + if (!mpi_cmp (tmp, E.p)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].a); + if (!mpi_cmp (tmp, E.a)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].b); + if (!mpi_cmp (tmp, E.b)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].n); + if (!mpi_cmp (tmp, E.n)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].g_x); + if (!mpi_cmp (tmp, E.G.x)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].g_y); + if (!mpi_cmp (tmp, E.G.y)) + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + break; + } + } + } + } + } + } + mpi_free (tmp); + } + + point_free (&E.G); + + return result; +} + + static gcry_err_code_t ecc_check_secret_key (int algo, gcry_mpi_t *skey) { @@ -1065,8 +1227,9 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) (void)algo; + /* FIXME: This check looks a bit fishy: Now long is the array? */ if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] - || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10]) + || !skey[6]) return GPG_ERR_BAD_MPI; sk.E.p = skey[0]; @@ -1150,6 +1313,7 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) return err; } + static gcry_err_code_t ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, int (*cmp)(void *, gcry_mpi_t), void *opaquev) @@ -1193,6 +1357,221 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, } +/* ecdh raw is classic 2-round DH protocol published in 1976. + * + * Overview of ecc_encrypt_raw and ecc_decrypt_raw. + * + * As with any PK operation, encrypt version uses a public key and + * decrypt -- private. + * + * Symbols used below: + * G - field generator point + * d - private long-term scalar + * dG - public long-term key + * k - ephemeral scalar + * kG - ephemeral public key + * dkG - shared secret + * + * ecc_encrypt_raw description: + * input: + * data[0] : private scalar (k) + * output: + * result[0] : shared point (kdG) + * result[1] : generated ephemeral public key (kG) + * + * ecc_decrypt_raw description: + * input: + * data[0] : a point kG (ephemeral public key) + * output: + * result[0] : shared point (kdG) + */ +static gcry_err_code_t +ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, + gcry_mpi_t *pkey, int flags) +{ + ECC_public_key pk; + mpi_ec_t ctx; + gcry_mpi_t result[2]; + int err; + + (void)algo; + (void)flags; + + if (!k + || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5]) + return GPG_ERR_BAD_MPI; + + pk.E.p = pkey[0]; + pk.E.a = pkey[1]; + pk.E.b = pkey[2]; + point_init (&pk.E.G); + err = os2ec (&pk.E.G, pkey[3]); + if (err) + { + point_free (&pk.E.G); + return err; + } + pk.E.n = pkey[4]; + point_init (&pk.Q); + err = os2ec (&pk.Q, pkey[5]); + if (err) + { + point_free (&pk.E.G); + point_free (&pk.Q); + return err; + } + + ctx = _gcry_mpi_ec_init (pk.E.p, pk.E.a); + + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + { + mpi_point_t R; /* Result that we return. */ + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); + + point_init (&R); + + /* R = kQ <=> R = kdG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kdG\n"); + + result[0] = ec2os (x, y, pk.E.p); + + /* R = kG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); + + result[1] = ec2os (x, y, pk.E.p); + + mpi_free (x); + mpi_free (y); + + point_free (&R); + } + + _gcry_mpi_ec_free (ctx); + point_free (&pk.E.G); + point_free (&pk.Q); + + if (!result[0] || !result[1]) + { + mpi_free (result[0]); + mpi_free (result[1]); + return GPG_ERR_ENOMEM; + } + + /* Success. */ + resarr[0] = result[0]; + resarr[1] = result[1]; + + return 0; +} + +/* input: + * data[0] : a point kG (ephemeral public key) + * output: + * resaddr[0] : shared point kdG + * + * see ecc_encrypt_raw for details. + */ +static gcry_err_code_t +ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) +{ + ECC_secret_key sk; + mpi_point_t R; /* Result that we return. */ + mpi_point_t kG; + mpi_ec_t ctx; + gcry_mpi_t r; + int err; + + (void)algo; + (void)flags; + + *result = NULL; + + if (!data || !data[0] + || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] + || !skey[5] || !skey[6] ) + return GPG_ERR_BAD_MPI; + + point_init (&kG); + err = os2ec (&kG, data[0]); + if (err) + { + point_free (&kG); + return err; + } + + + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; + point_init (&sk.Q); + err = os2ec (&sk.Q, skey[5]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); + return err; + } + sk.d = skey[6]; + + ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + + /* R = dkG */ + point_init (&R); + _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx); + + point_free (&kG); + + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */ + { + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates\n"); + + r = ec2os (x, y, sk.E.p); + mpi_free (x); + mpi_free (y); + } + + point_free (&R); + _gcry_mpi_ec_free (ctx); + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); + + if (!r) + return GPG_ERR_ENOMEM; + + /* Success. */ + + *result = r; + + return 0; +} + static unsigned int ecc_get_nbits (int algo, gcry_mpi_t *pkey) @@ -1203,23 +1582,23 @@ ecc_get_nbits (int algo, gcry_mpi_t *pkey) } - /* See rsa.c for a description of this function. */ static gpg_err_code_t compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) { - static const char names[] = "pabgnq"; +#define N_COMPONENTS 6 + static const char names[N_COMPONENTS+1] = "pabgnq"; gpg_err_code_t ec = 0; gcry_sexp_t l1; - gcry_mpi_t values[6]; + gcry_mpi_t values[N_COMPONENTS]; int idx; /* Clear the values for easier error cleanup. */ - for (idx=0; idx < 6; idx++) + for (idx=0; idx < N_COMPONENTS; idx++) values[idx] = NULL; - - /* Fill values with all available parameters. */ - for (idx=0; idx < 6; idx++) + + /* Fill values with all provided parameters. */ + for (idx=0; idx < N_COMPONENTS; idx++) { l1 = gcry_sexp_find_token (keyparam, names+idx, 1); if (l1) @@ -1233,19 +1612,20 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } } } - + /* Check whether a curve parameter is available and use that to fill in missing values. */ l1 = gcry_sexp_find_token (keyparam, "curve", 5); if (l1) { char *curve; - gcry_mpi_t tmpvalues[6]; - - for (idx = 0; idx < 6; idx++) + gcry_mpi_t tmpvalues[N_COMPONENTS]; + + for (idx = 0; idx < N_COMPONENTS; idx++) tmpvalues[idx] = NULL; curve = _gcry_sexp_nth_string (l1, 1); + gcry_sexp_release (l1); if (!curve) { ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ @@ -1256,7 +1636,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) if (ec) goto leave; - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) { if (!values[idx]) values[idx] = tmpvalues[idx]; @@ -1266,9 +1646,9 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } /* Check that all parameters are known and normalize all MPIs (that - should not be required but we use an internal fucntion later and + should not be required but we use an internal function later and thus we better make 100% sure that they are normalized). */ - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) if (!values[idx]) { ec = GPG_ERR_NO_OBJ; @@ -1276,14 +1656,14 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } else _gcry_mpi_normalize (values[idx]); - + /* Hash them all. */ - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) { char buf[30]; unsigned char *rawmpi; unsigned int rawmpilen; - + rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL); if (!rawmpi) { @@ -1298,17 +1678,18 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } leave: - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) _gcry_mpi_release (values[idx]); - + return ec; +#undef N_COMPONENTS } -/* +/* Self-test section. */ @@ -1318,7 +1699,7 @@ selftests_ecdsa (selftest_report_func_t report) { const char *what; const char *errtxt; - + what = "low-level"; errtxt = NULL; /*selftest ();*/ if (errtxt) @@ -1351,7 +1732,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1365,6 +1746,12 @@ static const char *ecdsa_names[] = "ecc", NULL, }; +static const char *ecdh_names[] = + { + "ecdh", + "ecc", + NULL, + }; gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = { @@ -1380,11 +1767,27 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = ecc_get_nbits }; -pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = +gcry_pk_spec_t _gcry_pubkey_spec_ecdh = + { + "ECDH", ecdh_names, + "pabgnq", "pabgnqd", "se", "", "pabgnq", + GCRY_PK_USAGE_ENCR, + ecc_generate, + ecc_check_secret_key, + ecc_encrypt_raw, + ecc_decrypt_raw, + NULL, + NULL, + ecc_get_nbits + }; + + +pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = { run_selftests, ecc_generate_ext, compute_keygrip, - ecc_get_param + ecc_get_param, + ecc_get_curve, + ecc_get_param_sexp }; - diff --git a/grub-core/lib/libgcrypt/cipher/elgamal.c b/grub-core/lib/libgcrypt/cipher/elgamal.c index 0b0c07cb4..ce4be8524 100644 --- a/grub-core/lib/libgcrypt/cipher/elgamal.c +++ b/grub-core/lib/libgcrypt/cipher/elgamal.c @@ -115,7 +115,7 @@ wiener_map( unsigned int n ) }; int i; - for(i=0; t[i].p_n; i++ ) + for(i=0; t[i].p_n; i++ ) { if( n <= t[i].p_n ) return t[i].q_n; @@ -158,7 +158,7 @@ test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie ) log_fatal ("Elgamal test key for %s %s failed\n", (failed & 1)? "encrypt+decrypt":"", (failed & 2)? "sign+verify":""); - if (failed && DBG_CIPHER) + if (failed && DBG_CIPHER) log_debug ("Elgamal test key for %s %s failed\n", (failed & 1)? "encrypt+decrypt":"", (failed & 2)? "sign+verify":""); @@ -199,15 +199,15 @@ gen_k( gcry_mpi_t p, int small_k ) if( DBG_CIPHER ) log_debug("choosing a random k "); mpi_sub_ui( p_1, p, 1); - for(;;) + for(;;) { - if( !rndbuf || nbits < 32 ) + if( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); } else - { + { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call to get_random_bytes() and use this the here maybe it is @@ -218,7 +218,7 @@ gen_k( gcry_mpi_t p, int small_k ) gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); - + for(;;) { if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ @@ -294,7 +294,7 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) if( DBG_CIPHER ) log_debug("choosing a random x of size %u", xbits ); rndbuf = NULL; - do + do { if( DBG_CIPHER ) progress('.'); @@ -314,21 +314,21 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) gcry_free(r); } } - else + else { rndbuf = gcry_random_bytes_secure( (xbits+7)/8, GCRY_VERY_STRONG_RANDOM ); } _gcry_mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); mpi_clear_highbit( x, xbits+1 ); - } + } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); gcry_free(rndbuf); y = gcry_mpi_new (nbits); gcry_mpi_powm( y, g, x, p ); - if( DBG_CIPHER ) + if( DBG_CIPHER ) { progress('\n'); log_mpidump("elg p= ", p ); @@ -354,7 +354,7 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) value for the secret key but the one given as X. This is useful to implement a passphrase based decryption for a public key based encryption. It has appliactions in backup systems. - + Returns: A structure filled with all needed values and an array with n-1 factors of (p-1). */ static gcry_err_code_t @@ -399,7 +399,7 @@ generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x, y = gcry_mpi_new (nbits); gcry_mpi_powm ( y, g, x, p ); - if ( DBG_CIPHER ) + if ( DBG_CIPHER ) { progress ('\n'); log_mpidump ("elg p= ", p ); @@ -493,7 +493,7 @@ decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey ) mpi_invm( t1, t1, skey->p ); mpi_mulm( output, b, t1, skey->p ); #if 0 - if( DBG_CIPHER ) + if( DBG_CIPHER ) { log_mpidump("elg decrypted x= ", skey->x); log_mpidump("elg decrypted p= ", skey->p); @@ -533,7 +533,7 @@ sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey ) mpi_mulm(b, t, inv, p_1 ); #if 0 - if( DBG_CIPHER ) + if( DBG_CIPHER ) { log_mpidump("elg sign p= ", skey->p); log_mpidump("elg sign g= ", skey->g); @@ -652,7 +652,7 @@ elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue, skey[1] = sk.g; skey[2] = sk.y; skey[3] = sk.x; - + return ec; } @@ -671,7 +671,7 @@ elg_generate (int algo, unsigned int nbits, unsigned long evalue, skey[1] = sk.g; skey[2] = sk.y; skey[3] = sk.x; - + return GPG_ERR_NO_ERROR; } @@ -692,7 +692,7 @@ elg_check_secret_key (int algo, gcry_mpi_t *skey) sk.g = skey[1]; sk.y = skey[2]; sk.x = skey[3]; - + if (! check_secret_key (&sk)) err = GPG_ERR_BAD_SECKEY; } @@ -773,7 +773,7 @@ elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p)); sign (resarr[0], resarr[1], data, &sk); } - + return err; } @@ -837,10 +837,9 @@ gcry_pk_spec_t _gcry_pubkey_spec_elg = elg_get_nbits }; -pk_extra_spec_t _gcry_pubkey_extraspec_elg = +pk_extra_spec_t _gcry_pubkey_extraspec_elg = { NULL, elg_generate_ext, NULL }; - diff --git a/grub-core/lib/libgcrypt/cipher/hash-common.c b/grub-core/lib/libgcrypt/cipher/hash-common.c index 656e180e2..8c413bcba 100644 --- a/grub-core/lib/libgcrypt/cipher/hash-common.c +++ b/grub-core/lib/libgcrypt/cipher/hash-common.c @@ -21,7 +21,7 @@ #include #include #include -#ifdef HAVE_STDINT_H +#ifdef HAVE_STDINT_H # include #endif @@ -35,10 +35,10 @@ describing the error. DATAMODE controls what will be hashed according to this table: - + 0 - Hash the supplied DATA of DATALEN. 1 - Hash one million times a 'a'. DATA and DATALEN are ignored. - + */ const char * _gcry_hash_selftest_check_one (int algo, @@ -49,14 +49,14 @@ _gcry_hash_selftest_check_one (int algo, gcry_error_t err = 0; gcry_md_hd_t hd; unsigned char *digest; - + if (_gcry_md_get_algo_dlen (algo) != expectlen) return "digest size does not match expected size"; - + err = _gcry_md_open (&hd, algo, 0); if (err) return "gcry_md_open failed"; - + switch (datamode) { case 0: @@ -64,7 +64,7 @@ _gcry_hash_selftest_check_one (int algo, break; case 1: /* Hash one million times an "a". */ - { + { char aaa[1000]; int i; @@ -82,7 +82,7 @@ _gcry_hash_selftest_check_one (int algo, if (!result) { digest = _gcry_md_read (hd, algo); - + if ( memcmp (digest, expect, expectlen) ) result = "digest mismatch"; } @@ -91,4 +91,3 @@ _gcry_hash_selftest_check_one (int algo, return result; } - diff --git a/grub-core/lib/libgcrypt/cipher/hash-common.h b/grub-core/lib/libgcrypt/cipher/hash-common.h index 9c4e33359..fdebef42a 100644 --- a/grub-core/lib/libgcrypt/cipher/hash-common.h +++ b/grub-core/lib/libgcrypt/cipher/hash-common.h @@ -21,11 +21,11 @@ #define GCRY_HASH_COMMON_H -const char * _gcry_hash_selftest_check_one -/**/ (int algo, +const char * _gcry_hash_selftest_check_one +/**/ (int algo, int datamode, const void *data, size_t datalen, const void *expect, size_t expectlen); - + diff --git a/grub-core/lib/libgcrypt/cipher/hmac-tests.c b/grub-core/lib/libgcrypt/cipher/hmac-tests.c index 56c9b203c..a32ece75d 100644 --- a/grub-core/lib/libgcrypt/cipher/hmac-tests.c +++ b/grub-core/lib/libgcrypt/cipher/hmac-tests.c @@ -17,7 +17,7 @@ * License along with this program; if not, see . */ -/* +/* Although algorithm self-tests are usually implemented in the module implementing the algorithm, the case for HMAC is different because HMAC is implemnetd on a higher level using a special feature of the @@ -33,7 +33,7 @@ #include #include #include -#ifdef HAVE_STDINT_H +#ifdef HAVE_STDINT_H # include #endif @@ -47,7 +47,7 @@ succdess or a string describing the failure. */ static const char * check_one (int algo, - const void *data, size_t datalen, + const void *data, size_t datalen, const void *key, size_t keylen, const void *expect, size_t expectlen) { @@ -88,7 +88,7 @@ check_one (int algo, return "does not match"; } _gcry_md_close (hd); - return NULL; + return NULL; } @@ -123,7 +123,7 @@ selftests_sha1 (int extended, selftest_report_func_t report) "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20); if (errtxt) goto failed; - + what = "FIPS-198a, A.3"; for (i=0, j=0x50; i < 100; i++) key[i] = j++; @@ -134,7 +134,7 @@ selftests_sha1 (int extended, selftest_report_func_t report) "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20 ); if (errtxt) goto failed; - + what = "FIPS-198a, A.4"; for (i=0, j=0x70; i < 49; i++) key[i] = j++; @@ -160,7 +160,7 @@ selftests_sha1 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha224 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -169,7 +169,7 @@ selftests_sha224 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, @@ -248,7 +248,7 @@ selftests_sha224 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; @@ -274,7 +274,7 @@ selftests_sha224 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha256 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -283,7 +283,7 @@ selftests_sha256 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, @@ -362,7 +362,7 @@ selftests_sha256 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { hmac256_context_t hmachd; @@ -416,7 +416,7 @@ selftests_sha256 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha384 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -425,7 +425,7 @@ selftests_sha384 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, @@ -516,7 +516,7 @@ selftests_sha384 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; @@ -542,7 +542,7 @@ selftests_sha384 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha512 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -551,7 +551,7 @@ selftests_sha512 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, @@ -654,7 +654,7 @@ selftests_sha512 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; diff --git a/grub-core/lib/libgcrypt/cipher/idea.c b/grub-core/lib/libgcrypt/cipher/idea.c new file mode 100644 index 000000000..3c5578f95 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/idea.c @@ -0,0 +1,378 @@ +/* idea.c - IDEA function + * Copyright 1997, 1998, 1999, 2001 Werner Koch (dd9jn) + * Copyright 2013 g10 Code GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Werner Koch shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Werner Koch. + * + * Patents on IDEA have expired: + * Europe: EP0482154 on 2011-05-16, + * Japan: JP3225440 on 2011-05-16, + * U.S.: 5,214,703 on 2012-01-07. + */ + +/* + * Please see http://www.noepatents.org/ to learn why software patents + * are bad for society and what you can do to fight them. + * + * The code herein is based on the one from: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. + */ + + +#include +#include +#include +#include +#include + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + + +#define IDEA_KEYSIZE 16 +#define IDEA_BLOCKSIZE 8 +#define IDEA_ROUNDS 8 +#define IDEA_KEYLEN (6*IDEA_ROUNDS+4) + +typedef struct { + u16 ek[IDEA_KEYLEN]; + u16 dk[IDEA_KEYLEN]; + int have_dk; +} IDEA_context; + +static const char *selftest(void); + + +static u16 +mul_inv( u16 x ) +{ + u16 t0, t1; + u16 q, y; + + if( x < 2 ) + return x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; + if( y == 1 ) + return (1-t1) & 0xffff; + + t0 = 1; + do { + q = x / y; + x = x % y; + t0 += q * t1; + if( x == 1 ) + return t0; + q = y / x; + y = y % x; + t1 += q * t0; + } while( y != 1 ); + return (1-t1) & 0xffff; +} + + + +static void +expand_key( const byte *userkey, u16 *ek ) +{ + int i,j; + + for(j=0; j < 8; j++ ) { + ek[j] = (*userkey << 8) + userkey[1]; + userkey += 2; + } + for(i=0; j < IDEA_KEYLEN; j++ ) { + i++; + ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; + ek += i & 8; + i &= 7; + } +} + + +static void +invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) +{ + int i; + u16 t1, t2, t3; + u16 temp[IDEA_KEYLEN]; + u16 *p = temp + IDEA_KEYLEN; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + + for(i=0; i < IDEA_ROUNDS-1; i++ ) { + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t2; + *--p = t3; + *--p = t1; + } + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + memcpy(dk, temp, sizeof(temp) ); + memset(temp, 0, sizeof(temp) ); /* burn temp */ +} + + +static void +cipher( byte *outbuf, const byte *inbuf, u16 *key ) +{ + u16 s2, s3; + u16 in[4]; + int r = IDEA_ROUNDS; +#define x1 (in[0]) +#define x2 (in[1]) +#define x3 (in[2]) +#define x4 (in[3]) +#define MUL(x,y) \ + do {u16 _t16; u32 _t32; \ + if( (_t16 = (y)) ) { \ + if( (x = (x)&0xffff) ) { \ + _t32 = (u32)x * _t16; \ + x = _t32 & 0xffff; \ + _t16 = _t32 >> 16; \ + x = ((x)-_t16) + (x<_t16?1:0); \ + } \ + else { \ + x = 1 - _t16; \ + } \ + } \ + else { \ + x = 1 - x; \ + } \ + } while(0) + + memcpy (in, inbuf, sizeof in); +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + do { + MUL(x1, *key++); + x2 += *key++; + x3 += *key++; + MUL(x4, *key++ ); + + s3 = x3; + x3 ^= x1; + MUL(x3, *key++); + s2 = x2; + x2 ^=x4; + x2 += x3; + MUL(x2, *key++); + x3 += x2; + + x1 ^= x2; + x4 ^= x3; + + x2 ^= s3; + x3 ^= s2; + } while( --r ); + MUL(x1, *key++); + x3 += *key++; + x2 += *key++; + MUL(x4, *key); + +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + memcpy (outbuf+0, &x1, 2); + memcpy (outbuf+2, &x3, 2); + memcpy (outbuf+4, &x2, 2); + memcpy (outbuf+6, &x4, 2); +#undef MUL +#undef x1 +#undef x2 +#undef x3 +#undef x4 +} + + +static int +do_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) +{ + static int initialized = 0; + static const char *selftest_failed = 0; + + if( !initialized ) { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error( "%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + assert(keylen == 16); + c->have_dk = 0; + expand_key( key, c->ek ); + invert_key( c->ek, c->dk ); + return 0; +} + +static gcry_err_code_t +idea_setkey (void *context, const byte *key, unsigned int keylen) +{ + IDEA_context *ctx = context; + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + +static void +encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + cipher( outbuf, inbuf, c->ek ); +} + +static void +idea_encrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + encrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + +static void +decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + if( !c->have_dk ) { + c->have_dk = 1; + invert_key( c->ek, c->dk ); + } + cipher( outbuf, inbuf, c->dk ); +} + +static void +idea_decrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + decrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +static const char * +selftest( void ) +{ +static struct { + byte key[16]; + byte plain[8]; + byte cipher[8]; +} test_vectors[] = { + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }, + { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF }, + { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 }, + { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E }, + { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 }, + { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 }, + { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } }, + { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, + 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } }, + { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3, + 0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } }, + { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90, + 0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 }, + { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA }, + { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } }, + { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A, + 0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 }, + { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, + { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } } +}; + IDEA_context c; + byte buffer[8]; + int i; + + for(i=0; i < DIM(test_vectors); i++ ) { + do_setkey( &c, test_vectors[i].key, 16 ); + encrypt_block( &c, buffer, test_vectors[i].plain ); + if( memcmp( buffer, test_vectors[i].cipher, 8 ) ) + return "IDEA test encryption failed."; + decrypt_block( &c, buffer, test_vectors[i].cipher ); + if( memcmp( buffer, test_vectors[i].plain, 8 ) ) + return "IDEA test decryption failed."; + } + + return NULL; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_idea = +{ + "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, + sizeof (IDEA_context), + idea_setkey, idea_encrypt, idea_decrypt +}; diff --git a/grub-core/lib/libgcrypt/cipher/kdf.c b/grub-core/lib/libgcrypt/cipher/kdf.c new file mode 100644 index 000000000..46e8550df --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/kdf.c @@ -0,0 +1,278 @@ +/* kdf.c - Key Derivation Functions + * Copyright (C) 1998, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "ath.h" + + +/* Transform a passphrase into a suitable key of length KEYSIZE and + store this key in the caller provided buffer KEYBUFFER. The caller + must provide an HASHALGO, a valid ALGO and depending on that algo a + SALT of 8 bytes and the number of ITERATIONS. Code taken from + gnupg/agent/protect.c:hash_passphrase. */ +gpg_err_code_t +openpgp_s2k (const void *passphrase, size_t passphraselen, + int algo, int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + gcry_md_hd_t md; + char *key = keybuffer; + int pass, i; + int used = 0; + int secmode; + + if ((algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K) + && (!salt || saltlen != 8)) + return GPG_ERR_INV_VALUE; + + secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer); + + ec = gpg_err_code (gcry_md_open (&md, hashalgo, + secmode? GCRY_MD_FLAG_SECURE : 0)); + if (ec) + return ec; + + for (pass=0; used < keysize; pass++) + { + if (pass) + { + gcry_md_reset (md); + for (i=0; i < pass; i++) /* Preset the hash context. */ + gcry_md_putc (md, 0); + } + + if (algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K) + { + int len2 = passphraselen + 8; + unsigned long count = len2; + + if (algo == GCRY_KDF_ITERSALTED_S2K) + { + count = iterations; + if (count < len2) + count = len2; + } + + while (count > len2) + { + gcry_md_write (md, salt, saltlen); + gcry_md_write (md, passphrase, passphraselen); + count -= len2; + } + if (count < saltlen) + gcry_md_write (md, salt, count); + else + { + gcry_md_write (md, salt, saltlen); + count -= saltlen; + gcry_md_write (md, passphrase, count); + } + } + else + gcry_md_write (md, passphrase, passphraselen); + + gcry_md_final (md); + i = gcry_md_get_algo_dlen (hashalgo); + if (i > keysize - used) + i = keysize - used; + memcpy (key+used, gcry_md_read (md, hashalgo), i); + used += i; + } + gcry_md_close (md); + return 0; +} + + +/* Transform a passphrase into a suitable key of length KEYSIZE and + store this key in the caller provided buffer KEYBUFFER. The caller + must provide PRFALGO which indicates the pseudorandom function to + use: This shall be the algorithms id of a hash algorithm; it is + used in HMAC mode. SALT is a salt of length SALTLEN and ITERATIONS + gives the number of iterations. */ +gpg_err_code_t +pkdf2 (const void *passphrase, size_t passphraselen, + int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + gcry_md_hd_t md; + int secmode; + unsigned int dklen = keysize; + char *dk = keybuffer; + unsigned int hlen; /* Output length of the digest function. */ + unsigned int l; /* Rounded up number of blocks. */ + unsigned int r; /* Number of octets in the last block. */ + char *sbuf; /* Malloced buffer to concatenate salt and iter + as well as space to hold TBUF and UBUF. */ + char *tbuf; /* Buffer for T; ptr into SBUF, size is HLEN. */ + char *ubuf; /* Buffer for U; ptr into SBUF, size is HLEN. */ + unsigned int lidx; /* Current block number. */ + unsigned long iter; /* Current iteration number. */ + unsigned int i; + + if (!salt || !saltlen || !iterations || !dklen) + return GPG_ERR_INV_VALUE; + + hlen = gcry_md_get_algo_dlen (hashalgo); + if (!hlen) + return GPG_ERR_DIGEST_ALGO; + + secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer); + + /* We ignore step 1 from pksc5v2.1 which demands a check that dklen + is not larger that 0xffffffff * hlen. */ + + /* Step 2 */ + l = ((dklen - 1)/ hlen) + 1; + r = dklen - (l - 1) * hlen; + + /* Setup buffers and prepare a hash context. */ + sbuf = (secmode + ? gcry_malloc_secure (saltlen + 4 + hlen + hlen) + : gcry_malloc (saltlen + 4 + hlen + hlen)); + if (!sbuf) + return gpg_err_code_from_syserror (); + tbuf = sbuf + saltlen + 4; + ubuf = tbuf + hlen; + + ec = gpg_err_code (gcry_md_open (&md, hashalgo, + (GCRY_MD_FLAG_HMAC + | (secmode?GCRY_MD_FLAG_SECURE:0)))); + if (ec) + { + gcry_free (sbuf); + return ec; + } + + /* Step 3 and 4. */ + memcpy (sbuf, salt, saltlen); + for (lidx = 1; lidx <= l; lidx++) + { + for (iter = 0; iter < iterations; iter++) + { + ec = gpg_err_code (gcry_md_setkey (md, passphrase, passphraselen)); + if (ec) + { + gcry_md_close (md); + gcry_free (sbuf); + return ec; + } + if (!iter) /* Compute U_1: */ + { + sbuf[saltlen] = (lidx >> 24); + sbuf[saltlen + 1] = (lidx >> 16); + sbuf[saltlen + 2] = (lidx >> 8); + sbuf[saltlen + 3] = lidx; + gcry_md_write (md, sbuf, saltlen + 4); + memcpy (ubuf, gcry_md_read (md, 0), hlen); + memcpy (tbuf, ubuf, hlen); + } + else /* Compute U_(2..c): */ + { + gcry_md_write (md, ubuf, hlen); + memcpy (ubuf, gcry_md_read (md, 0), hlen); + for (i=0; i < hlen; i++) + tbuf[i] ^= ubuf[i]; + } + } + if (lidx == l) /* Last block. */ + memcpy (dk, tbuf, r); + else + { + memcpy (dk, tbuf, hlen); + dk += hlen; + } + } + + gcry_md_close (md); + gcry_free (sbuf); + return 0; +} + + +/* Derive a key from a passphrase. KEYSIZE gives the requested size + of the keys in octets. KEYBUFFER is a caller provided buffer + filled on success with the derived key. The input passphrase is + taken from (PASSPHRASE,PASSPHRASELEN) which is an arbitrary memory + buffer. ALGO specifies the KDF algorithm to use; these are the + constants GCRY_KDF_*. SUBALGO specifies an algorithm used + internally by the KDF algorithms; this is usually a hash algorithm + but certain KDF algorithm may use it differently. {SALT,SALTLEN} + is a salt as needed by most KDF algorithms. ITERATIONS is a + positive integer parameter to most KDFs. 0 is returned on success, + or an error code on failure. */ +gpg_error_t +gcry_kdf_derive (const void *passphrase, size_t passphraselen, + int algo, int subalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + + if (!passphrase || (!passphraselen && algo != GCRY_KDF_PBKDF2)) + { + ec = GPG_ERR_INV_DATA; + goto leave; + } + if (!keybuffer || !keysize) + { + ec = GPG_ERR_INV_VALUE; + goto leave; + } + + + switch (algo) + { + case GCRY_KDF_SIMPLE_S2K: + case GCRY_KDF_SALTED_S2K: + case GCRY_KDF_ITERSALTED_S2K: + ec = openpgp_s2k (passphrase, passphraselen, algo, subalgo, + salt, saltlen, iterations, keysize, keybuffer); + break; + + case GCRY_KDF_PBKDF1: + ec = GPG_ERR_UNSUPPORTED_ALGORITHM; + break; + + case GCRY_KDF_PBKDF2: + ec = pkdf2 (passphrase, passphraselen, subalgo, + salt, saltlen, iterations, keysize, keybuffer); + break; + + default: + ec = GPG_ERR_UNKNOWN_ALGORITHM; + break; + } + + leave: + return gpg_error (ec); +} diff --git a/grub-core/lib/libgcrypt/cipher/md.c b/grub-core/lib/libgcrypt/cipher/md.c index 5dfbbd95a..c3b3a4f3a 100644 --- a/grub-core/lib/libgcrypt/cipher/md.c +++ b/grub-core/lib/libgcrypt/cipher/md.c @@ -43,15 +43,15 @@ static struct digest_table_entry gcry_md_spec_t *digest; md_extra_spec_t *extraspec; unsigned int algorithm; - int fips_allowed; + int fips_allowed; } digest_table[] = { -#if USE_CRC +#if USE_CRC /* We allow the CRC algorithms even in FIPS mode because they are actually no cryptographic primitives. */ - { &_gcry_digest_spec_crc32, + { &_gcry_digest_spec_crc32, &dummy_extra_spec, GCRY_MD_CRC32, 1 }, - { &_gcry_digest_spec_crc32_rfc1510, + { &_gcry_digest_spec_crc32_rfc1510, &dummy_extra_spec, GCRY_MD_CRC32_RFC1510, 1 }, { &_gcry_digest_spec_crc24_rfc2440, &dummy_extra_spec, GCRY_MD_CRC24_RFC2440, 1 }, @@ -69,7 +69,7 @@ static struct digest_table_entry &dummy_extra_spec, GCRY_MD_RMD160 }, #endif #if USE_SHA1 - { &_gcry_digest_spec_sha1, + { &_gcry_digest_spec_sha1, &_gcry_digest_extraspec_sha1, GCRY_MD_SHA1, 1 }, #endif #if USE_SHA256 @@ -87,6 +87,10 @@ static struct digest_table_entry #if USE_TIGER { &_gcry_digest_spec_tiger, &dummy_extra_spec, GCRY_MD_TIGER }, + { &_gcry_digest_spec_tiger1, + &dummy_extra_spec, GCRY_MD_TIGER1 }, + { &_gcry_digest_spec_tiger2, + &dummy_extra_spec, GCRY_MD_TIGER2 }, #endif #if USE_WHIRLPOOL { &_gcry_digest_spec_whirlpool, @@ -101,7 +105,7 @@ static gcry_module_t digests_registered; /* This is the lock protecting DIGESTS_REGISTERED. */ static ath_mutex_t digests_registered_lock = ATH_MUTEX_INITIALIZER; -/* Flag to check wether the default ciphers have already been +/* Flag to check whether the default ciphers have already been registered. */ static int default_digests_registered; @@ -173,7 +177,7 @@ md_register_default (void) { gcry_err_code_t err = 0; int i; - + for (i = 0; !err && digest_table[i].digest; i++) { if ( fips_mode ()) @@ -226,7 +230,7 @@ gcry_md_lookup_func_oid (void *spec, void *data) } /* Internal function. Lookup a digest entry by it's name. */ -static gcry_module_t +static gcry_module_t gcry_md_lookup_name (const char *name) { gcry_module_t digest; @@ -267,11 +271,11 @@ _gcry_md_register (gcry_md_spec_t *digest, ath_mutex_lock (&digests_registered_lock); err = _gcry_module_add (&digests_registered, 0, - (void *) digest, - (void *)(extraspec? extraspec : &dummy_extra_spec), + (void *) digest, + (void *)(extraspec? extraspec : &dummy_extra_spec), &mod); ath_mutex_unlock (&digests_registered_lock); - + if (! err) { *module = mod; @@ -292,7 +296,7 @@ gcry_md_unregister (gcry_module_t module) } -static int +static int search_oid (const char *oid, int *algorithm, gcry_md_oid_spec_t *oid_spec) { gcry_module_t module; @@ -563,7 +567,7 @@ md_enable (gcry_md_hd_t hd, int algorithm) else digest = (gcry_md_spec_t *) module->spec; - + if (!err && algorithm == GCRY_MD_MD5 && fips_mode ()) { _gcry_inactivate_fips_mode ("MD5 used"); @@ -574,7 +578,7 @@ md_enable (gcry_md_hd_t hd, int algorithm) err = GPG_ERR_DIGEST_ALGO; } } - + if (!err) { size_t size = (sizeof (*entry) @@ -631,7 +635,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) GcryDigestEntry *ar, *br; gcry_md_hd_t bhd; size_t n; - + if (ahd->bufpos) md_write (ahd, NULL, 0); @@ -693,7 +697,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) - sizeof (ar->context))); br->next = b->list; b->list = br; - + /* Add a reference to the module. */ ath_mutex_lock (&digests_registered_lock); _gcry_module_use (br->module); @@ -783,7 +787,7 @@ static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen) { GcryDigestEntry *r; - + if (a->ctx->debug) { if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1) @@ -834,8 +838,8 @@ md_final (gcry_md_hd_t a) if (err) _gcry_fatal_error (err, NULL); - md_write (om, - (a->ctx->macpads)+(a->ctx->macpads_Bsize), + md_write (om, + (a->ctx->macpads)+(a->ctx->macpads_Bsize), a->ctx->macpads_Bsize); md_write (om, p, dlen); md_final (om); @@ -856,7 +860,7 @@ prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen) if (!algo) return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */ - if ( keylen > hd->ctx->macpads_Bsize ) + if ( keylen > hd->ctx->macpads_Bsize ) { helpkey = gcry_malloc_secure (md_digest_length (algo)); if (!helpkey) @@ -872,7 +876,7 @@ prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen) opad = (hd->ctx->macpads)+(hd->ctx->macpads_Bsize); memcpy ( ipad, key, keylen ); memcpy ( opad, key, keylen ); - for (i=0; i < hd->ctx->macpads_Bsize; i++ ) + for (i=0; i < hd->ctx->macpads_Bsize; i++ ) { ipad[i] ^= 0x36; opad[i] ^= 0x5c; @@ -886,7 +890,7 @@ gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc = 0; - + switch (cmd) { case GCRYCTL_FINALIZE: @@ -948,10 +952,13 @@ md_read( gcry_md_hd_t a, int algo ) if (! algo) { - /* return the first algorithm */ - if (r && r->next) - log_debug ("more than one algorithm in md_read(0)\n"); - return r->digest->read( &r->context.c ); + /* Return the first algorithm */ + if (r) + { + if (r->next) + log_debug ("more than one algorithm in md_read(0)\n"); + return r->digest->read (&r->context.c); + } } else { @@ -1135,7 +1142,7 @@ md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) * Note: Because this function is in most cases used to return an * integer value, we can make it easier for the caller to just look at * the return value. The caller will in all cases consult the value - * and thereby detecting whether a error occured or not (i.e. while checking + * and thereby detecting whether a error occurred or not (i.e. while checking * the block size) */ gcry_error_t @@ -1160,7 +1167,7 @@ gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) { const char unsigned *asn; size_t asnlen; - + asn = md_asn_oid (algo, &asnlen, NULL); if (buffer && (*nbytes >= asnlen)) { @@ -1195,7 +1202,7 @@ md_start_debug ( gcry_md_hd_t md, const char *suffix ) if (fips_mode ()) return; - + if ( md->ctx->debug ) { log_debug("Oops: md debug already started\n"); @@ -1225,6 +1232,7 @@ md_stop_debug( gcry_md_hd_t md ) volatile u64 b = 42; volatile u64 c; c = a * b; + (void)c; } #endif } @@ -1261,7 +1269,7 @@ gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes) else { algo = *(int*)buffer; - + *nbytes = 0; for(r=h->ctx->list; r; r = r->next ) { if (r->module->mod_id == algo) @@ -1295,7 +1303,7 @@ _gcry_md_init (void) int -gcry_md_is_secure (gcry_md_hd_t a) +gcry_md_is_secure (gcry_md_hd_t a) { size_t value; @@ -1307,7 +1315,7 @@ gcry_md_is_secure (gcry_md_hd_t a) int -gcry_md_is_enabled (gcry_md_hd_t a, int algo) +gcry_md_is_enabled (gcry_md_hd_t a, int algo) { size_t value; @@ -1359,7 +1367,7 @@ _gcry_md_selftest (int algo, int extended, selftest_report_func_t report) { ec = GPG_ERR_DIGEST_ALGO; if (report) - report ("digest", algo, "module", + report ("digest", algo, "module", module && !(module->flags & FLAG_MODULE_DISABLED)? "no selftest available" : module? "algorithm disabled" : "algorithm not found"); diff --git a/grub-core/lib/libgcrypt/cipher/md4.c b/grub-core/lib/libgcrypt/cipher/md4.c index aa180f0d4..22fbf8d90 100644 --- a/grub-core/lib/libgcrypt/cipher/md4.c +++ b/grub-core/lib/libgcrypt/cipher/md4.c @@ -53,7 +53,6 @@ #include #include "g10lib.h" -#include "memory.h" #include "cipher.h" #include "bithelp.h" @@ -199,7 +198,7 @@ md4_write ( void *context, const void *inbuf_arg, size_t inlen) MD4_CONTEXT *hd = context; if( hd->count == 64 ) /* flush the buffer */ - { + { transform( hd, hd->buf ); _gcry_burn_stack (80+6*sizeof(void*)); hd->count = 0; @@ -260,15 +259,15 @@ md4_final( void *context ) lsb <<= 3; msb <<= 3; msb |= t >> 29; - + if( hd->count < 56 ) /* enough room */ { hd->buf[hd->count++] = 0x80; /* pad */ while( hd->count < 56 ) hd->buf[hd->count++] = 0; /* pad */ } - else /* need one extra block */ - { + else /* need one extra block */ + { hd->buf[hd->count++] = 0x80; /* pad character */ while( hd->count < 64 ) hd->buf[hd->count++] = 0; @@ -326,4 +325,3 @@ gcry_md_spec_t _gcry_digest_spec_md4 = md4_init, md4_write, md4_final, md4_read, sizeof (MD4_CONTEXT) }; - diff --git a/grub-core/lib/libgcrypt/cipher/md5.c b/grub-core/lib/libgcrypt/cipher/md5.c index 3d3046df2..a98678a9b 100644 --- a/grub-core/lib/libgcrypt/cipher/md5.c +++ b/grub-core/lib/libgcrypt/cipher/md5.c @@ -20,8 +20,8 @@ * * According to the definition of MD5 in RFC 1321 from April 1992. * NOTE: This is *not* the same file as the one from glibc. - * Written by Ulrich Drepper , 1995. - * heavily modified for GnuPG by Werner Koch + * Written by Ulrich Drepper , 1995. + * heavily modified for GnuPG by Werner Koch */ /* Test values: @@ -37,7 +37,6 @@ #include #include "g10lib.h" -#include "memory.h" #include "cipher.h" #include "bithelp.h" @@ -88,9 +87,9 @@ transform ( MD5_CONTEXT *ctx, const unsigned char *data ) register u32 C = ctx->C; register u32 D = ctx->D; u32 *cwp = correct_words; - + #ifdef WORDS_BIGENDIAN - { + { int i; byte *p2; const byte *p1; @@ -222,7 +221,7 @@ md5_write( void *context, const void *inbuf_arg , size_t inlen) { const unsigned char *inbuf = inbuf_arg; MD5_CONTEXT *hd = context; - + if( hd->count == 64 ) /* flush the buffer */ { transform( hd, hd->buf ); @@ -243,7 +242,7 @@ md5_write( void *context, const void *inbuf_arg , size_t inlen) } _gcry_burn_stack (80+6*sizeof(void*)); - while( inlen >= 64 ) + while( inlen >= 64 ) { transform( hd, inbuf ); hd->count = 0; @@ -270,7 +269,7 @@ md5_final( void *context) MD5_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; - + md5_write(hd, NULL, 0); /* flush */; t = hd->nblocks; diff --git a/grub-core/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c index b869bee83..2788e349f 100644 --- a/grub-core/lib/libgcrypt/cipher/primegen.c +++ b/grub-core/lib/libgcrypt/cipher/primegen.c @@ -31,7 +31,7 @@ #include "cipher.h" #include "ath.h" -static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel, +static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel, int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg); static int check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds, @@ -132,7 +132,7 @@ static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1; /* An object and a list to build up a global pool of primes. See save_pool_prime and get_pool_prime. */ -struct primepool_s +struct primepool_s { struct primepool_s *next; gcry_mpi_t prime; /* If this is NULL the entry is not used. */ @@ -163,7 +163,7 @@ save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel) /* Remove some of the entries. Our strategy is removing the last third from the list. */ int i; - + for (i=0, item2 = primepool; item2; item2 = item2->next) { if (i >= n/3*2) @@ -182,7 +182,7 @@ save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel) { /* Out of memory. Silently giving up. */ gcry_mpi_release (prime); - return; + return; } item->next = primepool; primepool = item; @@ -359,7 +359,7 @@ prime_generate_internal (int need_q_factor, fbits = (pbits - req_qbits -1) / n; qbits = pbits - n * fbits; } - + if (DBG_CIPHER) log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n); @@ -373,7 +373,7 @@ prime_generate_internal (int need_q_factor, /* Generate a specific Q-Factor if requested. */ if (need_q_factor) q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL); - + /* Allocate an array to hold all factors + 2 for later usage. */ factors = gcry_calloc (n + 2, sizeof (*factors)); if (!factors) @@ -391,10 +391,10 @@ prime_generate_internal (int need_q_factor, } for (i=0; i < n; i++) pool_in_use[i] = -1; - + /* Make a pool of 3n+5 primes (this is an arbitrary value). We - require at least 30 primes for are useful selection process. - + require at least 30 primes for are useful selection process. + Fixme: We need to research the best formula for sizing the pool. */ m = n * 3 + 5; @@ -443,7 +443,7 @@ prime_generate_internal (int need_q_factor, is_locked = 1; for (i = 0; i < n; i++) { - perms[i] = 1; + perms[i] = 1; /* At a maximum we use strong random for the factors. This saves us a lot of entropy. Given that Q and possible Q-factor are also used in the final prime @@ -523,12 +523,12 @@ prime_generate_internal (int need_q_factor, gcry_free (perms); perms = NULL; progress ('!'); - goto next_try; + goto next_try; } } /* Generate next prime candidate: - p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. + p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. */ mpi_set (prime, q); mpi_mul_ui (prime, prime, 2); @@ -553,7 +553,7 @@ prime_generate_internal (int need_q_factor, } else count1 = 0; - + if (nprime > pbits) { if (++count2 > 20) @@ -624,14 +624,14 @@ prime_generate_internal (int need_q_factor, factors_new[i] = mpi_copy (factors[i]); } } - + if (g) { /* Create a generator (start with 3). */ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime)); - + if (need_q_factor) err = GPG_ERR_NOT_IMPLEMENTED; else @@ -662,7 +662,7 @@ prime_generate_internal (int need_q_factor, } if (DBG_CIPHER) progress('\n'); - } + } while (i < n + 2); mpi_free (factors[n+1]); @@ -671,7 +671,7 @@ prime_generate_internal (int need_q_factor, mpi_free (pmin1); } } - + if (! DBG_CIPHER) progress ('\n'); @@ -738,19 +738,19 @@ gcry_mpi_t _gcry_generate_elg_prime (int mode, unsigned pbits, unsigned qbits, gcry_mpi_t g, gcry_mpi_t **ret_factors) { - gcry_err_code_t err = GPG_ERR_NO_ERROR; gcry_mpi_t prime = NULL; - - err = prime_generate_internal ((mode == 1), &prime, pbits, qbits, g, - ret_factors, GCRY_WEAK_RANDOM, 0, 0, - NULL, NULL); + + if (prime_generate_internal ((mode == 1), &prime, pbits, qbits, g, + ret_factors, GCRY_WEAK_RANDOM, 0, 0, + NULL, NULL)) + prime = NULL; /* (Should be NULL in the error case anyway.) */ return prime; } static gcry_mpi_t -gen_prime (unsigned int nbits, int secret, int randomlevel, +gen_prime (unsigned int nbits, int secret, int randomlevel, int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg) { gcry_mpi_t prime, ptest, pminus1, val_2, val_3, result; @@ -758,7 +758,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, unsigned int x, step; unsigned int count1, count2; int *mods; - + /* if ( DBG_CIPHER ) */ /* log_debug ("generate a prime of %u bits ", nbits ); */ @@ -777,10 +777,10 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, for (;;) { /* try forvever */ int dotcount=0; - + /* generate a random number */ gcry_mpi_randomize( prime, nbits, randomlevel ); - + /* Set high order bit to 1, set low order bit to 1. If we are generating a secret prime we are most probably doing that for RSA, to make sure that the modulus does have the @@ -789,17 +789,17 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, if (secret) mpi_set_bit (prime, nbits-2); mpi_set_bit(prime, 0); - + /* Calculate all remainders. */ for (i=0; (x = small_prime_numbers[i]); i++ ) mods[i] = mpi_fdiv_r_ui(NULL, prime, x); - + /* Now try some primes starting with prime. */ - for(step=0; step < 20000; step += 2 ) + for(step=0; step < 20000; step += 2 ) { /* Check against all the small primes we have in mods. */ count1++; - for (i=0; (x = small_prime_numbers[i]); i++ ) + for (i=0; (x = small_prime_numbers[i]); i++ ) { while ( mods[i] + step >= x ) mods[i] -= x; @@ -808,7 +808,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, } if ( x ) continue; /* Found a multiple of an already known prime. */ - + mpi_add_ui( ptest, prime, step ); /* Do a fast Fermat test now. */ @@ -816,7 +816,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, mpi_sub_ui( pminus1, ptest, 1); gcry_mpi_powm( result, val_2, pminus1, ptest ); if ( !mpi_cmp_ui( result, 1 ) ) - { + { /* Not composite, perform stronger tests */ if (is_prime(ptest, 5, &count2 )) { @@ -828,13 +828,13 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, } if (extra_check && extra_check (extra_check_arg, ptest)) - { + { /* The extra check told us that this prime is not of the caller's taste. */ progress ('/'); } else - { + { /* Got it. */ mpi_free(val_2); mpi_free(val_3); @@ -842,7 +842,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, mpi_free(pminus1); mpi_free(prime); gcry_free(mods); - return ptest; + return ptest; } } } @@ -883,7 +883,7 @@ check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds, gcry_mpi_powm( result, val_2, pminus1, prime ); mpi_free( pminus1 ); if ( mpi_cmp_ui( result, 1 ) ) - { + { /* Is composite. */ mpi_free( result ); progress('.'); @@ -924,7 +924,7 @@ is_prime (gcry_mpi_t n, int steps, unsigned int *count) unsigned nbits = mpi_get_nbits( n ); if (steps < 5) /* Make sure that we do at least 5 rounds. */ - steps = 5; + steps = 5; mpi_sub_ui( nminus1, n, 1 ); @@ -988,7 +988,7 @@ is_prime (gcry_mpi_t n, int steps, unsigned int *count) /* Given ARRAY of size N with M elements set to true produce a modified array with the next permutation of M elements. Note, that ARRAY is used in a one-bit-per-byte approach. To detected the last - permutation it is useful to intialize the array with the first M + permutation it is useful to initialize the array with the first M element set to true and use this test: m_out_of_n (array, m, n); for (i = j = 0; i < n && j < m; i++) @@ -996,7 +996,7 @@ is_prime (gcry_mpi_t n, int steps, unsigned int *count) j++; if (j == m) goto ready; - + This code is based on the algorithm 452 from the "Collected Algorithms From ACM, Volume II" by C. N. Liu and D. T. Tang. */ @@ -1010,7 +1010,7 @@ m_out_of_n ( char *array, int m, int n ) /* Need to handle this simple case separately. */ if( m == 1 ) - { + { for (i=0; i < n; i++ ) { if ( array[i] ) @@ -1060,7 +1060,7 @@ m_out_of_n ( char *array, int m, int n ) else k1 = k2 + 1; } - else + else { /* M is even. */ if( !array[n-1] ) @@ -1069,7 +1069,7 @@ m_out_of_n ( char *array, int m, int n ) k2 = k1 + 1; goto leave; } - + if( !(j1 & 1) ) { k1 = n - j1; @@ -1080,7 +1080,7 @@ m_out_of_n ( char *array, int m, int n ) } scan: jp = n - j1 - 1; - for (i=1; i <= jp; i++ ) + for (i=1; i <= jp; i++ ) { i1 = jp + 2 - i; if( array[i1-1] ) @@ -1128,7 +1128,7 @@ gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, if (!prime) return gpg_error (GPG_ERR_INV_ARG); - *prime = NULL; + *prime = NULL; if (flags & GCRY_PRIME_FLAG_SPECIAL_FACTOR) mode = 1; @@ -1156,7 +1156,7 @@ gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, mpi_free (factors_generated[i]); gcry_free (factors_generated); } - err = GPG_ERR_GENERAL; + err = GPG_ERR_GENERAL; } } @@ -1170,7 +1170,7 @@ gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, return gcry_error (err); } -/* Check wether the number X is prime. */ +/* Check whether the number X is prime. */ gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags) { @@ -1207,29 +1207,29 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, if (!factors || !r_g || !prime) return gpg_error (GPG_ERR_INV_ARG); - *r_g = NULL; + *r_g = NULL; for (n=0; factors[n]; n++) ; if (n < 2) return gpg_error (GPG_ERR_INV_ARG); - /* Extra sanity check - usually disabled. */ + /* Extra sanity check - usually disabled. */ /* mpi_set (tmp, factors[0]); */ /* for(i = 1; i < n; i++) */ /* mpi_mul (tmp, tmp, factors[i]); */ /* mpi_add_ui (tmp, tmp, 1); */ /* if (mpi_cmp (prime, tmp)) */ /* return gpg_error (GPG_ERR_INV_ARG); */ - - gcry_mpi_sub_ui (pmin1, prime, 1); - do + + gcry_mpi_sub_ui (pmin1, prime, 1); + do { if (first) first = 0; else gcry_mpi_add_ui (g, g, 1); - + if (DBG_CIPHER) { log_debug ("checking g:"); @@ -1238,7 +1238,7 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, } else progress('^'); - + for (i = 0; i < n; i++) { mpi_fdiv_q (tmp, pmin1, factors[i]); @@ -1250,13 +1250,13 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, progress('\n'); } while (i < n); - - gcry_mpi_release (tmp); - gcry_mpi_release (b); - gcry_mpi_release (pmin1); - *r_g = g; - return 0; + gcry_mpi_release (tmp); + gcry_mpi_release (b); + gcry_mpi_release (pmin1); + *r_g = g; + + return 0; } /* Convenience function to release the factors array. */ @@ -1266,7 +1266,7 @@ gcry_prime_release_factors (gcry_mpi_t *factors) if (factors) { int i; - + for (i=0; factors[i]; i++) mpi_free (factors[i]); gcry_free (factors); @@ -1279,11 +1279,11 @@ gcry_prime_release_factors (gcry_mpi_t *factors) static gcry_mpi_t find_x931_prime (const gcry_mpi_t pfirst) { - gcry_mpi_t val_2 = mpi_alloc_set_ui (2); + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); gcry_mpi_t prime; - + prime = gcry_mpi_copy (pfirst); - /* If P is even add 1. */ + /* If P is even add 1. */ mpi_set_bit (prime, 0); /* We use 64 Rabin-Miller rounds which is better and thus @@ -1299,7 +1299,7 @@ find_x931_prime (const gcry_mpi_t pfirst) } -/* Generate a prime using the algorithm from X9.31 appendix B.4. +/* Generate a prime using the algorithm from X9.31 appendix B.4. This function requires that the provided public exponent E is odd. XP, XP1 and XP2 are the seed values. All values are mandatory. @@ -1308,7 +1308,7 @@ find_x931_prime (const gcry_mpi_t pfirst) internal values P1 and P2 are saved at these addresses. On error NULL is returned. */ gcry_mpi_t -_gcry_derive_x931_prime (const gcry_mpi_t xp, +_gcry_derive_x931_prime (const gcry_mpi_t xp, const gcry_mpi_t xp1, const gcry_mpi_t xp2, const gcry_mpi_t e, gcry_mpi_t *r_p1, gcry_mpi_t *r_p2) @@ -1327,20 +1327,20 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, { gcry_mpi_t r1, tmp; - + /* r1 = (p2^{-1} mod p1)p2 - (p1^{-1} mod p2) */ tmp = mpi_alloc_like (p1); mpi_invm (tmp, p2, p1); mpi_mul (tmp, tmp, p2); r1 = tmp; - + tmp = mpi_alloc_like (p2); mpi_invm (tmp, p1, p2); mpi_mul (tmp, tmp, p1); mpi_sub (r1, r1, tmp); /* Fixup a negative value. */ - if (mpi_is_neg (r1)) + if (mpi_is_neg (r1)) mpi_add (r1, r1, p1p2); /* yp0 = xp + (r1 - xp mod p1*p2) */ @@ -1350,7 +1350,7 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, mpi_free (r1); /* Fixup a negative value. */ - if (mpi_cmp (yp0, xp) < 0 ) + if (mpi_cmp (yp0, xp) < 0 ) mpi_add (yp0, yp0, p1p2); } @@ -1378,10 +1378,10 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, */ { - gcry_mpi_t val_2 = mpi_alloc_set_ui (2); + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); gcry_mpi_t gcdtmp = mpi_alloc_like (yp0); int gcdres; - + mpi_sub_ui (p1p2, p1p2, 1); /* Adjust for loop body. */ mpi_sub_ui (yp0, yp0, 1); /* Ditto. */ for (;;) @@ -1453,7 +1453,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, ; /* No seed value given: We are asked to generate it. */ else if (!seed || seedlen < qbits/8) return GPG_ERR_INV_ARG; - + /* Allocate a buffer to later compute SEED+some_increment. */ seed_plus = gcry_malloc (seedlen < 20? 20:seedlen); if (!seed_plus) @@ -1468,7 +1468,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, value_w = gcry_mpi_new (pbits); value_x = gcry_mpi_new (pbits); - restart: + restart: /* Generate Q. */ for (;;) { @@ -1479,7 +1479,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, gcry_create_nonce (seed_help_buffer, seedlen); seed = seed_help_buffer; } - + /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits}) */ memcpy (seed_plus, seed, seedlen); for (i=seedlen-1; i >= 0; i--) @@ -1492,16 +1492,16 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); for (i=0; i < sizeof value_u; i++) value_u[i] ^= digest[i]; - + /* Step 3: Form q from U */ gcry_mpi_release (prime_q); prime_q = NULL; - ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, + ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, value_u, sizeof value_u, NULL)); if (ec) goto leave; mpi_set_highbit (prime_q, qbits-1 ); mpi_set_bit (prime_q, 0); - + /* Step 4: Test whether Q is prime using 64 round of Rabin-Miller. */ if (check_prime (prime_q, val_2, 64, NULL, NULL)) break; /* Yes, Q is prime. */ @@ -1509,7 +1509,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, /* Step 5. */ seed = NULL; /* Force a new seed at Step 1. */ } - + /* Step 6. Note that we do no use an explicit offset but increment SEED_PLUS accordingly. SEED_PLUS is currently SEED+1. */ counter = 0; @@ -1518,12 +1518,12 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, prime_p = gcry_mpi_new (pbits); for (;;) { - /* Step 7: For k = 0,...n let - V_k = sha1(seed+offset+k) mod 2^{qbits} - Step 8: W = V_0 + V_1*2^160 + - ... + /* Step 7: For k = 0,...n let + V_k = sha1(seed+offset+k) mod 2^{qbits} + Step 8: W = V_0 + V_1*2^160 + + ... + V_{n-1}*2^{(n-1)*160} - + (V_{n} mod 2^b)*2^{n*160} + + (V_{n} mod 2^b)*2^{n*160} */ mpi_set_ui (value_w, 0); for (value_k=0; value_k <= value_n; value_k++) @@ -1542,7 +1542,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, break; } gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); - + gcry_mpi_release (tmpval); tmpval = NULL; ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, digest, sizeof digest, NULL)); @@ -1631,7 +1631,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, value is stored at R_COUNTER and the seed actually used for generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm used is stored at R_HASHALGO. - + Note that this function is very similar to the fips186_2 code. Due to the minor differences, other buffer sizes and for documentarion, we use a separate function. @@ -1652,7 +1652,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gcry_mpi_t tmpval = NULL; /* Helper variable. */ int hashalgo; /* The id of the Approved Hash Function. */ int i; - + unsigned char value_u[256/8]; int value_n, value_b, value_j; int counter; @@ -1690,10 +1690,10 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, ; /* No seed value given: We are asked to generate it. */ else if (!seed || seedlen < qbits/8) return GPG_ERR_INV_ARG; - + /* Allocate a buffer to later compute SEED+some_increment and a few helper variables. */ - seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer? + seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer? sizeof seed_help_buffer : seedlen); if (!seed_plus) { @@ -1709,7 +1709,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, /* Step 4: b = L - 1 - (n * outlen) */ value_b = pbits - 1 - (value_n * qbits); - restart: + restart: /* Generate Q. */ for (;;) { @@ -1721,7 +1721,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gcry_create_nonce (seed_help_buffer, seedlen); seed = seed_help_buffer; } - + /* Step 6: U = hash(seed) */ gcry_md_hash_buffer (hashalgo, value_u, seed, seedlen); @@ -1736,12 +1736,12 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, } } gcry_mpi_release (prime_q); prime_q = NULL; - ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, + ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, value_u, sizeof value_u, NULL)); if (ec) goto leave; mpi_set_highbit (prime_q, qbits-1 ); - + /* Step 8: Test whether Q is prime using 64 round of Rabin-Miller. According to table C.1 this is sufficient for all supported prime sizes (i.e. up 3072/256). */ @@ -1751,7 +1751,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, /* Step 8. */ seed = NULL; /* Force a new seed at Step 5. */ } - + /* Step 11. Note that we do no use an explicit offset but increment SEED_PLUS accordingly. */ memcpy (seed_plus, seed, seedlen); @@ -1761,12 +1761,12 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, prime_p = gcry_mpi_new (pbits); for (;;) { - /* Step 11.1: For j = 0,...n let - V_j = hash(seed+offset+j) - Step 11.2: W = V_0 + V_1*2^outlen + - ... + /* Step 11.1: For j = 0,...n let + V_j = hash(seed+offset+j) + Step 11.2: W = V_0 + V_1*2^outlen + + ... + V_{n-1}*2^{(n-1)*outlen} - + (V_{n} mod 2^b)*2^{n*outlen} + + (V_{n} mod 2^b)*2^{n*outlen} */ mpi_set_ui (value_w, 0); for (value_j=0; value_j <= value_n; value_j++) @@ -1783,7 +1783,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, break; } gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); - + gcry_mpi_release (tmpval); tmpval = NULL; ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, digest, sizeof digest, NULL)); @@ -1813,7 +1813,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, if (mpi_get_nbits (prime_p) >= pbits-1 && check_prime (prime_p, val_2, 64, NULL, NULL) ) break; /* Yes, P is prime, continue with Step 15. */ - + /* Step 11.9: counter = counter + 1, offset = offset + n + 1. If counter >= 4L goto Step 5. */ counter++; @@ -1859,4 +1859,3 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gcry_mpi_release (val_2); return ec; } - diff --git a/grub-core/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c index 08abcbfde..910982141 100644 --- a/grub-core/lib/libgcrypt/cipher/pubkey.c +++ b/grub-core/lib/libgcrypt/cipher/pubkey.c @@ -1,6 +1,6 @@ /* pubkey.c - pubkey dispatcher - * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, - * 2007, 2008 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, + * 2007, 2008, 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -55,7 +55,7 @@ static struct pubkey_table_entry gcry_pk_spec_t *pubkey; pk_extra_spec_t *extraspec; unsigned int algorithm; - int fips_allowed; + int fips_allowed; } pubkey_table[] = { #if USE_RSA @@ -75,6 +75,8 @@ static struct pubkey_table_entry #if USE_ECC { &_gcry_pubkey_spec_ecdsa, &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 }, + { &_gcry_pubkey_spec_ecdh, + &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDH, 0 }, #endif { NULL, 0 }, }; @@ -85,7 +87,7 @@ static gcry_module_t pubkeys_registered; /* This is the lock protecting PUBKEYS_REGISTERED. */ static ath_mutex_t pubkeys_registered_lock = ATH_MUTEX_INITIALIZER;; -/* Flag to check wether the default pubkeys have already been +/* Flag to check whether the default pubkeys have already been registered. */ static int default_pubkeys_registered; @@ -197,7 +199,7 @@ pk_register_default (void) { gcry_err_code_t err = 0; int i; - + for (i = 0; (! err) && pubkey_table[i].pubkey; i++) { #define pubkey_use_dummy(func) \ @@ -215,8 +217,8 @@ pk_register_default (void) err = _gcry_module_add (&pubkeys_registered, pubkey_table[i].algorithm, - (void *) pubkey_table[i].pubkey, - (void *) pubkey_table[i].extraspec, + (void *) pubkey_table[i].pubkey, + (void *) pubkey_table[i].extraspec, NULL); } @@ -240,7 +242,7 @@ gcry_pk_lookup_func_name (void *spec, void *data) } /* Internal function. Lookup a pubkey entry by it's name. */ -static gcry_module_t +static gcry_module_t gcry_pk_lookup_name (const char *name) { gcry_module_t pubkey; @@ -269,8 +271,8 @@ _gcry_pk_register (gcry_pk_spec_t *pubkey, ath_mutex_lock (&pubkeys_registered_lock); err = _gcry_module_add (&pubkeys_registered, 0, - (void *) pubkey, - (void *)(extraspec? extraspec : &dummy_extra_spec), + (void *) pubkey, + (void *)(extraspec? extraspec : &dummy_extra_spec), &mod); ath_mutex_unlock (&pubkeys_registered_lock); @@ -559,13 +561,13 @@ pubkey_generate (int algorithm, if (extraspec && extraspec->ext_generate) { /* Use the extended generate function. */ - ec = extraspec->ext_generate + ec = extraspec->ext_generate (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo); } else { /* Use the standard generate function. */ - ec = ((gcry_pk_spec_t *) pubkey->spec)->generate + ec = ((gcry_pk_spec_t *) pubkey->spec)->generate (algorithm, nbits, use_e, skey, retfactors); } _gcry_module_release (pubkey); @@ -615,7 +617,7 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as an extra failsafe protection we explicitly test for fips mode - here. */ + here. */ if (DBG_CIPHER && !fips_mode ()) { log_debug ("pubkey_encrypt: algo=%d\n", algorithm); @@ -684,7 +686,7 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, } rc = GPG_ERR_PUBKEY_ALGO; - + ready: ath_mutex_unlock (&pubkeys_registered_lock); @@ -758,10 +760,10 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, { log_debug ("pubkey_verify: algo=%d\n", algorithm); for (i = 0; i < pubkey_get_npkey (algorithm); i++) - log_mpidump (" pkey:", pkey[i]); + log_mpidump (" pkey", pkey[i]); for (i = 0; i < pubkey_get_nsig (algorithm); i++) - log_mpidump (" sig:", data[i]); - log_mpidump (" hash:", hash); + log_mpidump (" sig", data[i]); + log_mpidump (" hash", hash); } ath_mutex_lock (&pubkeys_registered_lock); @@ -782,6 +784,1018 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, } +/* Turn VALUE into an octet string and store it in an allocated buffer + at R_FRAME or - if R_RAME is NULL - copy it into the caller + provided buffer SPACE; either SPACE or R_FRAME may be used. If + SPACE if not NULL, the caller must provide a buffer of at least + NBYTES. If the resulting octet string is shorter than NBYTES pad + it to the left with zeroes. If VALUE does not fit into NBYTES + return an error code. */ +static gpg_err_code_t +octet_string_from_mpi (unsigned char **r_frame, void *space, + gcry_mpi_t value, size_t nbytes) +{ + gpg_err_code_t rc; + size_t nframe, noff, n; + unsigned char *frame; + + if (!r_frame == !space) + return GPG_ERR_INV_ARG; /* Only one may be used. */ + + if (r_frame) + *r_frame = NULL; + + rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, + NULL, 0, &nframe, value)); + if (rc) + return rc; + if (nframe > nbytes) + return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */ + + noff = (nframe < nbytes)? nbytes - nframe : 0; + n = nframe + noff; + if (space) + frame = space; + else + { + frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n); + if (!frame) + { + rc = gpg_err_code_from_syserror (); + return rc; + } + } + if (noff) + memset (frame, 0, noff); + nframe += noff; + rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, + frame+noff, nframe-noff, NULL, value)); + if (rc) + { + gcry_free (frame); + return rc; + } + + if (r_frame) + *r_frame = frame; + return 0; +} + + +/* Encode {VALUE,VALUELEN} for an NBITS keys using the pkcs#1 block + type 2 padding. On sucess the result is stored as a new MPI at + R_RESULT. On error the value at R_RESULT is undefined. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the seed instead of using a random string for it. This feature is + only useful for regression tests. Note that this value may not + contain zero bytes. + + We encode the value in this way: + + 0 2 RND(n bytes) 0 VALUE + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 2 is the block type. + RND are non-zero random bytes. + + (Note that OpenPGP includes the cipher algorithm and a checksum in + VALUE; the caller needs to prepare the value accordingly.) + */ +static gcry_err_code_t +pkcs1_encode_for_encryption (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen, + const unsigned char *random_override, + size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + unsigned char *p; + + if (valuelen + 7 > nframe || !nframe) + { + /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ + return GPG_ERR_TOO_SHORT; /* The key is too short. */ + } + + if ( !(frame = gcry_malloc_secure (nframe))) + return gpg_err_code_from_syserror (); + + n = 0; + frame[n++] = 0; + frame[n++] = 2; /* block type */ + i = nframe - 3 - valuelen; + gcry_assert (i > 0); + + if (random_override) + { + int j; + + if (random_override_len != i) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + /* Check that random does not include a zero byte. */ + for (j=0; j < random_override_len; j++) + if (!random_override[j]) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + memcpy (frame + n, random_override, random_override_len); + n += random_override_len; + } + else + { + p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); + /* Replace zero bytes by new values. */ + for (;;) + { + int j, k; + unsigned char *pp; + + /* Count the zero bytes. */ + for (j=k=0; j < i; j++) + { + if (!p[j]) + k++; + } + if (!k) + break; /* Okay: no (more) zero bytes. */ + + k += k/128 + 3; /* Better get some more. */ + pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); + for (j=0; j < i && k; ) + { + if (!p[j]) + p[j] = pp[--k]; + if (p[j]) + j++; + } + gcry_free (pp); + } + memcpy (frame+n, p, i); + n += i; + gcry_free (p); + } + + frame[n++] = 0; + memcpy (frame+n, value, valuelen); + n += valuelen; + gcry_assert (n == nframe); + + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 2 encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding. + NBITS is the size of the secret key. On success the result is + stored as a newly allocated buffer at R_RESULT and its valid length at + R_RESULTLEN. On error NULL is stored at R_RESULT. */ +static gcry_err_code_t +pkcs1_decode_for_encryption (unsigned char **r_result, size_t *r_resultlen, + unsigned int nbits, gcry_mpi_t value) +{ + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + size_t n; + + *r_result = NULL; + + if ( !(frame = gcry_malloc_secure (nframe))) + return gpg_err_code_from_syserror (); + + err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &n, value); + if (err) + { + gcry_free (frame); + return gcry_err_code (err); + } + + nframe = n; /* Set NFRAME to the actual length. */ + + /* FRAME = 0x00 || 0x02 || PS || 0x00 || M + + pkcs#1 requires that the first byte is zero. Our MPIs usually + strip leading zero bytes; thus we are not able to detect them. + However due to the way gcry_mpi_print is implemented we may see + leading zero bytes nevertheless. We handle this by making the + first zero byte optional. */ + if (nframe < 4) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* Too short. */ + } + n = 0; + if (!frame[0]) + n++; + if (frame[n++] != 0x02) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* Wrong block type. */ + } + + /* Skip the non-zero random bytes and the terminating zero byte. */ + for (; n < nframe && frame[n] != 0x00; n++) + ; + if (n+1 >= nframe) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* No zero byte. */ + } + n++; /* Skip the zero byte. */ + + /* To avoid an extra allocation we reuse the frame buffer. The only + caller of this function will anyway free the result soon. */ + memmove (frame, frame + n, nframe - n); + *r_result = frame; + *r_resultlen = nframe - n; + + if (DBG_CIPHER) + log_printhex ("value extracted from PKCS#1 block type 2 encoded data:", + *r_result, *r_resultlen); + + return 0; +} + + +/* Encode {VALUE,VALUELEN} for an NBITS keys and hash algorith ALGO + using the pkcs#1 block type 1 padding. On success the result is + stored as a new MPI at R_RESULT. On error the value at R_RESULT is + undefined. + + We encode the value in this way: + + 0 1 PAD(n bytes) 0 ASN(asnlen bytes) VALUE(valuelen bytes) + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 1 is the block type. + PAD consists of 0xff bytes. + 0 marks the end of the padding. + ASN is the DER encoding of the hash algorithm; along with the VALUE + it yields a valid DER encoding. + + (Note that PGP prior to version 2.3 encoded the message digest as: + 0 1 MD(16 bytes) 0 PAD(n bytes) 1 + The MD is always 16 bytes here because it's always MD5. GnuPG + does not not support pre-v2.3 signatures, but I'm including this + comment so the information is easily found if needed.) +*/ +static gcry_err_code_t +pkcs1_encode_for_signature (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen, + int algo) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + byte asn[100]; + byte *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + size_t asnlen, dlen; + + asnlen = DIM(asn); + dlen = gcry_md_get_algo_dlen (algo); + + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + /* We don't have yet all of the above algorithms. */ + return GPG_ERR_NOT_IMPLEMENTED; + } + + if ( valuelen != dlen ) + { + /* Hash value does not match the length of digest for + the given algorithm. */ + return GPG_ERR_CONFLICT; + } + + if ( !dlen || dlen + asnlen + 4 > nframe) + { + /* Can't encode an DLEN byte digest MD into an NFRAME byte + frame. */ + return GPG_ERR_TOO_SHORT; + } + + if ( !(frame = gcry_malloc (nframe)) ) + return gpg_err_code_from_syserror (); + + /* Assemble the pkcs#1 block type 1. */ + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - valuelen - asnlen - 3 ; + gcry_assert (i > 1); + memset (frame+n, 0xff, i ); + n += i; + frame[n++] = 0; + memcpy (frame+n, asn, asnlen); + n += asnlen; + memcpy (frame+n, value, valuelen ); + n += valuelen; + gcry_assert (n == nframe); + + /* Convert it into an MPI. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 1 encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* Mask generation function for OAEP. See RFC-3447 B.2.1. */ +static gcry_err_code_t +mgf1 (unsigned char *output, size_t outlen, unsigned char *seed, size_t seedlen, + int algo) +{ + size_t dlen, nbytes, n; + int idx; + gcry_md_hd_t hd; + gcry_error_t err; + + err = gcry_md_open (&hd, algo, 0); + if (err) + return gpg_err_code (err); + + dlen = gcry_md_get_algo_dlen (algo); + + /* We skip step 1 which would be assert(OUTLEN <= 2^32). The loop + in step 3 is merged with step 4 by concatenating no more octets + than what would fit into OUTPUT. The ceiling for the counter IDX + is implemented indirectly. */ + nbytes = 0; /* Step 2. */ + idx = 0; + while ( nbytes < outlen ) + { + unsigned char c[4], *digest; + + if (idx) + gcry_md_reset (hd); + + c[0] = (idx >> 24) & 0xFF; + c[1] = (idx >> 16) & 0xFF; + c[2] = (idx >> 8) & 0xFF; + c[3] = idx & 0xFF; + idx++; + + gcry_md_write (hd, seed, seedlen); + gcry_md_write (hd, c, 4); + digest = gcry_md_read (hd, 0); + + n = (outlen - nbytes < dlen)? (outlen - nbytes) : dlen; + memcpy (output+nbytes, digest, n); + nbytes += n; + } + + gcry_md_close (hd); + return GPG_ERR_NO_ERROR; +} + + +/* RFC-3447 (pkcs#1 v2.1) OAEP encoding. NBITS is the length of the + key measured in bits. ALGO is the hash function; it must be a + valid and usable algorithm. {VALUE,VALUELEN} is the message to + encrypt. {LABEL,LABELLEN} is the optional label to be associated + with the message, if LABEL is NULL the default is to use the empty + string as label. On success the encoded ciphertext is returned at + R_RESULT. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the seed instead of using a random string for it. This feature is + only useful for regression tests. + + Here is figure 1 from the RFC depicting the process: + + +----------+---------+-------+ + DB = | lHash | PS | M | + +----------+---------+-------+ + | + +----------+ V + | seed |--> MGF ---> xor + +----------+ | + | | + +--+ V | + |00| xor <----- MGF <-----| + +--+ | | + | | | + V V V + +--+----------+----------------------------+ + EM = |00|maskedSeed| maskedDB | + +--+----------+----------------------------+ + */ +static gcry_err_code_t +oaep_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + const unsigned char *value, size_t valuelen, + const unsigned char *label, size_t labellen, + const void *random_override, size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + unsigned char *p; + size_t hlen; + size_t n; + + *r_result = NULL; + + /* Set defaults for LABEL. */ + if (!label || !labellen) + { + label = (const unsigned char*)""; + labellen = 0; + } + + hlen = gcry_md_get_algo_dlen (algo); + + /* We skip step 1a which would be to check that LABELLEN is not + greater than 2^61-1. See rfc-3447 7.1.1. */ + + /* Step 1b. Note that the obsolete rfc-2437 uses the check: + valuelen > nframe - 2 * hlen - 1 . */ + if (valuelen > nframe - 2 * hlen - 2 || !nframe) + { + /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ + return GPG_ERR_TOO_SHORT; /* The key is too short. */ + } + + /* Allocate the frame. */ + frame = gcry_calloc_secure (1, nframe); + if (!frame) + return gpg_err_code_from_syserror (); + + /* Step 2a: Compute the hash of the label. We store it in the frame + where later the maskedDB will commence. */ + gcry_md_hash_buffer (algo, frame + 1 + hlen, label, labellen); + + /* Step 2b: Set octet string to zero. */ + /* This has already been done while allocating FRAME. */ + + /* Step 2c: Create DB by concatenating lHash, PS, 0x01 and M. */ + n = nframe - valuelen - 1; + frame[n] = 0x01; + memcpy (frame + n + 1, value, valuelen); + + /* Step 3d: Generate seed. We store it where the maskedSeed will go + later. */ + if (random_override) + { + if (random_override_len != hlen) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + memcpy (frame + 1, random_override, hlen); + } + else + gcry_randomize (frame + 1, hlen, GCRY_STRONG_RANDOM); + + /* Step 2e and 2f: Create maskedDB. */ + { + unsigned char *dmask; + + dmask = gcry_malloc_secure (nframe - hlen - 1); + if (!dmask) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + return rc; + } + rc = mgf1 (dmask, nframe - hlen - 1, frame+1, hlen, algo); + if (rc) + { + gcry_free (dmask); + gcry_free (frame); + return rc; + } + for (n = 1 + hlen, p = dmask; n < nframe; n++) + frame[n] ^= *p++; + gcry_free (dmask); + } + + /* Step 2g and 2h: Create maskedSeed. */ + { + unsigned char *smask; + + smask = gcry_malloc_secure (hlen); + if (!smask) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + return rc; + } + rc = mgf1 (smask, hlen, frame + 1 + hlen, nframe - hlen - 1, algo); + if (rc) + { + gcry_free (smask); + gcry_free (frame); + return rc; + } + for (n = 1, p = smask; n < 1 + hlen; n++) + frame[n] ^= *p++; + gcry_free (smask); + } + + /* Step 2i: Concatenate 0x00, maskedSeed and maskedDB. */ + /* This has already been done by using in-place operations. */ + + /* Convert the stuff into an MPI as expected by the caller. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, nframe, NULL); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("OAEP encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* RFC-3447 (pkcs#1 v2.1) OAEP decoding. NBITS is the length of the + key measured in bits. ALGO is the hash function; it must be a + valid and usable algorithm. VALUE is the raw decrypted message + {LABEL,LABELLEN} is the optional label to be associated with the + message, if LABEL is NULL the default is to use the empty string as + label. On success the plaintext is returned as a newly allocated + buffer at R_RESULT; its valid length is stored at R_RESULTLEN. On + error NULL is stored at R_RESULT. */ +static gcry_err_code_t +oaep_decode (unsigned char **r_result, size_t *r_resultlen, + unsigned int nbits, int algo, + gcry_mpi_t value, const unsigned char *label, size_t labellen) +{ + gcry_err_code_t rc; + unsigned char *frame = NULL; /* Encoded messages (EM). */ + unsigned char *masked_seed; /* Points into FRAME. */ + unsigned char *masked_db; /* Points into FRAME. */ + unsigned char *seed = NULL; /* Allocated space for the seed and DB. */ + unsigned char *db; /* Points into SEED. */ + unsigned char *lhash = NULL; /* Hash of the label. */ + size_t nframe; /* Length of the ciphertext (EM). */ + size_t hlen; /* Length of the hash digest. */ + size_t db_len; /* Length of DB and masked_db. */ + size_t nkey = (nbits+7)/8; /* Length of the key in bytes. */ + int failed = 0; /* Error indicator. */ + size_t n; + + *r_result = NULL; + + /* This code is implemented as described by rfc-3447 7.1.2. */ + + /* Set defaults for LABEL. */ + if (!label || !labellen) + { + label = (const unsigned char*)""; + labellen = 0; + } + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + + /* Hash the label right away. */ + lhash = gcry_malloc (hlen); + if (!lhash) + return gpg_err_code_from_syserror (); + gcry_md_hash_buffer (algo, lhash, label, labellen); + + /* Turn the MPI into an octet string. If the octet string is + shorter than the key we pad it to the left with zeroes. This may + happen due to the leading zero in OAEP frames and due to the + following random octets (seed^mask) which may have leading zero + bytes. This all is needed to cope with our leading zeroes + suppressing MPI implementation. The code implictly implements + Step 1b (bail out if NFRAME != N). */ + rc = octet_string_from_mpi (&frame, NULL, value, nkey); + if (rc) + { + gcry_free (lhash); + return GPG_ERR_ENCODING_PROBLEM; + } + nframe = nkey; + + /* Step 1c: Check that the key is long enough. */ + if ( nframe < 2 * hlen + 2 ) + { + gcry_free (frame); + gcry_free (lhash); + return GPG_ERR_ENCODING_PROBLEM; + } + + /* Step 2 has already been done by the caller and the + gcry_mpi_aprint above. */ + + /* Allocate space for SEED and DB. */ + seed = gcry_malloc_secure (nframe - 1); + if (!seed) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + gcry_free (lhash); + return rc; + } + db = seed + hlen; + + /* To avoid choosen ciphertext attacks from now on we make sure to + run all code even in the error case; this avoids possible timing + attacks as described by Manger. */ + + /* Step 3a: Hash the label. */ + /* This has already been done. */ + + /* Step 3b: Separate the encoded message. */ + masked_seed = frame + 1; + masked_db = frame + 1 + hlen; + db_len = nframe - 1 - hlen; + + /* Step 3c and 3d: seed = maskedSeed ^ mgf(maskedDB, hlen). */ + if (mgf1 (seed, hlen, masked_db, db_len, algo)) + failed = 1; + for (n = 0; n < hlen; n++) + seed[n] ^= masked_seed[n]; + + /* Step 3e and 3f: db = maskedDB ^ mgf(seed, db_len). */ + if (mgf1 (db, db_len, seed, hlen, algo)) + failed = 1; + for (n = 0; n < db_len; n++) + db[n] ^= masked_db[n]; + + /* Step 3g: Check lhash, an possible empty padding string terminated + by 0x01 and the first byte of EM being 0. */ + if (memcmp (lhash, db, hlen)) + failed = 1; + for (n = hlen; n < db_len; n++) + if (db[n] == 0x01) + break; + if (n == db_len) + failed = 1; + if (frame[0]) + failed = 1; + + gcry_free (lhash); + gcry_free (frame); + if (failed) + { + gcry_free (seed); + return GPG_ERR_ENCODING_PROBLEM; + } + + /* Step 4: Output M. */ + /* To avoid an extra allocation we reuse the seed buffer. The only + caller of this function will anyway free the result soon. */ + n++; + memmove (seed, db + n, db_len - n); + *r_result = seed; + *r_resultlen = db_len - n; + seed = NULL; + + if (DBG_CIPHER) + log_printhex ("value extracted from OAEP encoded data:", + *r_result, *r_resultlen); + + return 0; +} + + +/* RFC-3447 (pkcs#1 v2.1) PSS encoding. Encode {VALUE,VALUELEN} for + an NBITS key. Note that VALUE is already the mHash from the + picture below. ALGO is a valid hash algorithm and SALTLEN is the + length of salt to be used. On success the result is stored as a + new MPI at R_RESULT. On error the value at R_RESULT is undefined. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the salt instead of using a random string for the salt. This + feature is only useful for regression tests. + + Here is figure 2 from the RFC (errata 595 applied) depicting the + process: + + +-----------+ + | M | + +-----------+ + | + V + Hash + | + V + +--------+----------+----------+ + M' = |Padding1| mHash | salt | + +--------+----------+----------+ + | + +--------+----------+ V + DB = |Padding2| salt | Hash + +--------+----------+ | + | | + V | +----+ + xor <--- MGF <---| |0xbc| + | | +----+ + | | | + V V V + +-------------------+----------+----+ + EM = | maskedDB | H |0xbc| + +-------------------+----------+----+ + + */ +static gcry_err_code_t +pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + const unsigned char *value, size_t valuelen, int saltlen, + const void *random_override, size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + size_t hlen; /* Length of the hash digest. */ + unsigned char *em = NULL; /* Encoded message. */ + size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */ + unsigned char *h; /* Points into EM. */ + unsigned char *buf = NULL; /* Help buffer. */ + size_t buflen; /* Length of BUF. */ + unsigned char *mhash; /* Points into BUF. */ + unsigned char *salt; /* Points into BUF. */ + unsigned char *dbmask; /* Points into BUF. */ + unsigned char *p; + size_t n; + + /* This code is implemented as described by rfc-3447 9.1.1. */ + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + + /* Allocate a help buffer and setup some pointers. */ + buflen = 8 + hlen + saltlen + (emlen - hlen - 1); + buf = gcry_malloc (buflen); + if (!buf) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + mhash = buf + 8; + salt = mhash + hlen; + dbmask= salt + saltlen; + + /* Step 2: That would be: mHash = Hash(M) but our input is already + mHash thus we do only a consistency check and copy to MHASH. */ + if (valuelen != hlen) + { + rc = GPG_ERR_INV_LENGTH; + goto leave; + } + memcpy (mhash, value, hlen); + + /* Step 3: Check length constraints. */ + if (emlen < hlen + saltlen + 2) + { + rc = GPG_ERR_TOO_SHORT; + goto leave; + } + + /* Allocate space for EM. */ + em = gcry_malloc (emlen); + if (!em) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + h = em + emlen - 1 - hlen; + + /* Step 4: Create a salt. */ + if (saltlen) + { + if (random_override) + { + if (random_override_len != saltlen) + { + rc = GPG_ERR_INV_ARG; + goto leave; + } + memcpy (salt, random_override, saltlen); + } + else + gcry_randomize (salt, saltlen, GCRY_STRONG_RANDOM); + } + + /* Step 5 and 6: M' = Hash(Padding1 || mHash || salt). */ + memset (buf, 0, 8); /* Padding. */ + gcry_md_hash_buffer (algo, h, buf, 8 + hlen + saltlen); + + /* Step 7 and 8: DB = PS || 0x01 || salt. */ + /* Note that we use EM to store DB and later Xor in-place. */ + p = em + emlen - 1 - hlen - saltlen - 1; + memset (em, 0, p - em); + *p++ = 0x01; + memcpy (p, salt, saltlen); + + /* Step 9: dbmask = MGF(H, emlen - hlen - 1). */ + mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo); + + /* Step 10: maskedDB = DB ^ dbMask */ + for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++) + em[n] ^= *p; + + /* Step 11: Set the leftmost bits to zero. */ + em[0] &= 0xFF >> (8 * emlen - nbits); + + /* Step 12: EM = maskedDB || H || 0xbc. */ + em[emlen-1] = 0xbc; + + /* Convert EM into an MPI. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, em, emlen, NULL); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PSS encoded data", *r_result); + + leave: + if (em) + { + wipememory (em, emlen); + gcry_free (em); + } + if (buf) + { + wipememory (buf, buflen); + gcry_free (buf); + } + return rc; +} + + +/* Verify a signature assuming PSS padding. VALUE is the hash of the + message (mHash) encoded as an MPI; its length must match the digest + length of ALGO. ENCODED is the output of the RSA public key + function (EM). NBITS is the size of the public key. ALGO is the + hash algorithm and SALTLEN is the length of the used salt. The + function returns 0 on success or on error code. */ +static gcry_err_code_t +pss_verify (gcry_mpi_t value, gcry_mpi_t encoded, unsigned int nbits, int algo, + size_t saltlen) +{ + gcry_err_code_t rc = 0; + size_t hlen; /* Length of the hash digest. */ + unsigned char *em = NULL; /* Encoded message. */ + size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */ + unsigned char *salt; /* Points into EM. */ + unsigned char *h; /* Points into EM. */ + unsigned char *buf = NULL; /* Help buffer. */ + size_t buflen; /* Length of BUF. */ + unsigned char *dbmask; /* Points into BUF. */ + unsigned char *mhash; /* Points into BUF. */ + unsigned char *p; + size_t n; + + /* This code is implemented as described by rfc-3447 9.1.2. */ + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + + /* Allocate a help buffer and setup some pointers. + This buffer is used for two purposes: + +------------------------------+-------+ + 1. | dbmask | mHash | + +------------------------------+-------+ + emlen - hlen - 1 hlen + + +----------+-------+---------+-+-------+ + 2. | padding1 | mHash | salt | | mHash | + +----------+-------+---------+-+-------+ + 8 hlen saltlen hlen + */ + buflen = 8 + hlen + saltlen; + if (buflen < emlen - hlen - 1) + buflen = emlen - hlen - 1; + buflen += hlen; + buf = gcry_malloc (buflen); + if (!buf) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + dbmask = buf; + mhash = buf + buflen - hlen; + + /* Step 2: That would be: mHash = Hash(M) but our input is already + mHash thus we only need to convert VALUE into MHASH. */ + rc = octet_string_from_mpi (NULL, mhash, value, hlen); + if (rc) + goto leave; + + /* Convert the signature into an octet string. */ + rc = octet_string_from_mpi (&em, NULL, encoded, emlen); + if (rc) + goto leave; + + /* Step 3: Check length of EM. Because we internally use MPI + functions we can't do this properly; EMLEN is always the length + of the key because octet_string_from_mpi needs to left pad the + result with zero to cope with the fact that our MPIs suppress all + leading zeroes. Thus what we test here are merely the digest and + salt lengths to the key. */ + if (emlen < hlen + saltlen + 2) + { + rc = GPG_ERR_TOO_SHORT; /* For the hash and saltlen. */ + goto leave; + } + + /* Step 4: Check last octet. */ + if (em[emlen - 1] != 0xbc) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 5: Split EM. */ + h = em + emlen - 1 - hlen; + + /* Step 6: Check the leftmost bits. */ + if ((em[0] & ~(0xFF >> (8 * emlen - nbits)))) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 7: dbmask = MGF(H, emlen - hlen - 1). */ + mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo); + + /* Step 8: maskedDB = DB ^ dbMask. */ + for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++) + em[n] ^= *p; + + /* Step 9: Set leftmost bits in DB to zero. */ + em[0] &= 0xFF >> (8 * emlen - nbits); + + /* Step 10: Check the padding of DB. */ + for (n = 0; n < emlen - hlen - saltlen - 2 && !em[n]; n++) + ; + if (n != emlen - hlen - saltlen - 2 || em[n++] != 1) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 11: Extract salt from DB. */ + salt = em + n; + + /* Step 12: M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */ + memset (buf, 0, 8); + memcpy (buf+8, mhash, hlen); + memcpy (buf+8+hlen, salt, saltlen); + + /* Step 13: H' = Hash(M'). */ + gcry_md_hash_buffer (algo, buf, buf, 8 + hlen + saltlen); + + /* Step 14: Check H == H'. */ + rc = memcmp (h, buf, hlen) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR; + + leave: + if (em) + { + wipememory (em, emlen); + gcry_free (em); + } + if (buf) + { + wipememory (buf, buflen); + gcry_free (buf); + } + return rc; +} + + +/* Callback for the pubkey algorithm code to verify PSS signatures. + OPAQUE is the data provided by the actual caller. The meaning of + TMP depends on the actual algorithm (but there is only RSA); now + for RSA it is the output of running the public key function on the + input. */ +static int +pss_verify_cmp (void *opaque, gcry_mpi_t tmp) +{ + struct pk_encoding_ctx *ctx = opaque; + gcry_mpi_t hash = ctx->verify_arg; + + return pss_verify (hash, tmp, ctx->nbits - 1, ctx->hash_algo, ctx->saltlen); +} + + /* Internal function. */ static gcry_err_code_t sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, @@ -855,7 +1869,11 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, /* Clear the array for easier error cleanup. */ for (name = element_names, idx = 0; *name; name++, idx++) elements[idx] = NULL; - gcry_assert (idx >= 6); /* We know that ECC has at least 6 elements. */ + gcry_assert (idx >= 5); /* We know that ECC has at least 5 elements + (params only) or 6 (full public key). */ + if (idx == 5) + elements[5] = NULL; /* Extra clear for the params only case. */ + /* Init the array with the available curve parameters. */ for (name = element_names, idx = 0; *name && !err; name++, idx++) @@ -884,23 +1902,23 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, { char *curve; gcry_mpi_t params[6]; - + for (idx = 0; idx < DIM(params); idx++) params[idx] = NULL; - + curve = _gcry_sexp_nth_string (list, 1); gcry_sexp_release (list); if (!curve) { /* No curve name given (or out of core). */ - err = GPG_ERR_INV_OBJ; + err = GPG_ERR_INV_OBJ; goto leave; } err = extraspec->get_param (curve, params); gcry_free (curve); if (err) goto leave; - + for (idx = 0; idx < DIM(params); idx++) { if (!elements[idx]) @@ -924,7 +1942,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, err = GPG_ERR_NO_OBJ; goto leave; } - + leave: if (err) { @@ -948,6 +1966,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * openpgp-elg * openpgp-elg-sig * ecdsa + * ecdh * Provide a SE with the first element be either "private-key" or * or "public-key". It is followed by a list with its first element * be one of the above algorithm identifiers and the remaning @@ -955,6 +1974,10 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * NOTE: we look through the list to find a list beginning with * "private-key" or "public-key" - the first one found is used. * + * If OVERRIDE_ELEMS is not NULL those elems override the parameter + * specification taken from the module. This ise used by + * gcry_pk_get_curve. + * * Returns: A pointer to an allocated array of MPIs if the return value is * zero; the caller has to release this array. * @@ -970,8 +1993,8 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * The are expected to be in GCRYMPI_FMT_USG */ static gcry_err_code_t -sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, - gcry_module_t *retalgo) +sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, + gcry_mpi_t **retarray, gcry_module_t *retalgo) { gcry_err_code_t err = 0; gcry_sexp_t list, l2; @@ -984,7 +2007,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, int is_ecc; /* Check that the first element is valid. */ - list = gcry_sexp_find_token (sexp, + list = gcry_sexp_find_token (sexp, want_private? "private-key":"public-key", 0); if (!list) return GPG_ERR_INV_OBJ; /* Does not contain a key object. */ @@ -1002,16 +2025,18 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pk_lookup_name (name); ath_mutex_unlock (&pubkeys_registered_lock); - + /* Fixme: We should make sure that an ECC key is always named "ecc" and not "ecdsa". "ecdsa" should be used for the signature itself. We need a function to test whether an algorithm given with a key is compatible with an application of the key (signing, encryption). For RSA this is easy, but ECC is the first - algorithm which has many flavours. */ - is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); + algorithm which has many flavours. */ + is_ecc = ( !strcmp (name, "ecdsa") + || !strcmp (name, "ecdh") + || !strcmp (name, "ecc") ); gcry_free (name); - + if (!module) { gcry_sexp_release (list); @@ -1023,10 +2048,15 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, extraspec = module->extraspec; } - elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey; + if (override_elems) + elems = override_elems; + else if (want_private) + elems = pubkey->elements_skey; + else + elems = pubkey->elements_pkey; array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); if (!array) - err = gpg_err_code_from_errno (errno); + err = gpg_err_code_from_syserror (); if (!err) { if (is_ecc) @@ -1034,9 +2064,9 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, else err = sexp_elements_extract (list, elems, array, pubkey->name); } - + gcry_sexp_release (list); - + if (err) { gcry_free (array); @@ -1050,7 +2080,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, *retarray = array; *retalgo = module; } - + return err; } @@ -1066,7 +2096,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_mpi_t *array; gcry_module_t module; gcry_pk_spec_t *pubkey; - + /* Check that the first element is valid. */ list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); if (!list) @@ -1085,7 +2115,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_sexp_release (l2); return GPG_ERR_INV_OBJ; /* Invalid structure of object. */ } - else if (!strcmp (name, "flags")) + else if (!strcmp (name, "flags")) { /* Skip flags, since they are not used but here just for the sake of consistent S-expressions. */ @@ -1099,7 +2129,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, } name = _gcry_sexp_nth_string (l2, 0); } - + ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pk_lookup_name (name); ath_mutex_unlock (&pubkeys_registered_lock); @@ -1118,7 +2148,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, elems = pubkey->elements_sig; array = gcry_calloc (strlen (elems) + 1 , sizeof *array ); if (!array) - err = gpg_err_code_from_errno (errno); + err = gpg_err_code_from_syserror (); if (!err) err = sexp_elements_extract (list, elems, array, NULL); @@ -1131,7 +2161,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, ath_mutex_lock (&pubkeys_registered_lock); _gcry_module_release (module); ath_mutex_unlock (&pubkeys_registered_lock); - + gcry_free (array); } else @@ -1139,26 +2169,82 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, *retarray = array; *retalgo = module; } - + return err; } +static inline int +get_hash_algo (const char *s, size_t n) +{ + static const struct { const char *name; int algo; } hashnames[] = { + { "sha1", GCRY_MD_SHA1 }, + { "md5", GCRY_MD_MD5 }, + { "sha256", GCRY_MD_SHA256 }, + { "ripemd160", GCRY_MD_RMD160 }, + { "rmd160", GCRY_MD_RMD160 }, + { "sha384", GCRY_MD_SHA384 }, + { "sha512", GCRY_MD_SHA512 }, + { "sha224", GCRY_MD_SHA224 }, + { "md2", GCRY_MD_MD2 }, + { "md4", GCRY_MD_MD4 }, + { "tiger", GCRY_MD_TIGER }, + { "haval", GCRY_MD_HAVAL }, + { NULL, 0 } + }; + int algo; + int i; + + for (i=0; hashnames[i].name; i++) + { + if ( strlen (hashnames[i].name) == n + && !memcmp (hashnames[i].name, s, n)) + break; + } + if (hashnames[i].name) + algo = hashnames[i].algo; + else + { + /* In case of not listed or dynamically allocated hash + algorithm we fall back to this somewhat slower + method. Further, it also allows to use OIDs as + algorithm names. */ + char *tmpname; + + tmpname = gcry_malloc (n+1); + if (!tmpname) + algo = 0; /* Out of core - silently give up. */ + else + { + memcpy (tmpname, s, n); + tmpname[n] = 0; + algo = gcry_md_map_name (tmpname); + gcry_free (tmpname); + } + } + return algo; +} + /**************** * Take sexp and return an array of MPI as used for our internal decrypt * function. * s_data = (enc-val - * [(flags [pkcs1])] + * [(flags [raw, pkcs1, oaep, no-blinding])] + * [(hash-algo )] + * [(label